diff --git a/CHANGELOG.md b/CHANGELOG.md index b75e1c934..2eab5d355 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### v1.7.24 +*2014-04-30* + **ccd0** - Fix bug where multiple images selected for posting were out of order. - Check dimensions and duration of .webm files before posting. diff --git a/LICENSE b/LICENSE index 0f459c8fc..d5ee36f05 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.7.23 - 2014-04-29 +* 4chan X - Version 1.7.24 - 2014-04-30 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index c5d395051..6f08f02bb 100755 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.7.23 +// @version 1.7.24 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 34e979545..d27634168 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.7.23 +// @version 1.7.24 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.7.23 - 2014-04-29 +* 4chan X - Version 1.7.24 - 2014-04-30 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -372,7 +372,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.23', + VERSION: '1.7.24', NAMESPACE: '4chan X.', boards: {} }; @@ -6048,7 +6048,7 @@ }); }, handleFiles: function(files) { - var file, isSingle, max, _i, _len; + var file, i, _i, _len; if (this !== QR) { files = __slice.call(this.files); this.value = null; @@ -6056,64 +6056,114 @@ if (!files.length) { return; } - max = QR.nodes.fileInput.max; - isSingle = files.length === 1; QR.cleanNotifications(); - for (_i = 0, _len = files.length; _i < _len; _i++) { - file = files[_i]; - QR.checkDimensions(file, isSingle, max); + for (i = _i = 0, _len = files.length; _i < _len; i = ++_i) { + file = files[i]; + QR.handleFile(file, i, files.length); } - if (!isSingle) { + if (files.length !== 1) { return $.addClass(QR.nodes.el, 'dump'); } }, - checkDimensions: function(file, isSingle, max) { - var img; + handleFile: function(file, index, nfiles) { + var isNewPost, max, post, _ref; + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { + max = QR.nodes.fileInput.max; + if (/^video\//.test(file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (file.size > max) { + return QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + } + isNewPost = false; + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { + isNewPost = true; + post = new QR.post(); + } + return QR.checkDimensions(file, function(pass) { + if (pass) { + return post.setFile(file); + } else if (isNewPost) { + return post.rm(); + } + }); + } else if (/^text/.test(file.type)) { + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { + post = new QR.post(); + } + return post.pasteText(file); + } else { + return QR.error("" + file.name + ": Unsupported file type."); + } + }, + checkDimensions: function(file, cb) { + var img, video; if (/^image\//.test(file.type)) { img = new Image(); img.onload = (function(_this) { return function() { var height, width; height = img.height, width = img.width; - if (height > QR.max_heigth || width > QR.max_heigth) { - return QR.error("" + file.name + ": Image too large (image: " + img.height + "x" + img.width + "px, max: " + QR.max_heigth + "x" + QR.max_width + "px)"); + 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)"); + return cb(false); + } else 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)"); + return cb(false); + } else { + return cb(true); } - if (height < QR.min_heigth || width < QR.min_heigth) { - return QR.error("" + file.name + ": Image too small (image: " + img.height + "x" + img.width + "px, min: " + QR.min_heigth + "x" + QR.min_width + "px)"); - } - return QR.handleFile(file, isSingle, max); }; })(this); return img.src = URL.createObjectURL(file); + } else if (/^video\//.test(file.type)) { + video = $.el('video'); + $.on(video, 'loadedmetadata', (function(_this) { + return function() { + var duration, max_height, max_width, videoHeight, videoWidth; + if (cb == null) { + 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); + 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)"); + cb(false); + } else 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)"); + cb(false); + } else if (!isFinite(video.duration)) { + QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); + cb(false); + } else if (duration > QR.max_duration_video) { + QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + cb(false); + } else { + cb(true); + } + return cb = null; + }; + })(this)); + $.on(video, 'error', (function(_this) { + return function() { + if (cb == null) { + return; + } + QR.error("" + file.name + ": Video appears corrupt"); + cb(false); + return cb = null; + }; + })(this)); + return video.src = URL.createObjectURL(file); } else { - return QR.handleFile(file, isSingle, max); + return cb(true); } }, - handleFile: function(file, isSingle, max) { - var post, _ref; - if (file.size > max) { - QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); - return; - } else if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { - if (!/^text/.test(file.type)) { - QR.error("" + file.name + ": Unsupported file type."); - return; - } - if (isSingle) { - post = QR.selected; - } else if ((post = QR.posts[QR.posts.length - 1]).com) { - post = new QR.post(); - } - post.pasteText(file); - return; - } - if (isSingle) { - post = QR.selected; - } else if ((post = QR.posts[QR.posts.length - 1]).file) { - post = new QR.post(); - } - return post.setFile(file); - }, openFileInput: function(e) { var _ref; e.stopPropagation(); @@ -6158,7 +6208,7 @@ return list.value = g.VIEW === 'thread' ? g.THREADID : 'new'; }, dialog: function() { - var dialog, elm, event, i, items, key, name, node, nodes, rules, save, value, _, _ref, _ref1, _ref2; + var dialog, elm, event, i, items, key, name, node, nodes, prop, rules, save, value, _, _i, _len, _ref, _ref1, _ref2, _ref3; QR.nodes = nodes = { el: dialog = UI.dialog('qr', 'top:0;right:0;', "
×
+
No selected file
") }; @@ -6193,15 +6243,23 @@ nodes[key] = $(value, dialog); } rules = $('ul.rules').textContent.trim(); - QR.min_width = QR.min_heigth = 1; - QR.max_width = QR.max_heigth = 5000; + QR.min_width = QR.min_height = 1; + QR.max_width = QR.max_height = 5000; try { - _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_heigth = _ref1[2]; - _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_heigth = _ref2[2]; + _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_height = _ref1[2]; + _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_height = _ref2[2]; + _ref3 = ['min_width', 'min_height', 'max_width', 'max_height']; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + prop = _ref3[_i]; + QR[prop] = parseInt(QR[prop], 10); + } } catch (_error) { null; } nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; + QR.max_size_video = 3145728; + QR.max_width_video = QR.max_height_video = 2048; + QR.max_duration_video = 120; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); diff --git a/builds/crx.crx b/builds/crx.crx index 607e6aa00..36e7e8a2e 100644 Binary files a/builds/crx.crx and b/builds/crx.crx differ diff --git a/builds/crx/manifest.json b/builds/crx/manifest.json index 511fe3356..57213eab9 100755 --- a/builds/crx/manifest.json +++ b/builds/crx/manifest.json @@ -1,6 +1,6 @@ { "name": "4chan X", - "version": "1.7.23", + "version": "1.7.24", "manifest_version": 2, "description": "Cross-browser userscript for maximum lurking on 4chan.", "icons": { diff --git a/builds/crx/script.js b/builds/crx/script.js index 7af3c6471..1f1feafe0 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.7.23 - 2014-04-29 +* 4chan X - Version 1.7.24 - 2014-04-30 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -348,7 +348,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.23', + VERSION: '1.7.24', NAMESPACE: '4chan X.', boards: {} }; @@ -6084,7 +6084,7 @@ xhr.send(); }, handleFiles: function(files) { - var file, isSingle, max, _i, _len; + var file, i, _i, _len; if (this !== QR) { files = __slice.call(this.files); this.value = null; @@ -6092,64 +6092,114 @@ if (!files.length) { return; } - max = QR.nodes.fileInput.max; - isSingle = files.length === 1; QR.cleanNotifications(); - for (_i = 0, _len = files.length; _i < _len; _i++) { - file = files[_i]; - QR.checkDimensions(file, isSingle, max); + for (i = _i = 0, _len = files.length; _i < _len; i = ++_i) { + file = files[i]; + QR.handleFile(file, i, files.length); } - if (!isSingle) { + if (files.length !== 1) { return $.addClass(QR.nodes.el, 'dump'); } }, - checkDimensions: function(file, isSingle, max) { - var img; + handleFile: function(file, index, nfiles) { + var isNewPost, max, post, _ref; + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { + max = QR.nodes.fileInput.max; + if (/^video\//.test(file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (file.size > max) { + return QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + } + isNewPost = false; + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { + isNewPost = true; + post = new QR.post(); + } + return QR.checkDimensions(file, function(pass) { + if (pass) { + return post.setFile(file); + } else if (isNewPost) { + return post.rm(); + } + }); + } else if (/^text/.test(file.type)) { + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { + post = new QR.post(); + } + return post.pasteText(file); + } else { + return QR.error("" + file.name + ": Unsupported file type."); + } + }, + checkDimensions: function(file, cb) { + var img, video; if (/^image\//.test(file.type)) { img = new Image(); img.onload = (function(_this) { return function() { var height, width; height = img.height, width = img.width; - if (height > QR.max_heigth || width > QR.max_heigth) { - return QR.error("" + file.name + ": Image too large (image: " + img.height + "x" + img.width + "px, max: " + QR.max_heigth + "x" + QR.max_width + "px)"); + 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)"); + return cb(false); + } else 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)"); + return cb(false); + } else { + return cb(true); } - if (height < QR.min_heigth || width < QR.min_heigth) { - return QR.error("" + file.name + ": Image too small (image: " + img.height + "x" + img.width + "px, min: " + QR.min_heigth + "x" + QR.min_width + "px)"); - } - return QR.handleFile(file, isSingle, max); }; })(this); return img.src = URL.createObjectURL(file); + } else if (/^video\//.test(file.type)) { + video = $.el('video'); + $.on(video, 'loadedmetadata', (function(_this) { + return function() { + var duration, max_height, max_width, videoHeight, videoWidth; + if (cb == null) { + 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); + 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)"); + cb(false); + } else 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)"); + cb(false); + } else if (!isFinite(video.duration)) { + QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); + cb(false); + } else if (duration > QR.max_duration_video) { + QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + cb(false); + } else { + cb(true); + } + return cb = null; + }; + })(this)); + $.on(video, 'error', (function(_this) { + return function() { + if (cb == null) { + return; + } + QR.error("" + file.name + ": Video appears corrupt"); + cb(false); + return cb = null; + }; + })(this)); + return video.src = URL.createObjectURL(file); } else { - return QR.handleFile(file, isSingle, max); + return cb(true); } }, - handleFile: function(file, isSingle, max) { - var post, _ref; - if (file.size > max) { - QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); - return; - } else if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { - if (!/^text/.test(file.type)) { - QR.error("" + file.name + ": Unsupported file type."); - return; - } - if (isSingle) { - post = QR.selected; - } else if ((post = QR.posts[QR.posts.length - 1]).com) { - post = new QR.post(); - } - post.pasteText(file); - return; - } - if (isSingle) { - post = QR.selected; - } else if ((post = QR.posts[QR.posts.length - 1]).file) { - post = new QR.post(); - } - return post.setFile(file); - }, openFileInput: function(e) { var _ref; e.stopPropagation(); @@ -6194,7 +6244,7 @@ return list.value = g.VIEW === 'thread' ? g.THREADID : 'new'; }, dialog: function() { - var dialog, elm, event, i, items, key, name, node, nodes, rules, save, value, _, _ref, _ref1, _ref2; + var dialog, elm, event, i, items, key, name, node, nodes, prop, rules, save, value, _, _i, _len, _ref, _ref1, _ref2, _ref3; QR.nodes = nodes = { el: dialog = UI.dialog('qr', 'top:0;right:0;', "
×
+
No selected file
") }; @@ -6229,15 +6279,23 @@ nodes[key] = $(value, dialog); } rules = $('ul.rules').textContent.trim(); - QR.min_width = QR.min_heigth = 1; - QR.max_width = QR.max_heigth = 5000; + QR.min_width = QR.min_height = 1; + QR.max_width = QR.max_height = 5000; try { - _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_heigth = _ref1[2]; - _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_heigth = _ref2[2]; + _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_height = _ref1[2]; + _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_height = _ref2[2]; + _ref3 = ['min_width', 'min_height', 'max_width', 'max_height']; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + prop = _ref3[_i]; + QR[prop] = parseInt(QR[prop], 10); + } } catch (_error) { null; } nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; + QR.max_size_video = 3145728; + QR.max_width_video = QR.max_height_video = 2048; + QR.max_duration_video = 120; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); diff --git a/builds/updates.xml b/builds/updates.xml index 414436237..d6680a96f 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/package.json b/package.json index a3e336e2c..7bb1ba6c0 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "4chan-X", - "version": "1.7.23", + "version": "1.7.24", "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X",