From 0fdeae4e778344a9e2552774d6acef3cf5fec682 Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Sat, 3 May 2014 06:05:28 -0700 Subject: [PATCH] Consolidate dimension-check code into QR.post. Reduces redundant generation of video/image elements for thumbnail generation and dimension check code by merging them into one routine --- builds/4chan-X.user.js | 149 ++++++++++++++----------------------- builds/crx/script.js | 142 ++++++++++++++--------------------- src/General/Main.coffee | 2 +- src/Posting/QR.coffee | 60 --------------- src/Posting/QR.post.coffee | 51 ++++++++++--- 5 files changed, 154 insertions(+), 250 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 0a075551f..b1e4ae6e5 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -6378,7 +6378,7 @@ } }, handleFile: function(file, index, nfiles) { - var isNewPost, isSingle, max, post, _ref; + var isSingle, max, post, _ref; isSingle = nfiles === 1; if (/^text\//.test(file.type)) { if (isSingle) { @@ -6405,93 +6405,15 @@ return; } } - isNewPost = false; if (isSingle) { post = QR.selected; } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { - isNewPost = true; post = new QR.post(); } if (/^text/.test(file.type)) { return post.pasteText(file); } else { - post.setFile(file); - } - return QR.checkDimensions(file, function(pass) { - if (pass || isSingle) { - return post.setFile(file); - } else if (isNewPost) { - return post.rm(); - } - }); - }, - checkDimensions: function(file, cb) { - var img, video; - if (/^image\//.test(file.type)) { - img = new Image(); - img.onload = function() { - var height, pass, width; - height = img.height, width = img.width; - pass = true; - if (height > QR.max_height || width > QR.max_width) { - QR.error("" + file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - pass = false; - } - if (height < QR.min_height || width < QR.min_width) { - QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - pass = false; - } - return cb(pass); - }; - return img.src = URL.createObjectURL(file); - } else if (/^video\//.test(file.type)) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - var duration, max_height, max_width, pass, videoHeight, videoWidth; - if (!cb) { - return; - } - videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - pass = true; - if (videoHeight > max_height || videoWidth > max_width) { - QR.error("" + file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - pass = false; - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - pass = false; - } - if (!isFinite(video.duration)) { - QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); - pass = false; - } - if (duration > QR.max_duration_video) { - QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - pass = false; - } - if (video.mozHasAudio) { - QR.error("" + file.name + ": Audio not allowed"); - pass = false; - } - cb(pass); - return cb = null; - }); - $.on(video, 'error', function() { - var _ref; - if (!cb) { - return; - } - if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { - QR.error("" + file.name + ": Video appears corrupt"); - } - cb(false); - return cb = null; - }); - return video.src = URL.createObjectURL(file); - } else { - return cb(true); + return post.setFile(file); } }, openFileInput: function(e) { @@ -7583,21 +7505,30 @@ }; _Class.prototype.setThumbnail = function() { - var fileURL, img, isVideo; + var el, fileURL, isVideo; isVideo = /^video\//.test(this.file.type); - img = $.el((isVideo ? 'video' : 'img')); - $.on(img, (isVideo ? 'loadeddata' : 'load'), (function(_this) { + el = $.el((isVideo ? 'video' : 'img')); + $.on(el, (isVideo ? 'loadeddata' : 'load'), (function(_this) { return function() { - var cv, height, s, width; + var cv, error, errors, height, s, width, _i, _len; + errors = _this.checkDimensions(el, isVideo); + if (errors.length) { + for (_i = 0, _len = errors.length; _i < _len; _i++) { + error = errors[_i]; + QR.error(error); + } + _this.URL = fileURL; + return _this.rmFile(); + } s = 90 * 2 * window.devicePixelRatio; if (_this.file.type === 'image/gif') { s *= 3; } if (isVideo) { - height = img.videoHeight; - width = img.videoWidth; + height = el.videoHeight; + width = el.videoWidth; } else { - height = img.height, width = img.width; + height = el.height, width = el.width; if (height < s || width < s) { _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; @@ -7612,9 +7543,9 @@ width = s; } cv = $.el('canvas'); - cv.height = img.height = height; - cv.width = img.width = width; - cv.getContext('2d').drawImage(img, 0, 0, width, height); + cv.height = el.height = height; + cv.width = el.width = width; + cv.getContext('2d').drawImage(el, 0, 0, width, height); URL.revokeObjectURL(fileURL); return cv.toBlob(function(blob) { _this.URL = URL.createObjectURL(blob); @@ -7623,7 +7554,41 @@ }; })(this)); fileURL = URL.createObjectURL(this.file); - return img.src = fileURL; + return el.src = fileURL; + }; + + _Class.prototype.checkDimensions = function(el, video) { + var duration, err, height, max_height, max_width, videoHeight, videoWidth, width; + err = []; + if (video) { + videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; + max_height = QR.max_height < QR.max_height_video ? QR.max_height : QR.max_height_video; + max_width = QR.max_width < QR.max_width_video ? QR.max_width : QR.max_width_video; + if (videoHeight > max_height || videoWidth > max_width) { + err.push("" + this.file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); + } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + err.push("" + this.file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + if (!isFinite(el.duration)) { + err.push("" + file.name + ": Video lacks duration metadata (try remuxing)"); + } + if (duration > QR.max_duration_video) { + err.push("" + this.file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + } + if (el.mozHasAudio) { + err.push("" + file.name + ": Audio not allowed"); + } + } else { + height = el.height, width = el.width; + if (height > QR.max_height || width > QR.max_width) { + err.push("" + this.file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); + } + if (height < QR.min_height || width < QR.min_width) { + err.push("" + this.file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + } + return err; }; _Class.prototype.rmFile = function() { @@ -14043,7 +14008,7 @@ return window.open('//sys.4chan.org/auth', 'This will steal your data.', 'left=0,top=0,width=500,height=255,toolbar=0,resizable=0'); }); $.before(styleSelector.previousSibling, [$.tn('['), passLink, $.tn(']\u00A0\u00A0')]); - $('link[href*="yotsubluemobile.559.css"', d.head).disabled = true; + $('link[href*="mobile"', d.head).disabled = true; } if (!Conf['JSON Navigation'] || g.VIEW === 'thread') { Main.initThread(); diff --git a/builds/crx/script.js b/builds/crx/script.js index 7ed2ec3c5..cb4c21075 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -6436,7 +6436,7 @@ } }, handleFile: function(file, index, nfiles) { - var isNewPost, isSingle, max, post, _ref; + var isSingle, max, post, _ref; isSingle = nfiles === 1; if (/^text\//.test(file.type)) { if (isSingle) { @@ -6463,89 +6463,15 @@ return; } } - isNewPost = false; if (isSingle) { post = QR.selected; } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { - isNewPost = true; post = new QR.post(); } if (/^text/.test(file.type)) { return post.pasteText(file); } else { - post.setFile(file); - } - return QR.checkDimensions(file, function(pass) { - if (pass || isSingle) { - return post.setFile(file); - } else if (isNewPost) { - return post.rm(); - } - }); - }, - checkDimensions: function(file, cb) { - var img, video; - if (/^image\//.test(file.type)) { - img = new Image(); - img.onload = function() { - var height, pass, width; - height = img.height, width = img.width; - pass = true; - if (height > QR.max_height || width > QR.max_width) { - QR.error("" + file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - pass = false; - } - if (height < QR.min_height || width < QR.min_width) { - QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - pass = false; - } - return cb(pass); - }; - return img.src = URL.createObjectURL(file); - } else if (/^video\//.test(file.type)) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - var duration, max_height, max_width, pass, videoHeight, videoWidth; - if (!cb) { - return; - } - videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - pass = true; - if (videoHeight > max_height || videoWidth > max_width) { - QR.error("" + file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - pass = false; - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - pass = false; - } - if (!isFinite(video.duration)) { - QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); - pass = false; - } - if (duration > QR.max_duration_video) { - QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - pass = false; - } - cb(pass); - return cb = null; - }); - $.on(video, 'error', function() { - var _ref; - if (!cb) { - return; - } - if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { - QR.error("" + file.name + ": Video appears corrupt"); - } - cb(false); - return cb = null; - }); - return video.src = URL.createObjectURL(file); - } else { - return cb(true); + return post.setFile(file); } }, openFileInput: function(e) { @@ -7620,21 +7546,30 @@ }; _Class.prototype.setThumbnail = function() { - var fileURL, img, isVideo; + var el, fileURL, isVideo; isVideo = /^video\//.test(this.file.type); - img = $.el((isVideo ? 'video' : 'img')); - $.on(img, (isVideo ? 'loadeddata' : 'load'), (function(_this) { + el = $.el((isVideo ? 'video' : 'img')); + $.on(el, (isVideo ? 'loadeddata' : 'load'), (function(_this) { return function() { - var cv, height, s, width; + var cv, error, errors, height, s, width, _i, _len; + errors = _this.checkDimensions(el, isVideo); + if (errors.length) { + for (_i = 0, _len = errors.length; _i < _len; _i++) { + error = errors[_i]; + QR.error(error); + } + _this.URL = fileURL; + return _this.rmFile(); + } s = 90 * 2 * window.devicePixelRatio; if (_this.file.type === 'image/gif') { s *= 3; } if (isVideo) { - height = img.videoHeight; - width = img.videoWidth; + height = el.videoHeight; + width = el.videoWidth; } else { - height = img.height, width = img.width; + height = el.height, width = el.width; if (height < s || width < s) { _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; @@ -7649,9 +7584,9 @@ width = s; } cv = $.el('canvas'); - cv.height = img.height = height; - cv.width = img.width = width; - cv.getContext('2d').drawImage(img, 0, 0, width, height); + cv.height = el.height = height; + cv.width = el.width = width; + cv.getContext('2d').drawImage(el, 0, 0, width, height); URL.revokeObjectURL(fileURL); return cv.toBlob(function(blob) { _this.URL = URL.createObjectURL(blob); @@ -7660,7 +7595,38 @@ }; })(this)); fileURL = URL.createObjectURL(this.file); - return img.src = fileURL; + return el.src = fileURL; + }; + + _Class.prototype.checkDimensions = function(el, video) { + var duration, err, height, max_height, max_width, videoHeight, videoWidth, width; + err = []; + if (video) { + videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; + max_height = QR.max_height < QR.max_height_video ? QR.max_height : QR.max_height_video; + max_width = QR.max_width < QR.max_width_video ? QR.max_width : QR.max_width_video; + if (videoHeight > max_height || videoWidth > max_width) { + err.push("" + this.file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); + } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + err.push("" + this.file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + if (!isFinite(el.duration)) { + err.push("" + file.name + ": Video lacks duration metadata (try remuxing)"); + } + if (duration > QR.max_duration_video) { + err.push("" + this.file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + } + } else { + height = el.height, width = el.width; + if (height > QR.max_height || width > QR.max_width) { + err.push("" + this.file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); + } + if (height < QR.min_height || width < QR.min_width) { + err.push("" + this.file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + } + } + return err; }; _Class.prototype.rmFile = function() { @@ -14060,7 +14026,7 @@ return window.open('//sys.4chan.org/auth', 'This will steal your data.', 'left=0,top=0,width=500,height=255,toolbar=0,resizable=0'); }); $.before(styleSelector.previousSibling, [$.tn('['), passLink, $.tn(']\u00A0\u00A0')]); - $('link[href*="yotsubluemobile.559.css"', d.head).disabled = true; + $('link[href*="mobile"', d.head).disabled = true; } if (!Conf['JSON Navigation'] || g.VIEW === 'thread') { Main.initThread(); diff --git a/src/General/Main.coffee b/src/General/Main.coffee index acd18d487..313cfbeb1 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -195,7 +195,7 @@ Main = 'left=0,top=0,width=500,height=255,toolbar=0,resizable=0' $.before styleSelector.previousSibling, [$.tn '['; passLink, $.tn ']\u00A0\u00A0'] # Completely disable the mobile layout - $('link[href*="yotsubluemobile.559.css"', d.head).disabled = true + $('link[href*="mobile"', d.head).disabled = true # Parse HTML or skip it and start building from JSON. if !Conf['JSON Navigation'] or g.VIEW is 'thread' diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index 210071a95..196ed41ee 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -372,74 +372,14 @@ QR = if file.size > max QR.error "#{file.name}: File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})." return unless isSingle - isNewPost = false if isSingle post = QR.selected else if index isnt 0 or (post = QR.posts[QR.posts.length - 1]).file - isNewPost = true post = new QR.post() if /^text/.test file.type return post.pasteText file else post.setFile file - QR.checkDimensions file, (pass) -> - if pass or isSingle - post.setFile file - else if isNewPost - post.rm() - - checkDimensions: (file, cb) -> - if /^image\//.test file.type - img = new Image() - img.onload = -> - {height, width} = img - pass = true - if height > QR.max_height or width > QR.max_width - QR.error "#{file.name}: Image too large (image: #{height}x#{width}px, max: #{QR.max_height}x#{QR.max_width}px)" - pass = false - if height < QR.min_height or width < QR.min_width - QR.error "#{file.name}: Image too small (image: #{height}x#{width}px, min: #{QR.min_height}x#{QR.min_width}px)" - pass = false - cb pass - img.src = URL.createObjectURL file - else if /^video\//.test file.type - video = $.el 'video' - $.on video, 'loadedmetadata', -> - return unless cb - {videoHeight, videoWidth, duration} = video - max_height = Math.min(QR.max_height, QR.max_height_video) - max_width = Math.min(QR.max_width, QR.max_width_video) - pass = true - if videoHeight > max_height or videoWidth > max_width - QR.error "#{file.name}: Video too large (video: #{videoHeight}x#{videoWidth}px, max: #{max_height}x#{max_width}px)" - pass = false - if videoHeight < QR.min_height or videoWidth < QR.min_width - QR.error "#{file.name}: Video too small (video: #{videoHeight}x#{videoWidth}px, min: #{QR.min_height}x#{QR.min_width}px)" - pass = false - unless isFinite video.duration - QR.error "#{file.name}: Video lacks duration metadata (try remuxing)" - pass = false - if duration > QR.max_duration_video - QR.error "#{file.name}: Video too long (video: #{duration}s, max: #{QR.max_duration_video}s)" - pass = false - <% if (type === 'userscript') { %> - if video.mozHasAudio - QR.error "#{file.name}: Audio not allowed" - pass = false - <% } %> - cb pass - cb = null - $.on video, 'error', -> - return unless cb - if file.type in QR.mimeTypes - # only report error here if we should have been able to play the video - # otherwise "unsupported type" should already have been shown - QR.error "#{file.name}: Video appears corrupt" - cb false - cb = null - video.src = URL.createObjectURL file - else - cb true openFileInput: (e) -> e.stopPropagation() diff --git a/src/Posting/QR.post.coffee b/src/Posting/QR.post.coffee index 913b8e057..ea4c4578b 100644 --- a/src/Posting/QR.post.coffee +++ b/src/Posting/QR.post.coffee @@ -173,9 +173,16 @@ QR.post = class setThumbnail: -> # Create a redimensioned thumbnail. isVideo = /^video\//.test @file.type - img = $.el (if isVideo then 'video' else 'img') + el = $.el (if isVideo then 'video' else 'img') + + $.on el, (if isVideo then 'loadeddata' else 'load'), => + # Verify element dimensions. + errors = @checkDimensions el, isVideo + if errors.length + QR.error error for error in errors + @URL = fileURL # this.removeFile will revoke this proper. + return @rmFile() - $.on img, (if isVideo then 'loadeddata' else 'load'), => # Generate thumbnails only if they're really big. # Resized pictures through canvases look like ass, # so we generate thumbnails `s` times bigger then expected @@ -183,10 +190,10 @@ QR.post = class s = 90 * 2 * window.devicePixelRatio s *= 3 if @file.type is 'image/gif' # let them animate if isVideo - height = img.videoHeight - width = img.videoWidth + height = el.videoHeight + width = el.videoWidth else - {height, width} = img + {height, width} = el if height < s or width < s @URL = fileURL @nodes.el.style.backgroundImage = "url(#{@URL})" @@ -198,16 +205,42 @@ QR.post = class height = s / width * height width = s cv = $.el 'canvas' - cv.height = img.height = height - cv.width = img.width = width - cv.getContext('2d').drawImage img, 0, 0, width, height + cv.height = el.height = height + cv.width = el.width = width + cv.getContext('2d').drawImage el, 0, 0, width, height URL.revokeObjectURL fileURL cv.toBlob (blob) => @URL = URL.createObjectURL blob @nodes.el.style.backgroundImage = "url(#{@URL})" fileURL = URL.createObjectURL @file - img.src = fileURL + el.src = fileURL + + checkDimensions: (el, video) -> + err = [] + if video + {videoHeight, videoWidth, duration} = el + max_height = if QR.max_height < QR.max_height_video then QR.max_height else QR.max_height_video + max_width = if QR.max_width < QR.max_width_video then QR.max_width else QR.max_width_video + if videoHeight > max_height or videoWidth > max_width + err.push "#{@file.name}: Video too large (video: #{videoHeight}x#{videoWidth}px, max: #{max_height}x#{max_width}px)" + if videoHeight < QR.min_height or videoWidth < QR.min_width + err.push "#{@file.name}: Video too small (video: #{videoHeight}x#{videoWidth}px, min: #{QR.min_height}x#{QR.min_width}px)" + unless isFinite el.duration + err.push "#{file.name}: Video lacks duration metadata (try remuxing)" + if duration > QR.max_duration_video + err.push "#{@file.name}: Video too long (video: #{duration}s, max: #{QR.max_duration_video}s)" + <% if (type === 'userscript') { %> + if el.mozHasAudio + err.push "#{file.name}: Audio not allowed" + <% } %> + else + {height, width} = el + if height > QR.max_height or width > QR.max_width + err.push "#{@file.name}: Image too large (image: #{height}x#{width}px, max: #{QR.max_height}x#{QR.max_width}px)" + if height < QR.min_height or width < QR.min_width + err.push "#{@file.name}: Image too small (image: #{height}x#{width}px, min: #{QR.min_height}x#{QR.min_width}px)" + err rmFile: -> return if @isLocked