Release 4chan X v1.10.3.0.

This commit is contained in:
ccd0 2015-03-01 01:24:09 -08:00
parent bf8d530b29
commit 6ab3969672
13 changed files with 765 additions and 812 deletions

View File

@ -2,6 +2,16 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's wor
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x). The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
### v1.10.3
**v1.10.3.0** *(2015-03-01)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.3.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.3.0/builds/4chan-X-noupdate.crx "Chromium version")]
- Make the filename in the Quick Reply editable immediately without having to Control+click it.
- Add a "Files" button which can be used to open the file picker even if a file has already been selected. This also fixes issues with opening the file picker via keyboard on Firefox.
- Move the spoiler checkbox into the box containing the filename.
- Always merely warn about disallowed file types / sizes / dimensions, rather than outright preventing them from being posted. Links to `[delete]` and `[delete all]` such posts have been added to the warning messages to make removing the files from a dumplist convenient.
- Remove the "low on cached captchas" notifications as the 2-minute captcha expiry time has made them more annoying than useful.
- Minor bugfixes.
### v1.10.2 ### v1.10.2
**v1.10.2.8** *(2015-02-28)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.crx "Chromium version")] **v1.10.2.8** *(2015-02-28)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.2.8/builds/4chan-X-noupdate.crx "Chromium version")]

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan X beta // @name 4chan X beta
// @version 1.10.2.8 // @version 1.10.3.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X beta // @name 4chan X beta
// @version 1.10.2.8 // @version 1.10.3.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -393,7 +393,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.2.8', VERSION: '1.10.3.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
NAME: '4chan X', NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@ -3066,7 +3066,7 @@
el: $.el('span', { el: $.el('span', {
textContent: 'Index Navigation' textContent: 'Index Navigation'
}), }),
order: 98, order: 100,
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry] subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
}); });
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
@ -6392,7 +6392,7 @@
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread); $.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
Header.menu.addEntry(this.entry = { Header.menu.addEntry(this.entry = {
el: this.controls, el: this.controls,
order: 98 order: 99
}); });
Thread.callbacks.push({ Thread.callbacks.push({
name: 'Quote Threading', name: 'Quote Threading',
@ -7169,6 +7169,7 @@
if (url === null) { if (url === null) {
return; return;
} }
QR.nodes.fileButton.focus();
return CrossOrigin.file(url, function(blob) { return CrossOrigin.file(url, function(blob) {
if (blob) { if (blob) {
return QR.handleFiles([blob]); return QR.handleFiles([blob]);
@ -7178,7 +7179,7 @@
}); });
}, },
handleFiles: function(files) { handleFiles: function(files) {
var file, i, k, len1; var file, k, len1;
if (this !== QR) { if (this !== QR) {
files = slice.call(this.files); files = slice.call(this.files);
this.value = null; this.value = null;
@ -7187,147 +7188,36 @@
return; return;
} }
QR.cleanNotifications(); QR.cleanNotifications();
for (i = k = 0, len1 = files.length; k < len1; i = ++k) { for (k = 0, len1 = files.length; k < len1; k++) {
file = files[i]; file = files[k];
QR.handleFile(file, i, files.length); QR.handleFile(file, files.length);
} }
if (files.length !== 1) { if (files.length !== 1) {
return $.addClass(QR.nodes.el, 'dump'); $.addClass(QR.nodes.el, 'dump');
}
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
return QR.nodes.filename.focus();
} }
}, },
handleFile: function(file, index, nfiles) { handleFile: function(file, nfiles) {
var isNewPost, isSingle, max, post, ref; var isText, post;
isSingle = nfiles === 1; isText = /^text\//.test(file.type);
if (/^text\//.test(file.type)) { if (nfiles === 1) {
if (isSingle) { post = QR.selected;
post = QR.selected; } else {
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { post = QR.posts[QR.posts.length - 1];
if ((isText ? post.com || post.pasting : post.file)) {
post = new QR.post(); post = new QR.post();
} }
post.pasteText(file); }
return post[isText ? 'pasteText' : 'setFile'](file);
},
openFileInput: function() {
if (QR.nodes.fileButton.disabled) {
return; return;
} }
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) { QR.nodes.fileInput.click();
QR.error(file.name + ": Unsupported file type."); return QR.nodes.fileButton.focus();
if (!isSingle) {
return;
}
}
max = QR.nodes.fileInput.max;
if (/^video\//.test(file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (file.size > max) {
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
if (!isSingle) {
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();
}
return QR.checkDimensions(file, function(pass, el) {
if (pass || isSingle) {
return post.setFile(file, el);
} else if (isNewPost) {
post.rm();
if (el) {
return URL.revokeObjectURL(el.src);
}
}
});
},
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, img);
};
img.onerror = function() {
return cb(false, null);
};
return img.src = URL.createObjectURL(file);
} else if (/^video\//.test(file.type)) {
video = $.el('video');
$.on(video, 'loadeddata', function() {
var duration, max_height, max_width, pass, ref, 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(duration)) {
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
pass = false;
} else 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 (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
QR.error(file.name + ": Audio not allowed");
pass = false;
}
cb(pass, video);
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");
}
URL.revokeObjectURL(file);
cb(false, null);
return cb = null;
});
return video.src = URL.createObjectURL(file);
} else {
return cb(true, null);
}
},
openFileInput: function(e) {
var ref;
e.stopPropagation();
if (e.shiftKey && e.type === 'click') {
return QR.selected.rmFile();
}
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
$.addClass(QR.nodes.filename, 'edit');
QR.nodes.filename.focus();
}
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
return;
}
e.preventDefault();
return QR.nodes.fileInput.click();
}, },
generatePostableThreadsList: function() { generatePostableThreadsList: function() {
var k, len1, list, options, ref, thread, val; var k, len1, list, options, ref, thread, val;
@ -7358,7 +7248,7 @@
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode; var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
QR.nodes = nodes = { QR.nodes = nodes = {
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> " innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
}) })
}; };
setNode = function(name, query) { setNode = function(name, query) {
@ -7380,10 +7270,10 @@
setNode('addPost', '#add-post'); setNode('addPost', '#add-post');
setNode('charCount', '#char-count'); setNode('charCount', '#char-count');
setNode('fileSubmit', '#file-n-submit'); setNode('fileSubmit', '#file-n-submit');
setNode('fileButton', '#qr-file-button');
setNode('noFile', '#qr-no-file');
setNode('filename', '#qr-filename'); setNode('filename', '#qr-filename');
setNode('fileContainer', '#qr-filename-container');
setNode('fileRM', '#qr-filerm'); setNode('fileRM', '#qr-filerm');
setNode('fileExtras', '#qr-extras-container');
setNode('spoiler', '#qr-file-spoiler'); setNode('spoiler', '#qr-file-spoiler');
setNode('spoilerPar', '#qr-spoiler-label'); setNode('spoilerPar', '#qr-spoiler-label');
setNode('status', '[type=submit]'); setNode('status', '[type=submit]');
@ -7437,7 +7327,8 @@
nodes.flashTag.dataset["default"] = '4'; nodes.flashTag.dataset["default"] = '4';
$.add(nodes.form, nodes.flashTag); $.add(nodes.form, nodes.flashTag);
} }
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput); $.on(nodes.fileButton, 'click', QR.openFileInput);
$.on(nodes.noFile, 'click', QR.openFileInput);
$.on(nodes.autohide, 'change', QR.toggleHide); $.on(nodes.autohide, 'change', QR.toggleHide);
$.on(nodes.close, 'click', QR.close); $.on(nodes.close, 'click', QR.close);
$.on(nodes.dumpButton, 'click', function() { $.on(nodes.dumpButton, 'click', function() {
@ -7448,15 +7339,9 @@
return new QR.post(true); return new QR.post(true);
}); });
$.on(nodes.form, 'submit', QR.submit); $.on(nodes.form, 'submit', QR.submit);
$.on(nodes.filename, 'blur', function() {
return $.rmClass(this, 'edit');
});
$.on(nodes.fileRM, 'click', function() { $.on(nodes.fileRM, 'click', function() {
return QR.selected.rmFile(); return QR.selected.rmFile();
}); });
$.on(nodes.fileExtras, 'click', function(e) {
return e.stopPropagation();
});
$.on(nodes.spoiler, 'change', function() { $.on(nodes.spoiler, 'change', function() {
return QR.selected.nodes.spoiler.click(); return QR.selected.nodes.spoiler.click();
}); });
@ -7626,7 +7511,7 @@
return QR.status(); return QR.status();
}, },
response: function() { response: function() {
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID; var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
req = QR.req; req = QR.req;
delete QR.req; delete QR.req;
post = QR.posts[0]; post = QR.posts[0];
@ -7696,22 +7581,6 @@
}); });
postsCount = QR.posts.length - 1; postsCount = QR.posts.length - 1;
QR.cooldown.auto = postsCount && isReply; QR.cooldown.auto = postsCount && isReply;
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
notif = new Notification('Quick reply warning', {
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
icon: Favicon.logo
});
notif.onclick = function() {
QR.open();
window.focus();
return QR.captcha.setup(true);
};
notif.onshow = function() {
return setTimeout(function() {
return notif.close();
}, 7 * $.SECOND);
};
}
if (!(Conf['Persistent QR'] || postsCount)) { if (!(Conf['Persistent QR'] || postsCount)) {
QR.close(); QR.close();
} else { } else {
@ -8119,7 +7988,7 @@
return $.on(window, 'focus', function() { return $.on(window, 'focus', function() {
return $.queueTask(function() { return $.queueTask(function() {
var checkbox; var checkbox;
if (!(checkbox = $.id('recaptcha-anchor'))) { if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return; return;
} }
if (d.activeElement !== checkbox) { if (d.activeElement !== checkbox) {
@ -8166,7 +8035,6 @@
if (!(this.isEnabled && (this.needed() || force))) { if (!(this.isEnabled && (this.needed() || force))) {
return; return;
} }
$.addClass(QR.nodes.el, 'captcha-open');
if (focus) { if (focus) {
this.shouldFocus = true; this.shouldFocus = true;
} }
@ -8210,6 +8078,7 @@
}, },
setupIFrame: function(iframe) { setupIFrame: function(iframe) {
this.setupTime = Date.now(); this.setupTime = Date.now();
$.addClass(QR.nodes.el, 'captcha-open');
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
QR.nodes.el.style.top = null; QR.nodes.el.style.top = null;
QR.nodes.el.style.bottom = '0px'; QR.nodes.el.style.bottom = '0px';
@ -8693,7 +8562,8 @@
_Class.prototype["delete"] = function() { _Class.prototype["delete"] = function() {
$.rm(this.nodes.el); $.rm(this.nodes.el);
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors();
}; };
_Class.prototype.lock = function(lock) { _Class.prototype.lock = function(lock) {
@ -8713,7 +8583,6 @@
} }
} }
this.nodes.rm.style.visibility = lock ? 'hidden' : ''; this.nodes.rm.style.visibility = lock ? 'hidden' : '';
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
this.nodes.spoiler.disabled = lock; this.nodes.spoiler.disabled = lock;
return this.nodes.el.draggable = !lock; return this.nodes.el.draggable = !lock;
}; };
@ -8799,10 +8668,82 @@
} }
}; };
_Class.prototype.setFile = function(file1, el) { _Class.rmErrored = function(e) {
var error, errors, k, len1, post, q, ref;
e.stopPropagation();
ref = QR.posts;
for (k = ref.length - 1; k >= 0; k += -1) {
post = ref[k];
if (errors = post.errors) {
for (q = 0, len1 = errors.length; q < len1; q++) {
error = errors[q];
if (!(doc.contains(error))) {
continue;
}
post.rm();
break;
}
}
}
};
_Class.prototype.error = function(className, message) {
var div, ref, rm, rmAll;
div = $.el('div', {
className: className
});
$.extend(div, {
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
});
(this.errors || (this.errors = [])).push(div);
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
$.on(div, 'click', (function(_this) {
return function() {
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.select();
}
};
})(this));
$.on(rm, 'click', (function(_this) {
return function(e) {
e.stopPropagation();
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.rm();
}
};
})(this));
$.on(rmAll, 'click', QR.post.rmErrored);
return QR.error(div);
};
_Class.prototype.fileError = function(message) {
return this.error('file-error', this.filename + ": " + message);
};
_Class.prototype.dismissErrors = function(test) {
var error, k, len1, ref;
if (test == null) {
test = function() {
return true;
};
}
if (this.errors) {
ref = this.errors;
for (k = 0, len1 = ref.length; k < len1; k++) {
error = ref[k];
if (doc.contains(error) && test(error)) {
error.parentNode.previousElementSibling.click();
}
}
}
};
_Class.prototype.setFile = function(file1) {
var ref;
this.file = file1; this.file = file1;
this.filename = this.file.name; this.filename = this.file.name;
this.filesize = $.bytesToString(this.file.size); this.filesize = $.bytesToString(this.file.size);
this.checkSize();
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = false; this.nodes.label.hidden = false;
} }
@ -8813,10 +8754,79 @@
} else { } else {
this.updateFilename(); this.updateFilename();
} }
if (el) { this.nodes.el.style.backgroundImage = null;
return this.setThumbnail(el); if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
return this.fileError('Unsupported file type.');
} else if (/^(image|video)\//.test(this.file.type)) {
return this.readFile();
}
};
_Class.prototype.checkSize = function() {
var max;
max = QR.nodes.fileInput.max;
if (/^video\//.test(this.file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (this.file.size > max) {
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
}
};
_Class.prototype.readFile = function() {
var el, event, isVideo, onerror, onload;
isVideo = /^video\//.test(this.file.type);
el = $.el(isVideo ? 'video' : 'img');
event = isVideo ? 'loadeddata' : 'load';
onload = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.checkDimensions(el);
return _this.setThumbnail(el);
};
})(this);
onerror = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
return URL.revokeObjectURL(el.src);
};
})(this);
$.on(el, event, onload);
$.on(el, 'error', onerror);
return el.src = URL.createObjectURL(this.file);
};
_Class.prototype.checkDimensions = function(el) {
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
if (el.tagName === 'IMG') {
height = el.height, width = el.width;
if (height > QR.max_height || width > QR.max_width) {
this.fileError("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) {
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
} else { } else {
return this.nodes.el.style.backgroundImage = null; videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.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) {
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
}
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
if (!isFinite(duration)) {
this.fileError('Video lacks duration metadata (try remuxing)');
} else if (duration > QR.max_duration_video) {
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
}
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
return this.fileError('Audio not allowed');
}
} }
}; };
@ -8866,23 +8876,26 @@
delete this.filename; delete this.filename;
delete this.filesize; delete this.filesize;
this.nodes.el.title = null; this.nodes.el.title = null;
QR.nodes.fileContainer.title = ''; QR.nodes.filename.title = '';
this.nodes.el.style.backgroundImage = null; this.nodes.el.style.backgroundImage = null;
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = true; this.nodes.label.hidden = true;
} }
this.showFileData(); this.showFileData();
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors(function(error) {
return $.hasClass(error, 'file-error');
});
}; };
_Class.prototype.updateFilename = function() { _Class.prototype.updateFilename = function() {
var long; var long;
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear."; long = this.filename + " (" + this.filesize + ")";
this.nodes.el.title = long; this.nodes.el.title = long;
if (this !== QR.selected) { if (this !== QR.selected) {
return; return;
} }
return QR.nodes.fileContainer.title = long; return QR.nodes.filename.title = long;
}; };
_Class.prototype.showFileData = function() { _Class.prototype.showFileData = function() {
@ -8898,6 +8911,7 @@
_Class.prototype.pasteText = function(file) { _Class.prototype.pasteText = function(file) {
var reader; var reader;
this.pasting = true;
reader = new FileReader(); reader = new FileReader();
reader.onload = (function(_this) { reader.onload = (function(_this) {
return function(e) { return function(e) {
@ -8911,7 +8925,8 @@
if (QR.selected === _this) { if (QR.selected === _this) {
QR.nodes.com.value = _this.com; QR.nodes.com.value = _this.com;
} }
return _this.nodes.span.textContent = _this.com; _this.nodes.span.textContent = _this.com;
return delete _this.pasting;
}; };
})(this); })(this);
return reader.readAsText(file); return reader.readAsText(file);
@ -10166,7 +10181,7 @@
$.on(this.el, 'change', this.toggle); $.on(this.el, 'change', this.toggle);
return Header.menu.addEntry({ return Header.menu.addEntry({
el: prefetch, el: prefetch,
order: 104 order: 98
}); });
}, },
node: function() { node: function() {
@ -17020,9 +17035,6 @@
"body.hasDropDownNav{\n" + "body.hasDropDownNav{\n" +
" margin-top: 5px;\n" + " margin-top: 5px;\n" +
"}\n" + "}\n" +
"a {\n" +
" outline: none !important;\n" +
"}\n" +
".painted {\n" + ".painted {\n" +
" border-radius: 3px;\n" + " border-radius: 3px;\n" +
" padding: 0px 2px;\n" + " padding: 0px 2px;\n" +
@ -17667,7 +17679,7 @@
" text-align: center;\n" + " text-align: center;\n" +
"}\n" + "}\n" +
"/* /tg/ dice rolls */\n" + "/* /tg/ dice rolls */\n" +
".catalog-thread > .comment > b {\n" + ".board_tg .catalog-thread > .comment > b {\n" +
" font-weight: normal;\n" + " font-weight: normal;\n" +
"}\n" + "}\n" +
".catalog-code {\n" + ".catalog-code {\n" +
@ -18118,17 +18130,6 @@
" -webkit-flex-direction: row;\n" + " -webkit-flex-direction: row;\n" +
" flex-direction: row;\n" + " flex-direction: row;\n" +
"}\n" + "}\n" +
"#url-button, #custom-cooldown-button, #dump-button {\n" +
" width: 10%;\n" +
" margin: 0;\n" +
" margin-right: 4px;\n" +
" font: 13px sans-serif;\n" +
" padding: 1px 0px 2px;\n" +
" opacity: 0.6;\n" +
"}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
".persona .field {\n" + ".persona .field {\n" +
" -webkit-flex: 1;\n" + " -webkit-flex: 1;\n" +
" flex: 1;\n" + " flex: 1;\n" +
@ -18151,8 +18152,18 @@
" text-shadow: none !important;\n" + " text-shadow: none !important;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + "#qr textarea {\n" +
" min-width: 100%;\n" +
" resize: both;\n" + " resize: both;\n" +
"}\n" + "}\n" +
".field {\n" +
" -moz-box-sizing: border-box;\n" +
" margin: 0px;\n" +
" padding: 2px 4px 3px;\n" +
"}\n" +
"#qr label input[type=\"checkbox\"] {\n" +
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
"/* Noscript Recaptcha */\n" + "/* Noscript Recaptcha */\n" +
".captcha-img {\n" + ".captcha-img {\n" +
" margin: 0px;\n" + " margin: 0px;\n" +
@ -18196,111 +18207,81 @@
" display: block;\n" + " display: block;\n" +
" width: 100%;\n" + " width: 100%;\n" +
"}\n" + "}\n" +
".field {\n" + "/* File Input, Submit Button */\n" +
" -moz-box-sizing: border-box;\n" + "#file-n-submit {\n" +
" margin: 0px;\n" + " display: -webkit-flex;\n" +
" padding: 2px 4px 3px;\n" + " display: flex;\n" +
" -webkit-align-items: stretch;\n" +
" align-items: stretch;\n" +
" margin-top: 1px;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + ":root.gecko #file-n-submit > input {\n" +
" min-width: 100%;\n" + " margin: 0px -1px -1px;\n" +
"}\n" + "}\n" +
"#qr [type=\"submit\"] {\n" + "#file-n-submit input[type=\"submit\"] {\n" +
" width: 25%;\n" + " width: 25%;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
":root.webkit #qr [type=\"submit\"] {\n" + "#qr-filename-container {\n" +
" height: 24px;\n" + " -webkit-flex: 1 1 auto;\n" +
"}\n" + " flex: 1 1 auto;\n" +
"#qr label input[type=\"checkbox\"] {\n" + " width: 0;\n" +
" display: -webkit-flex;\n" +
" display: flex;\n" +
" -webkit-align-items: center;\n" +
" align-items: center;\n" +
" position: relative;\n" + " position: relative;\n" +
" top: 2px;\n" + " padding: 1px;\n" +
"}\n" + "}\n" +
"/* Fake File Input */\n" +
"input#qr-filename {\n" + "input#qr-filename {\n" +
" border: none !important;\n" + " border: none !important;\n" +
" width: 80%;\n" +
" padding: 0px 4px;\n" +
" position: relative;\n" +
" bottom: 1px;\n" +
" background: none !important;\n" + " background: none !important;\n" +
"}\n" + "}\n" +
"input#qr-filename:not(.edit) {\n" +
" pointer-events: none;\n" +
"}\n" +
"#qr-filename,\n" + "#qr-filename,\n" +
"#qr-filesize,\n" +
".has-file #qr-no-file {\n" + ".has-file #qr-no-file {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr-no-file,\n" + "#qr-no-file,\n" +
".has-file #qr-filename,\n" + ".has-file #qr-filename {\n" +
".has-file #qr-filesize {\n" + " -webkit-flex: 1 1 auto;\n" +
" flex: 1 1 auto;\n" +
" display: inline-block;\n" + " display: inline-block;\n" +
" margin: 0 0 2px;\n" + " padding: 0;\n" +
" padding-left: 3px;\n" +
" overflow: hidden;\n" + " overflow: hidden;\n" +
" text-overflow: ellipsis;\n" + " text-overflow: ellipsis;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
"#qr-no-file {\n" + "#qr-no-file {\n" +
" color: #AAA;\n" + " color: #AAA;\n" +
" padding: 1px 4px;\n" +
"}\n" +
"#qr-filename-container {\n" +
" -moz-box-sizing: border-box;\n" +
" display: inline-block;\n" +
" position: relative;\n" +
" width: 100px;\n" +
" min-width: 74.6%;\n" +
" max-width: 74.6%;\n" +
" margin-right: 0.4%;\n" +
" margin-top: 1px;\n" +
" overflow: hidden;\n" +
" padding: 2px 1px 0;\n" +
" height: 22px;\n" +
"}\n" +
"#qr-filename-container:hover {\n" +
" cursor: text;\n" +
"}\n" +
"#qr-extras-container {\n" +
" position: absolute;\n" +
" right: 0px;\n" +
"}\n" +
"#qr-filerm {\n" +
" margin-right: 3px;\n" +
" z-index: 2;\n" +
"}\n" +
"#file-n-submit {\n" +
" height: 23px;\n" +
"}\n" +
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" display: none;\n" +
"}\n" + "}\n" +
"#qr input[type=\"file\"] {\n" + "#qr input[type=\"file\"] {\n" +
" visibility: hidden;\n" + " visibility: hidden;\n" +
" position: absolute;\n" + " position: absolute;\n" +
"}\n" + "}\n" +
"/* Thread Select / Spoiler Label */\n" + "/* Spoiler Checkbox, QR Icons */\n" +
"#qr select[data-name=\"thread\"] {\n" + "#qr-spoiler-label, #qr-filename-container > a {\n" +
" float: right;\n" + " -webkit-flex: none;\n" +
" flex: none;\n" +
" margin: 0;\n" +
" margin-right: 3px;\n" +
" font: 13px sans-serif;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" + "#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
" width: 6.7%;\n" + ".has-file #url-button,\n" +
" min-width: 6.7%;\n" + "#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" max-width: 6.7%;\n" +
" display: inline-block;\n" +
" text-align: center;\n" +
" vertical-align: top;\n" +
"}\n" +
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-filename-container {\n" + "#qr-file-spoiler {\n" +
" max-width: 67.9%;\n" + " margin: 0;\n" +
" min-width: 67.9%;\n" +
"}\n" + "}\n" +
"#qr-spoiler-label input {\n" + "#url-button, #custom-cooldown-button, #dump-button {\n" +
" position: relative;\n" + " opacity: 0.6;\n" +
" top: 3px;\n" + "}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
"/* Thread Select */\n" +
"#qr select[data-name=\"thread\"] {\n" +
" float: right;\n" +
"}\n" + "}\n" +
"/* Dumping UI */\n" + "/* Dumping UI */\n" +
".dump #dump-list-container {\n" + ".dump #dump-list-container {\n" +

Binary file not shown.

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.10.2.8 // @version 1.10.3.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -392,7 +392,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.2.8', VERSION: '1.10.3.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
NAME: '4chan X', NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@ -3065,7 +3065,7 @@
el: $.el('span', { el: $.el('span', {
textContent: 'Index Navigation' textContent: 'Index Navigation'
}), }),
order: 98, order: 100,
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry] subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
}); });
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
@ -6391,7 +6391,7 @@
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread); $.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
Header.menu.addEntry(this.entry = { Header.menu.addEntry(this.entry = {
el: this.controls, el: this.controls,
order: 98 order: 99
}); });
Thread.callbacks.push({ Thread.callbacks.push({
name: 'Quote Threading', name: 'Quote Threading',
@ -7168,6 +7168,7 @@
if (url === null) { if (url === null) {
return; return;
} }
QR.nodes.fileButton.focus();
return CrossOrigin.file(url, function(blob) { return CrossOrigin.file(url, function(blob) {
if (blob) { if (blob) {
return QR.handleFiles([blob]); return QR.handleFiles([blob]);
@ -7177,7 +7178,7 @@
}); });
}, },
handleFiles: function(files) { handleFiles: function(files) {
var file, i, k, len1; var file, k, len1;
if (this !== QR) { if (this !== QR) {
files = slice.call(this.files); files = slice.call(this.files);
this.value = null; this.value = null;
@ -7186,147 +7187,36 @@
return; return;
} }
QR.cleanNotifications(); QR.cleanNotifications();
for (i = k = 0, len1 = files.length; k < len1; i = ++k) { for (k = 0, len1 = files.length; k < len1; k++) {
file = files[i]; file = files[k];
QR.handleFile(file, i, files.length); QR.handleFile(file, files.length);
} }
if (files.length !== 1) { if (files.length !== 1) {
return $.addClass(QR.nodes.el, 'dump'); $.addClass(QR.nodes.el, 'dump');
}
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
return QR.nodes.filename.focus();
} }
}, },
handleFile: function(file, index, nfiles) { handleFile: function(file, nfiles) {
var isNewPost, isSingle, max, post, ref; var isText, post;
isSingle = nfiles === 1; isText = /^text\//.test(file.type);
if (/^text\//.test(file.type)) { if (nfiles === 1) {
if (isSingle) { post = QR.selected;
post = QR.selected; } else {
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { post = QR.posts[QR.posts.length - 1];
if ((isText ? post.com || post.pasting : post.file)) {
post = new QR.post(); post = new QR.post();
} }
post.pasteText(file); }
return post[isText ? 'pasteText' : 'setFile'](file);
},
openFileInput: function() {
if (QR.nodes.fileButton.disabled) {
return; return;
} }
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) { QR.nodes.fileInput.click();
QR.error(file.name + ": Unsupported file type."); return QR.nodes.fileButton.focus();
if (!isSingle) {
return;
}
}
max = QR.nodes.fileInput.max;
if (/^video\//.test(file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (file.size > max) {
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
if (!isSingle) {
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();
}
return QR.checkDimensions(file, function(pass, el) {
if (pass || isSingle) {
return post.setFile(file, el);
} else if (isNewPost) {
post.rm();
if (el) {
return URL.revokeObjectURL(el.src);
}
}
});
},
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, img);
};
img.onerror = function() {
return cb(false, null);
};
return img.src = URL.createObjectURL(file);
} else if (/^video\//.test(file.type)) {
video = $.el('video');
$.on(video, 'loadeddata', function() {
var duration, max_height, max_width, pass, ref, 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(duration)) {
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
pass = false;
} else 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 (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
QR.error(file.name + ": Audio not allowed");
pass = false;
}
cb(pass, video);
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");
}
URL.revokeObjectURL(file);
cb(false, null);
return cb = null;
});
return video.src = URL.createObjectURL(file);
} else {
return cb(true, null);
}
},
openFileInput: function(e) {
var ref;
e.stopPropagation();
if (e.shiftKey && e.type === 'click') {
return QR.selected.rmFile();
}
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
$.addClass(QR.nodes.filename, 'edit');
QR.nodes.filename.focus();
}
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
return;
}
e.preventDefault();
return QR.nodes.fileInput.click();
}, },
generatePostableThreadsList: function() { generatePostableThreadsList: function() {
var k, len1, list, options, ref, thread, val; var k, len1, list, options, ref, thread, val;
@ -7357,7 +7247,7 @@
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode; var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
QR.nodes = nodes = { QR.nodes = nodes = {
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> " innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
}) })
}; };
setNode = function(name, query) { setNode = function(name, query) {
@ -7379,10 +7269,10 @@
setNode('addPost', '#add-post'); setNode('addPost', '#add-post');
setNode('charCount', '#char-count'); setNode('charCount', '#char-count');
setNode('fileSubmit', '#file-n-submit'); setNode('fileSubmit', '#file-n-submit');
setNode('fileButton', '#qr-file-button');
setNode('noFile', '#qr-no-file');
setNode('filename', '#qr-filename'); setNode('filename', '#qr-filename');
setNode('fileContainer', '#qr-filename-container');
setNode('fileRM', '#qr-filerm'); setNode('fileRM', '#qr-filerm');
setNode('fileExtras', '#qr-extras-container');
setNode('spoiler', '#qr-file-spoiler'); setNode('spoiler', '#qr-file-spoiler');
setNode('spoilerPar', '#qr-spoiler-label'); setNode('spoilerPar', '#qr-spoiler-label');
setNode('status', '[type=submit]'); setNode('status', '[type=submit]');
@ -7436,7 +7326,8 @@
nodes.flashTag.dataset["default"] = '4'; nodes.flashTag.dataset["default"] = '4';
$.add(nodes.form, nodes.flashTag); $.add(nodes.form, nodes.flashTag);
} }
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput); $.on(nodes.fileButton, 'click', QR.openFileInput);
$.on(nodes.noFile, 'click', QR.openFileInput);
$.on(nodes.autohide, 'change', QR.toggleHide); $.on(nodes.autohide, 'change', QR.toggleHide);
$.on(nodes.close, 'click', QR.close); $.on(nodes.close, 'click', QR.close);
$.on(nodes.dumpButton, 'click', function() { $.on(nodes.dumpButton, 'click', function() {
@ -7447,15 +7338,9 @@
return new QR.post(true); return new QR.post(true);
}); });
$.on(nodes.form, 'submit', QR.submit); $.on(nodes.form, 'submit', QR.submit);
$.on(nodes.filename, 'blur', function() {
return $.rmClass(this, 'edit');
});
$.on(nodes.fileRM, 'click', function() { $.on(nodes.fileRM, 'click', function() {
return QR.selected.rmFile(); return QR.selected.rmFile();
}); });
$.on(nodes.fileExtras, 'click', function(e) {
return e.stopPropagation();
});
$.on(nodes.spoiler, 'change', function() { $.on(nodes.spoiler, 'change', function() {
return QR.selected.nodes.spoiler.click(); return QR.selected.nodes.spoiler.click();
}); });
@ -7625,7 +7510,7 @@
return QR.status(); return QR.status();
}, },
response: function() { response: function() {
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID; var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
req = QR.req; req = QR.req;
delete QR.req; delete QR.req;
post = QR.posts[0]; post = QR.posts[0];
@ -7695,22 +7580,6 @@
}); });
postsCount = QR.posts.length - 1; postsCount = QR.posts.length - 1;
QR.cooldown.auto = postsCount && isReply; QR.cooldown.auto = postsCount && isReply;
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
notif = new Notification('Quick reply warning', {
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
icon: Favicon.logo
});
notif.onclick = function() {
QR.open();
window.focus();
return QR.captcha.setup(true);
};
notif.onshow = function() {
return setTimeout(function() {
return notif.close();
}, 7 * $.SECOND);
};
}
if (!(Conf['Persistent QR'] || postsCount)) { if (!(Conf['Persistent QR'] || postsCount)) {
QR.close(); QR.close();
} else { } else {
@ -8118,7 +7987,7 @@
return $.on(window, 'focus', function() { return $.on(window, 'focus', function() {
return $.queueTask(function() { return $.queueTask(function() {
var checkbox; var checkbox;
if (!(checkbox = $.id('recaptcha-anchor'))) { if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return; return;
} }
if (d.activeElement !== checkbox) { if (d.activeElement !== checkbox) {
@ -8165,7 +8034,6 @@
if (!(this.isEnabled && (this.needed() || force))) { if (!(this.isEnabled && (this.needed() || force))) {
return; return;
} }
$.addClass(QR.nodes.el, 'captcha-open');
if (focus) { if (focus) {
this.shouldFocus = true; this.shouldFocus = true;
} }
@ -8209,6 +8077,7 @@
}, },
setupIFrame: function(iframe) { setupIFrame: function(iframe) {
this.setupTime = Date.now(); this.setupTime = Date.now();
$.addClass(QR.nodes.el, 'captcha-open');
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
QR.nodes.el.style.top = null; QR.nodes.el.style.top = null;
QR.nodes.el.style.bottom = '0px'; QR.nodes.el.style.bottom = '0px';
@ -8692,7 +8561,8 @@
_Class.prototype["delete"] = function() { _Class.prototype["delete"] = function() {
$.rm(this.nodes.el); $.rm(this.nodes.el);
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors();
}; };
_Class.prototype.lock = function(lock) { _Class.prototype.lock = function(lock) {
@ -8712,7 +8582,6 @@
} }
} }
this.nodes.rm.style.visibility = lock ? 'hidden' : ''; this.nodes.rm.style.visibility = lock ? 'hidden' : '';
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
this.nodes.spoiler.disabled = lock; this.nodes.spoiler.disabled = lock;
return this.nodes.el.draggable = !lock; return this.nodes.el.draggable = !lock;
}; };
@ -8798,10 +8667,82 @@
} }
}; };
_Class.prototype.setFile = function(file1, el) { _Class.rmErrored = function(e) {
var error, errors, k, len1, post, q, ref;
e.stopPropagation();
ref = QR.posts;
for (k = ref.length - 1; k >= 0; k += -1) {
post = ref[k];
if (errors = post.errors) {
for (q = 0, len1 = errors.length; q < len1; q++) {
error = errors[q];
if (!(doc.contains(error))) {
continue;
}
post.rm();
break;
}
}
}
};
_Class.prototype.error = function(className, message) {
var div, ref, rm, rmAll;
div = $.el('div', {
className: className
});
$.extend(div, {
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
});
(this.errors || (this.errors = [])).push(div);
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
$.on(div, 'click', (function(_this) {
return function() {
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.select();
}
};
})(this));
$.on(rm, 'click', (function(_this) {
return function(e) {
e.stopPropagation();
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.rm();
}
};
})(this));
$.on(rmAll, 'click', QR.post.rmErrored);
return QR.error(div);
};
_Class.prototype.fileError = function(message) {
return this.error('file-error', this.filename + ": " + message);
};
_Class.prototype.dismissErrors = function(test) {
var error, k, len1, ref;
if (test == null) {
test = function() {
return true;
};
}
if (this.errors) {
ref = this.errors;
for (k = 0, len1 = ref.length; k < len1; k++) {
error = ref[k];
if (doc.contains(error) && test(error)) {
error.parentNode.previousElementSibling.click();
}
}
}
};
_Class.prototype.setFile = function(file1) {
var ref;
this.file = file1; this.file = file1;
this.filename = this.file.name; this.filename = this.file.name;
this.filesize = $.bytesToString(this.file.size); this.filesize = $.bytesToString(this.file.size);
this.checkSize();
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = false; this.nodes.label.hidden = false;
} }
@ -8812,10 +8753,79 @@
} else { } else {
this.updateFilename(); this.updateFilename();
} }
if (el) { this.nodes.el.style.backgroundImage = null;
return this.setThumbnail(el); if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
return this.fileError('Unsupported file type.');
} else if (/^(image|video)\//.test(this.file.type)) {
return this.readFile();
}
};
_Class.prototype.checkSize = function() {
var max;
max = QR.nodes.fileInput.max;
if (/^video\//.test(this.file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (this.file.size > max) {
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
}
};
_Class.prototype.readFile = function() {
var el, event, isVideo, onerror, onload;
isVideo = /^video\//.test(this.file.type);
el = $.el(isVideo ? 'video' : 'img');
event = isVideo ? 'loadeddata' : 'load';
onload = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.checkDimensions(el);
return _this.setThumbnail(el);
};
})(this);
onerror = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
return URL.revokeObjectURL(el.src);
};
})(this);
$.on(el, event, onload);
$.on(el, 'error', onerror);
return el.src = URL.createObjectURL(this.file);
};
_Class.prototype.checkDimensions = function(el) {
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
if (el.tagName === 'IMG') {
height = el.height, width = el.width;
if (height > QR.max_height || width > QR.max_width) {
this.fileError("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) {
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
} else { } else {
return this.nodes.el.style.backgroundImage = null; videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.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) {
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
}
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
if (!isFinite(duration)) {
this.fileError('Video lacks duration metadata (try remuxing)');
} else if (duration > QR.max_duration_video) {
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
}
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
return this.fileError('Audio not allowed');
}
} }
}; };
@ -8865,23 +8875,26 @@
delete this.filename; delete this.filename;
delete this.filesize; delete this.filesize;
this.nodes.el.title = null; this.nodes.el.title = null;
QR.nodes.fileContainer.title = ''; QR.nodes.filename.title = '';
this.nodes.el.style.backgroundImage = null; this.nodes.el.style.backgroundImage = null;
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = true; this.nodes.label.hidden = true;
} }
this.showFileData(); this.showFileData();
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors(function(error) {
return $.hasClass(error, 'file-error');
});
}; };
_Class.prototype.updateFilename = function() { _Class.prototype.updateFilename = function() {
var long; var long;
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear."; long = this.filename + " (" + this.filesize + ")";
this.nodes.el.title = long; this.nodes.el.title = long;
if (this !== QR.selected) { if (this !== QR.selected) {
return; return;
} }
return QR.nodes.fileContainer.title = long; return QR.nodes.filename.title = long;
}; };
_Class.prototype.showFileData = function() { _Class.prototype.showFileData = function() {
@ -8897,6 +8910,7 @@
_Class.prototype.pasteText = function(file) { _Class.prototype.pasteText = function(file) {
var reader; var reader;
this.pasting = true;
reader = new FileReader(); reader = new FileReader();
reader.onload = (function(_this) { reader.onload = (function(_this) {
return function(e) { return function(e) {
@ -8910,7 +8924,8 @@
if (QR.selected === _this) { if (QR.selected === _this) {
QR.nodes.com.value = _this.com; QR.nodes.com.value = _this.com;
} }
return _this.nodes.span.textContent = _this.com; _this.nodes.span.textContent = _this.com;
return delete _this.pasting;
}; };
})(this); })(this);
return reader.readAsText(file); return reader.readAsText(file);
@ -10165,7 +10180,7 @@
$.on(this.el, 'change', this.toggle); $.on(this.el, 'change', this.toggle);
return Header.menu.addEntry({ return Header.menu.addEntry({
el: prefetch, el: prefetch,
order: 104 order: 98
}); });
}, },
node: function() { node: function() {
@ -17019,9 +17034,6 @@
"body.hasDropDownNav{\n" + "body.hasDropDownNav{\n" +
" margin-top: 5px;\n" + " margin-top: 5px;\n" +
"}\n" + "}\n" +
"a {\n" +
" outline: none !important;\n" +
"}\n" +
".painted {\n" + ".painted {\n" +
" border-radius: 3px;\n" + " border-radius: 3px;\n" +
" padding: 0px 2px;\n" + " padding: 0px 2px;\n" +
@ -17666,7 +17678,7 @@
" text-align: center;\n" + " text-align: center;\n" +
"}\n" + "}\n" +
"/* /tg/ dice rolls */\n" + "/* /tg/ dice rolls */\n" +
".catalog-thread > .comment > b {\n" + ".board_tg .catalog-thread > .comment > b {\n" +
" font-weight: normal;\n" + " font-weight: normal;\n" +
"}\n" + "}\n" +
".catalog-code {\n" + ".catalog-code {\n" +
@ -18117,17 +18129,6 @@
" -webkit-flex-direction: row;\n" + " -webkit-flex-direction: row;\n" +
" flex-direction: row;\n" + " flex-direction: row;\n" +
"}\n" + "}\n" +
"#url-button, #custom-cooldown-button, #dump-button {\n" +
" width: 10%;\n" +
" margin: 0;\n" +
" margin-right: 4px;\n" +
" font: 13px sans-serif;\n" +
" padding: 1px 0px 2px;\n" +
" opacity: 0.6;\n" +
"}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
".persona .field {\n" + ".persona .field {\n" +
" -webkit-flex: 1;\n" + " -webkit-flex: 1;\n" +
" flex: 1;\n" + " flex: 1;\n" +
@ -18150,8 +18151,18 @@
" text-shadow: none !important;\n" + " text-shadow: none !important;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + "#qr textarea {\n" +
" min-width: 100%;\n" +
" resize: both;\n" + " resize: both;\n" +
"}\n" + "}\n" +
".field {\n" +
" -moz-box-sizing: border-box;\n" +
" margin: 0px;\n" +
" padding: 2px 4px 3px;\n" +
"}\n" +
"#qr label input[type=\"checkbox\"] {\n" +
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
"/* Noscript Recaptcha */\n" + "/* Noscript Recaptcha */\n" +
".captcha-img {\n" + ".captcha-img {\n" +
" margin: 0px;\n" + " margin: 0px;\n" +
@ -18195,111 +18206,81 @@
" display: block;\n" + " display: block;\n" +
" width: 100%;\n" + " width: 100%;\n" +
"}\n" + "}\n" +
".field {\n" + "/* File Input, Submit Button */\n" +
" -moz-box-sizing: border-box;\n" + "#file-n-submit {\n" +
" margin: 0px;\n" + " display: -webkit-flex;\n" +
" padding: 2px 4px 3px;\n" + " display: flex;\n" +
" -webkit-align-items: stretch;\n" +
" align-items: stretch;\n" +
" margin-top: 1px;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + ":root.gecko #file-n-submit > input {\n" +
" min-width: 100%;\n" + " margin: 0px -1px -1px;\n" +
"}\n" + "}\n" +
"#qr [type=\"submit\"] {\n" + "#file-n-submit input[type=\"submit\"] {\n" +
" width: 25%;\n" + " width: 25%;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
":root.webkit #qr [type=\"submit\"] {\n" + "#qr-filename-container {\n" +
" height: 24px;\n" + " -webkit-flex: 1 1 auto;\n" +
"}\n" + " flex: 1 1 auto;\n" +
"#qr label input[type=\"checkbox\"] {\n" + " width: 0;\n" +
" display: -webkit-flex;\n" +
" display: flex;\n" +
" -webkit-align-items: center;\n" +
" align-items: center;\n" +
" position: relative;\n" + " position: relative;\n" +
" top: 2px;\n" + " padding: 1px;\n" +
"}\n" + "}\n" +
"/* Fake File Input */\n" +
"input#qr-filename {\n" + "input#qr-filename {\n" +
" border: none !important;\n" + " border: none !important;\n" +
" width: 80%;\n" +
" padding: 0px 4px;\n" +
" position: relative;\n" +
" bottom: 1px;\n" +
" background: none !important;\n" + " background: none !important;\n" +
"}\n" + "}\n" +
"input#qr-filename:not(.edit) {\n" +
" pointer-events: none;\n" +
"}\n" +
"#qr-filename,\n" + "#qr-filename,\n" +
"#qr-filesize,\n" +
".has-file #qr-no-file {\n" + ".has-file #qr-no-file {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr-no-file,\n" + "#qr-no-file,\n" +
".has-file #qr-filename,\n" + ".has-file #qr-filename {\n" +
".has-file #qr-filesize {\n" + " -webkit-flex: 1 1 auto;\n" +
" flex: 1 1 auto;\n" +
" display: inline-block;\n" + " display: inline-block;\n" +
" margin: 0 0 2px;\n" + " padding: 0;\n" +
" padding-left: 3px;\n" +
" overflow: hidden;\n" + " overflow: hidden;\n" +
" text-overflow: ellipsis;\n" + " text-overflow: ellipsis;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
"#qr-no-file {\n" + "#qr-no-file {\n" +
" color: #AAA;\n" + " color: #AAA;\n" +
" padding: 1px 4px;\n" +
"}\n" +
"#qr-filename-container {\n" +
" -moz-box-sizing: border-box;\n" +
" display: inline-block;\n" +
" position: relative;\n" +
" width: 100px;\n" +
" min-width: 74.6%;\n" +
" max-width: 74.6%;\n" +
" margin-right: 0.4%;\n" +
" margin-top: 1px;\n" +
" overflow: hidden;\n" +
" padding: 2px 1px 0;\n" +
" height: 22px;\n" +
"}\n" +
"#qr-filename-container:hover {\n" +
" cursor: text;\n" +
"}\n" +
"#qr-extras-container {\n" +
" position: absolute;\n" +
" right: 0px;\n" +
"}\n" +
"#qr-filerm {\n" +
" margin-right: 3px;\n" +
" z-index: 2;\n" +
"}\n" +
"#file-n-submit {\n" +
" height: 23px;\n" +
"}\n" +
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" display: none;\n" +
"}\n" + "}\n" +
"#qr input[type=\"file\"] {\n" + "#qr input[type=\"file\"] {\n" +
" visibility: hidden;\n" + " visibility: hidden;\n" +
" position: absolute;\n" + " position: absolute;\n" +
"}\n" + "}\n" +
"/* Thread Select / Spoiler Label */\n" + "/* Spoiler Checkbox, QR Icons */\n" +
"#qr select[data-name=\"thread\"] {\n" + "#qr-spoiler-label, #qr-filename-container > a {\n" +
" float: right;\n" + " -webkit-flex: none;\n" +
" flex: none;\n" +
" margin: 0;\n" +
" margin-right: 3px;\n" +
" font: 13px sans-serif;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" + "#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
" width: 6.7%;\n" + ".has-file #url-button,\n" +
" min-width: 6.7%;\n" + "#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" max-width: 6.7%;\n" +
" display: inline-block;\n" +
" text-align: center;\n" +
" vertical-align: top;\n" +
"}\n" +
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-filename-container {\n" + "#qr-file-spoiler {\n" +
" max-width: 67.9%;\n" + " margin: 0;\n" +
" min-width: 67.9%;\n" +
"}\n" + "}\n" +
"#qr-spoiler-label input {\n" + "#url-button, #custom-cooldown-button, #dump-button {\n" +
" position: relative;\n" + " opacity: 0.6;\n" +
" top: 3px;\n" + "}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
"/* Thread Select */\n" +
"#qr select[data-name=\"thread\"] {\n" +
" float: right;\n" +
"}\n" + "}\n" +
"/* Dumping UI */\n" + "/* Dumping UI */\n" +
".dump #dump-list-container {\n" + ".dump #dump-list-container {\n" +

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.10.2.8 // @version 1.10.3.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.10.2.8 // @version 1.10.3.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -393,7 +393,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.2.8', VERSION: '1.10.3.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
NAME: '4chan X', NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@ -3066,7 +3066,7 @@
el: $.el('span', { el: $.el('span', {
textContent: 'Index Navigation' textContent: 'Index Navigation'
}), }),
order: 98, order: 100,
subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry] subEntries: [repliesEntry, pinEntry, anchorEntry, refNavEntry]
}); });
$.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode");
@ -6392,7 +6392,7 @@
$.on(this.threadNewLink.firstElementChild, 'click', this.rethread); $.on(this.threadNewLink.firstElementChild, 'click', this.rethread);
Header.menu.addEntry(this.entry = { Header.menu.addEntry(this.entry = {
el: this.controls, el: this.controls,
order: 98 order: 99
}); });
Thread.callbacks.push({ Thread.callbacks.push({
name: 'Quote Threading', name: 'Quote Threading',
@ -7169,6 +7169,7 @@
if (url === null) { if (url === null) {
return; return;
} }
QR.nodes.fileButton.focus();
return CrossOrigin.file(url, function(blob) { return CrossOrigin.file(url, function(blob) {
if (blob) { if (blob) {
return QR.handleFiles([blob]); return QR.handleFiles([blob]);
@ -7178,7 +7179,7 @@
}); });
}, },
handleFiles: function(files) { handleFiles: function(files) {
var file, i, k, len1; var file, k, len1;
if (this !== QR) { if (this !== QR) {
files = slice.call(this.files); files = slice.call(this.files);
this.value = null; this.value = null;
@ -7187,147 +7188,36 @@
return; return;
} }
QR.cleanNotifications(); QR.cleanNotifications();
for (i = k = 0, len1 = files.length; k < len1; i = ++k) { for (k = 0, len1 = files.length; k < len1; k++) {
file = files[i]; file = files[k];
QR.handleFile(file, i, files.length); QR.handleFile(file, files.length);
} }
if (files.length !== 1) { if (files.length !== 1) {
return $.addClass(QR.nodes.el, 'dump'); $.addClass(QR.nodes.el, 'dump');
}
if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) {
return QR.nodes.filename.focus();
} }
}, },
handleFile: function(file, index, nfiles) { handleFile: function(file, nfiles) {
var isNewPost, isSingle, max, post, ref; var isText, post;
isSingle = nfiles === 1; isText = /^text\//.test(file.type);
if (/^text\//.test(file.type)) { if (nfiles === 1) {
if (isSingle) { post = QR.selected;
post = QR.selected; } else {
} else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { post = QR.posts[QR.posts.length - 1];
if ((isText ? post.com || post.pasting : post.file)) {
post = new QR.post(); post = new QR.post();
} }
post.pasteText(file); }
return post[isText ? 'pasteText' : 'setFile'](file);
},
openFileInput: function() {
if (QR.nodes.fileButton.disabled) {
return; return;
} }
if (ref = file.type, indexOf.call(QR.mimeTypes, ref) < 0) { QR.nodes.fileInput.click();
QR.error(file.name + ": Unsupported file type."); return QR.nodes.fileButton.focus();
if (!isSingle) {
return;
}
}
max = QR.nodes.fileInput.max;
if (/^video\//.test(file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (file.size > max) {
QR.error(file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ").");
if (!isSingle) {
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();
}
return QR.checkDimensions(file, function(pass, el) {
if (pass || isSingle) {
return post.setFile(file, el);
} else if (isNewPost) {
post.rm();
if (el) {
return URL.revokeObjectURL(el.src);
}
}
});
},
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, img);
};
img.onerror = function() {
return cb(false, null);
};
return img.src = URL.createObjectURL(file);
} else if (/^video\//.test(file.type)) {
video = $.el('video');
$.on(video, 'loadeddata', function() {
var duration, max_height, max_width, pass, ref, 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(duration)) {
QR.error(file.name + ": Video lacks duration metadata (try remuxing)");
pass = false;
} else 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 (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(video)) {
QR.error(file.name + ": Audio not allowed");
pass = false;
}
cb(pass, video);
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");
}
URL.revokeObjectURL(file);
cb(false, null);
return cb = null;
});
return video.src = URL.createObjectURL(file);
} else {
return cb(true, null);
}
},
openFileInput: function(e) {
var ref;
e.stopPropagation();
if (e.shiftKey && e.type === 'click') {
return QR.selected.rmFile();
}
if ((e.ctrlKey || e.metaKey) && e.type === 'click') {
$.addClass(QR.nodes.filename, 'edit');
QR.nodes.filename.focus();
}
if (e.target.nodeName === 'INPUT' || (e.keyCode && ((ref = e.keyCode) !== 32 && ref !== 13)) || e.ctrlKey) {
return;
}
e.preventDefault();
return QR.nodes.fileInput.click();
}, },
generatePostableThreadsList: function() { generatePostableThreadsList: function() {
var k, len1, list, options, ref, thread, val; var k, len1, list, options, ref, thread, val;
@ -7358,7 +7248,7 @@
var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode; var dialog, event, i, items, m, match_max, match_min, name, node, nodes, ref, rules, save, setNode;
QR.nodes = nodes = { QR.nodes = nodes = {
el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', { el: dialog = UI.dialog('qr', 'top: 50px; right: 0px;', {
innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=file-n-submit><span id=qr-filename-container class=field tabindex=0><span id=qr-no-file>No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><span id=\"qr-extras-container\"><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span></span><label id=qr-spoiler-label><input type=checkbox id=qr-file-spoiler title='Spoiler image'></label><input type=submit></div><input type=file multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> " innerHTML: "<div class=move><label><input type=checkbox id=autohide title=Auto-hide>Quick Reply</label><a href=javascript:; class=close title=Close>×</a><select data-name=thread title='Create a new thread / Reply'><option value=new>New thread</option></select></div><form><div class=persona><input name=name data-name=name list=\"list-name\" placeholder=Name class=field size=1><input name=email data-name=email list=\"list-email\" placeholder=Options class=field size=1><input name=sub data-name=sub list=\"list-sub\" placeholder=Subject class=field size=1></div><div class=textarea><textarea data-name=com placeholder=Comment class=field></textarea><span id=char-count></span></div><div id=dump-list-container><div id=dump-list></div><a id=add-post href=javascript:; title=\"Add a post\">+</a></div><div id=\"file-n-submit\"><input type=\"button\" id=\"qr-file-button\" value=\"Files\"><span id=\"qr-filename-container\" class=\"field\"><span id=\"qr-no-file\">No selected file</span><input id=\"qr-filename\" data-name=\"filename\" spellcheck=\"false\"><label id=\"qr-spoiler-label\"><input type=\"checkbox\" id=\"qr-file-spoiler\" title=\"Spoiler image\"></label><a href=\"javascript:;\" id=\"qr-filerm\" title=\"Remove file\"><i class=\"fa fa-times-circle\"></i></a><a id=\"url-button\" title=\"Post from url\"><i class=\"fa fa-link\"></i></a><a id=\"custom-cooldown-button\" title=\"Toggle custom cooldown\" class=\"disabled\"><i class=\"fa fa-clock-o\"></i></a><a id=\"dump-button\" title=\"Dump list\"><i class=\"fa fa-plus-square\"></i></a></span><input type=\"submit\"></div><input type=\"file\" multiple></form><datalist id=\"list-name\"></datalist><datalist id=\"list-email\"></datalist><datalist id=\"list-sub\"></datalist> "
}) })
}; };
setNode = function(name, query) { setNode = function(name, query) {
@ -7380,10 +7270,10 @@
setNode('addPost', '#add-post'); setNode('addPost', '#add-post');
setNode('charCount', '#char-count'); setNode('charCount', '#char-count');
setNode('fileSubmit', '#file-n-submit'); setNode('fileSubmit', '#file-n-submit');
setNode('fileButton', '#qr-file-button');
setNode('noFile', '#qr-no-file');
setNode('filename', '#qr-filename'); setNode('filename', '#qr-filename');
setNode('fileContainer', '#qr-filename-container');
setNode('fileRM', '#qr-filerm'); setNode('fileRM', '#qr-filerm');
setNode('fileExtras', '#qr-extras-container');
setNode('spoiler', '#qr-file-spoiler'); setNode('spoiler', '#qr-file-spoiler');
setNode('spoilerPar', '#qr-spoiler-label'); setNode('spoilerPar', '#qr-spoiler-label');
setNode('status', '[type=submit]'); setNode('status', '[type=submit]');
@ -7437,7 +7327,8 @@
nodes.flashTag.dataset["default"] = '4'; nodes.flashTag.dataset["default"] = '4';
$.add(nodes.form, nodes.flashTag); $.add(nodes.form, nodes.flashTag);
} }
$.on(nodes.filename.parentNode, 'click keydown', QR.openFileInput); $.on(nodes.fileButton, 'click', QR.openFileInput);
$.on(nodes.noFile, 'click', QR.openFileInput);
$.on(nodes.autohide, 'change', QR.toggleHide); $.on(nodes.autohide, 'change', QR.toggleHide);
$.on(nodes.close, 'click', QR.close); $.on(nodes.close, 'click', QR.close);
$.on(nodes.dumpButton, 'click', function() { $.on(nodes.dumpButton, 'click', function() {
@ -7448,15 +7339,9 @@
return new QR.post(true); return new QR.post(true);
}); });
$.on(nodes.form, 'submit', QR.submit); $.on(nodes.form, 'submit', QR.submit);
$.on(nodes.filename, 'blur', function() {
return $.rmClass(this, 'edit');
});
$.on(nodes.fileRM, 'click', function() { $.on(nodes.fileRM, 'click', function() {
return QR.selected.rmFile(); return QR.selected.rmFile();
}); });
$.on(nodes.fileExtras, 'click', function(e) {
return e.stopPropagation();
});
$.on(nodes.spoiler, 'change', function() { $.on(nodes.spoiler, 'change', function() {
return QR.selected.nodes.spoiler.click(); return QR.selected.nodes.spoiler.click();
}); });
@ -7626,7 +7511,7 @@
return QR.status(); return QR.status();
}, },
response: function() { response: function() {
var URL, _, ban, captchasCount, err, h1, isReply, m, notif, post, postID, postsCount, ref, ref1, req, resDoc, threadID; var URL, _, ban, err, h1, isReply, m, post, postID, postsCount, ref, ref1, req, resDoc, threadID;
req = QR.req; req = QR.req;
delete QR.req; delete QR.req;
post = QR.posts[0]; post = QR.posts[0];
@ -7696,22 +7581,6 @@
}); });
postsCount = QR.posts.length - 1; postsCount = QR.posts.length - 1;
QR.cooldown.auto = postsCount && isReply; QR.cooldown.auto = postsCount && isReply;
if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) {
notif = new Notification('Quick reply warning', {
body: "You are running low on cached captchas. Cache count: " + captchasCount + ".",
icon: Favicon.logo
});
notif.onclick = function() {
QR.open();
window.focus();
return QR.captcha.setup(true);
};
notif.onshow = function() {
return setTimeout(function() {
return notif.close();
}, 7 * $.SECOND);
};
}
if (!(Conf['Persistent QR'] || postsCount)) { if (!(Conf['Persistent QR'] || postsCount)) {
QR.close(); QR.close();
} else { } else {
@ -8119,7 +7988,7 @@
return $.on(window, 'focus', function() { return $.on(window, 'focus', function() {
return $.queueTask(function() { return $.queueTask(function() {
var checkbox; var checkbox;
if (!(checkbox = $.id('recaptcha-anchor'))) { if (!(d.hasFocus() && (checkbox = $.id('recaptcha-anchor')))) {
return; return;
} }
if (d.activeElement !== checkbox) { if (d.activeElement !== checkbox) {
@ -8166,7 +8035,6 @@
if (!(this.isEnabled && (this.needed() || force))) { if (!(this.isEnabled && (this.needed() || force))) {
return; return;
} }
$.addClass(QR.nodes.el, 'captcha-open');
if (focus) { if (focus) {
this.shouldFocus = true; this.shouldFocus = true;
} }
@ -8210,6 +8078,7 @@
}, },
setupIFrame: function(iframe) { setupIFrame: function(iframe) {
this.setupTime = Date.now(); this.setupTime = Date.now();
$.addClass(QR.nodes.el, 'captcha-open');
if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) {
QR.nodes.el.style.top = null; QR.nodes.el.style.top = null;
QR.nodes.el.style.bottom = '0px'; QR.nodes.el.style.bottom = '0px';
@ -8693,7 +8562,8 @@
_Class.prototype["delete"] = function() { _Class.prototype["delete"] = function() {
$.rm(this.nodes.el); $.rm(this.nodes.el);
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors();
}; };
_Class.prototype.lock = function(lock) { _Class.prototype.lock = function(lock) {
@ -8713,7 +8583,6 @@
} }
} }
this.nodes.rm.style.visibility = lock ? 'hidden' : ''; this.nodes.rm.style.visibility = lock ? 'hidden' : '';
(lock ? $.off : $.on)(QR.nodes.filename.previousElementSibling, 'click', QR.openFileInput);
this.nodes.spoiler.disabled = lock; this.nodes.spoiler.disabled = lock;
return this.nodes.el.draggable = !lock; return this.nodes.el.draggable = !lock;
}; };
@ -8799,10 +8668,82 @@
} }
}; };
_Class.prototype.setFile = function(file1, el) { _Class.rmErrored = function(e) {
var error, errors, k, len1, post, q, ref;
e.stopPropagation();
ref = QR.posts;
for (k = ref.length - 1; k >= 0; k += -1) {
post = ref[k];
if (errors = post.errors) {
for (q = 0, len1 = errors.length; q < len1; q++) {
error = errors[q];
if (!(doc.contains(error))) {
continue;
}
post.rm();
break;
}
}
}
};
_Class.prototype.error = function(className, message) {
var div, ref, rm, rmAll;
div = $.el('div', {
className: className
});
$.extend(div, {
innerHTML: E(message) + "<br>[<a href=\"javascript:;\">delete</a>] [<a href=\"javascript:;\">delete all</a>]"
});
(this.errors || (this.errors = [])).push(div);
ref = $$('a', div), rm = ref[0], rmAll = ref[1];
$.on(div, 'click', (function(_this) {
return function() {
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.select();
}
};
})(this));
$.on(rm, 'click', (function(_this) {
return function(e) {
e.stopPropagation();
if (indexOf.call(QR.posts, _this) >= 0) {
return _this.rm();
}
};
})(this));
$.on(rmAll, 'click', QR.post.rmErrored);
return QR.error(div);
};
_Class.prototype.fileError = function(message) {
return this.error('file-error', this.filename + ": " + message);
};
_Class.prototype.dismissErrors = function(test) {
var error, k, len1, ref;
if (test == null) {
test = function() {
return true;
};
}
if (this.errors) {
ref = this.errors;
for (k = 0, len1 = ref.length; k < len1; k++) {
error = ref[k];
if (doc.contains(error) && test(error)) {
error.parentNode.previousElementSibling.click();
}
}
}
};
_Class.prototype.setFile = function(file1) {
var ref;
this.file = file1; this.file = file1;
this.filename = this.file.name; this.filename = this.file.name;
this.filesize = $.bytesToString(this.file.size); this.filesize = $.bytesToString(this.file.size);
this.checkSize();
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = false; this.nodes.label.hidden = false;
} }
@ -8813,10 +8754,79 @@
} else { } else {
this.updateFilename(); this.updateFilename();
} }
if (el) { this.nodes.el.style.backgroundImage = null;
return this.setThumbnail(el); if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) {
return this.fileError('Unsupported file type.');
} else if (/^(image|video)\//.test(this.file.type)) {
return this.readFile();
}
};
_Class.prototype.checkSize = function() {
var max;
max = QR.nodes.fileInput.max;
if (/^video\//.test(this.file.type)) {
max = Math.min(max, QR.max_size_video);
}
if (this.file.size > max) {
return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ").");
}
};
_Class.prototype.readFile = function() {
var el, event, isVideo, onerror, onload;
isVideo = /^video\//.test(this.file.type);
el = $.el(isVideo ? 'video' : 'img');
event = isVideo ? 'loadeddata' : 'load';
onload = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.checkDimensions(el);
return _this.setThumbnail(el);
};
})(this);
onerror = (function(_this) {
return function() {
$.off(el, event, onload);
$.off(el, 'error', onerror);
_this.fileError((isVideo ? 'Video' : 'Image') + " appears corrupt");
return URL.revokeObjectURL(el.src);
};
})(this);
$.on(el, event, onload);
$.on(el, 'error', onerror);
return el.src = URL.createObjectURL(this.file);
};
_Class.prototype.checkDimensions = function(el) {
var duration, height, max_height, max_width, ref, videoHeight, videoWidth, width;
if (el.tagName === 'IMG') {
height = el.height, width = el.width;
if (height > QR.max_height || width > QR.max_width) {
this.fileError("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) {
return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
} else { } else {
return this.nodes.el.style.backgroundImage = null; videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.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) {
this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)");
}
if (videoHeight < QR.min_height || videoWidth < QR.min_width) {
this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)");
}
if (!isFinite(duration)) {
this.fileError('Video lacks duration metadata (try remuxing)');
} else if (duration > QR.max_duration_video) {
this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)");
}
if (((ref = g.BOARD.ID) !== 'gif' && ref !== 'wsg') && $.hasAudio(el)) {
return this.fileError('Audio not allowed');
}
} }
}; };
@ -8866,23 +8876,26 @@
delete this.filename; delete this.filename;
delete this.filesize; delete this.filesize;
this.nodes.el.title = null; this.nodes.el.title = null;
QR.nodes.fileContainer.title = ''; QR.nodes.filename.title = '';
this.nodes.el.style.backgroundImage = null; this.nodes.el.style.backgroundImage = null;
if (QR.spoiler) { if (QR.spoiler) {
this.nodes.label.hidden = true; this.nodes.label.hidden = true;
} }
this.showFileData(); this.showFileData();
return URL.revokeObjectURL(this.URL); URL.revokeObjectURL(this.URL);
return this.dismissErrors(function(error) {
return $.hasClass(error, 'file-error');
});
}; };
_Class.prototype.updateFilename = function() { _Class.prototype.updateFilename = function() {
var long; var long;
long = this.filename + " (" + this.filesize + ")\nCtrl/\u2318+click to edit filename. Shift+click to clear."; long = this.filename + " (" + this.filesize + ")";
this.nodes.el.title = long; this.nodes.el.title = long;
if (this !== QR.selected) { if (this !== QR.selected) {
return; return;
} }
return QR.nodes.fileContainer.title = long; return QR.nodes.filename.title = long;
}; };
_Class.prototype.showFileData = function() { _Class.prototype.showFileData = function() {
@ -8898,6 +8911,7 @@
_Class.prototype.pasteText = function(file) { _Class.prototype.pasteText = function(file) {
var reader; var reader;
this.pasting = true;
reader = new FileReader(); reader = new FileReader();
reader.onload = (function(_this) { reader.onload = (function(_this) {
return function(e) { return function(e) {
@ -8911,7 +8925,8 @@
if (QR.selected === _this) { if (QR.selected === _this) {
QR.nodes.com.value = _this.com; QR.nodes.com.value = _this.com;
} }
return _this.nodes.span.textContent = _this.com; _this.nodes.span.textContent = _this.com;
return delete _this.pasting;
}; };
})(this); })(this);
return reader.readAsText(file); return reader.readAsText(file);
@ -10166,7 +10181,7 @@
$.on(this.el, 'change', this.toggle); $.on(this.el, 'change', this.toggle);
return Header.menu.addEntry({ return Header.menu.addEntry({
el: prefetch, el: prefetch,
order: 104 order: 98
}); });
}, },
node: function() { node: function() {
@ -17020,9 +17035,6 @@
"body.hasDropDownNav{\n" + "body.hasDropDownNav{\n" +
" margin-top: 5px;\n" + " margin-top: 5px;\n" +
"}\n" + "}\n" +
"a {\n" +
" outline: none !important;\n" +
"}\n" +
".painted {\n" + ".painted {\n" +
" border-radius: 3px;\n" + " border-radius: 3px;\n" +
" padding: 0px 2px;\n" + " padding: 0px 2px;\n" +
@ -17667,7 +17679,7 @@
" text-align: center;\n" + " text-align: center;\n" +
"}\n" + "}\n" +
"/* /tg/ dice rolls */\n" + "/* /tg/ dice rolls */\n" +
".catalog-thread > .comment > b {\n" + ".board_tg .catalog-thread > .comment > b {\n" +
" font-weight: normal;\n" + " font-weight: normal;\n" +
"}\n" + "}\n" +
".catalog-code {\n" + ".catalog-code {\n" +
@ -18118,17 +18130,6 @@
" -webkit-flex-direction: row;\n" + " -webkit-flex-direction: row;\n" +
" flex-direction: row;\n" + " flex-direction: row;\n" +
"}\n" + "}\n" +
"#url-button, #custom-cooldown-button, #dump-button {\n" +
" width: 10%;\n" +
" margin: 0;\n" +
" margin-right: 4px;\n" +
" font: 13px sans-serif;\n" +
" padding: 1px 0px 2px;\n" +
" opacity: 0.6;\n" +
"}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
".persona .field {\n" + ".persona .field {\n" +
" -webkit-flex: 1;\n" + " -webkit-flex: 1;\n" +
" flex: 1;\n" + " flex: 1;\n" +
@ -18151,8 +18152,18 @@
" text-shadow: none !important;\n" + " text-shadow: none !important;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + "#qr textarea {\n" +
" min-width: 100%;\n" +
" resize: both;\n" + " resize: both;\n" +
"}\n" + "}\n" +
".field {\n" +
" -moz-box-sizing: border-box;\n" +
" margin: 0px;\n" +
" padding: 2px 4px 3px;\n" +
"}\n" +
"#qr label input[type=\"checkbox\"] {\n" +
" position: relative;\n" +
" top: 2px;\n" +
"}\n" +
"/* Noscript Recaptcha */\n" + "/* Noscript Recaptcha */\n" +
".captcha-img {\n" + ".captcha-img {\n" +
" margin: 0px;\n" + " margin: 0px;\n" +
@ -18196,111 +18207,81 @@
" display: block;\n" + " display: block;\n" +
" width: 100%;\n" + " width: 100%;\n" +
"}\n" + "}\n" +
".field {\n" + "/* File Input, Submit Button */\n" +
" -moz-box-sizing: border-box;\n" + "#file-n-submit {\n" +
" margin: 0px;\n" + " display: -webkit-flex;\n" +
" padding: 2px 4px 3px;\n" + " display: flex;\n" +
" -webkit-align-items: stretch;\n" +
" align-items: stretch;\n" +
" margin-top: 1px;\n" +
"}\n" + "}\n" +
"#qr textarea {\n" + ":root.gecko #file-n-submit > input {\n" +
" min-width: 100%;\n" + " margin: 0px -1px -1px;\n" +
"}\n" + "}\n" +
"#qr [type=\"submit\"] {\n" + "#file-n-submit input[type=\"submit\"] {\n" +
" width: 25%;\n" + " width: 25%;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
":root.webkit #qr [type=\"submit\"] {\n" + "#qr-filename-container {\n" +
" height: 24px;\n" + " -webkit-flex: 1 1 auto;\n" +
"}\n" + " flex: 1 1 auto;\n" +
"#qr label input[type=\"checkbox\"] {\n" + " width: 0;\n" +
" display: -webkit-flex;\n" +
" display: flex;\n" +
" -webkit-align-items: center;\n" +
" align-items: center;\n" +
" position: relative;\n" + " position: relative;\n" +
" top: 2px;\n" + " padding: 1px;\n" +
"}\n" + "}\n" +
"/* Fake File Input */\n" +
"input#qr-filename {\n" + "input#qr-filename {\n" +
" border: none !important;\n" + " border: none !important;\n" +
" width: 80%;\n" +
" padding: 0px 4px;\n" +
" position: relative;\n" +
" bottom: 1px;\n" +
" background: none !important;\n" + " background: none !important;\n" +
"}\n" + "}\n" +
"input#qr-filename:not(.edit) {\n" +
" pointer-events: none;\n" +
"}\n" +
"#qr-filename,\n" + "#qr-filename,\n" +
"#qr-filesize,\n" +
".has-file #qr-no-file {\n" + ".has-file #qr-no-file {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr-no-file,\n" + "#qr-no-file,\n" +
".has-file #qr-filename,\n" + ".has-file #qr-filename {\n" +
".has-file #qr-filesize {\n" + " -webkit-flex: 1 1 auto;\n" +
" flex: 1 1 auto;\n" +
" display: inline-block;\n" + " display: inline-block;\n" +
" margin: 0 0 2px;\n" + " padding: 0;\n" +
" padding-left: 3px;\n" +
" overflow: hidden;\n" + " overflow: hidden;\n" +
" text-overflow: ellipsis;\n" + " text-overflow: ellipsis;\n" +
" vertical-align: top;\n" +
"}\n" + "}\n" +
"#qr-no-file {\n" + "#qr-no-file {\n" +
" color: #AAA;\n" + " color: #AAA;\n" +
" padding: 1px 4px;\n" +
"}\n" +
"#qr-filename-container {\n" +
" -moz-box-sizing: border-box;\n" +
" display: inline-block;\n" +
" position: relative;\n" +
" width: 100px;\n" +
" min-width: 74.6%;\n" +
" max-width: 74.6%;\n" +
" margin-right: 0.4%;\n" +
" margin-top: 1px;\n" +
" overflow: hidden;\n" +
" padding: 2px 1px 0;\n" +
" height: 22px;\n" +
"}\n" +
"#qr-filename-container:hover {\n" +
" cursor: text;\n" +
"}\n" +
"#qr-extras-container {\n" +
" position: absolute;\n" +
" right: 0px;\n" +
"}\n" +
"#qr-filerm {\n" +
" margin-right: 3px;\n" +
" z-index: 2;\n" +
"}\n" +
"#file-n-submit {\n" +
" height: 23px;\n" +
"}\n" +
"#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" display: none;\n" +
"}\n" + "}\n" +
"#qr input[type=\"file\"] {\n" + "#qr input[type=\"file\"] {\n" +
" visibility: hidden;\n" + " visibility: hidden;\n" +
" position: absolute;\n" + " position: absolute;\n" +
"}\n" + "}\n" +
"/* Thread Select / Spoiler Label */\n" + "/* Spoiler Checkbox, QR Icons */\n" +
"#qr select[data-name=\"thread\"] {\n" + "#qr-spoiler-label, #qr-filename-container > a {\n" +
" float: right;\n" + " -webkit-flex: none;\n" +
" flex: none;\n" +
" margin: 0;\n" +
" margin-right: 3px;\n" +
" font: 13px sans-serif;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-spoiler-label {\n" + "#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label,\n" +
" width: 6.7%;\n" + ".has-file #url-button,\n" +
" min-width: 6.7%;\n" + "#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n" +
" max-width: 6.7%;\n" +
" display: inline-block;\n" +
" text-align: center;\n" +
" vertical-align: top;\n" +
"}\n" +
"#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\n" +
" display: none;\n" + " display: none;\n" +
"}\n" + "}\n" +
"#qr.has-spoiler .has-file #qr-filename-container {\n" + "#qr-file-spoiler {\n" +
" max-width: 67.9%;\n" + " margin: 0;\n" +
" min-width: 67.9%;\n" +
"}\n" + "}\n" +
"#qr-spoiler-label input {\n" + "#url-button, #custom-cooldown-button, #dump-button {\n" +
" position: relative;\n" + " opacity: 0.6;\n" +
" top: 3px;\n" + "}\n" +
"#custom-cooldown-button.disabled {\n" +
" opacity: 0.27;\n" +
"}\n" +
"/* Thread Select */\n" +
"#qr select[data-name=\"thread\"] {\n" +
" float: right;\n" +
"}\n" + "}\n" +
"/* Dumping UI */\n" + "/* Dumping UI */\n" +
".dump #dump-list-container {\n" + ".dump #dump-list-container {\n" +

Binary file not shown.

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'> <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'> <app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.10.2.8' /> <updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X-beta.crx' version='1.10.3.0' />
</app> </app>
</gupdate> </gupdate>

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'> <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='lacclbnghgdicfifcamcmcnilckjamag'> <app appid='lacclbnghgdicfifcamcmcnilckjamag'>
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.10.2.8' /> <updatecheck codebase='https://ccd0.github.io/4chan-x/builds/4chan-X.crx' version='1.10.3.0' />
</app> </app>
</gupdate> </gupdate>

View File

@ -3,7 +3,7 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.", "description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": { "meta": {
"name": "4chan X", "name": "4chan X",
"version": "1.10.2.8", "version": "1.10.3.0",
"repo": "https://github.com/ccd0/4chan-x/", "repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x", "page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/", "downloads": "https://ccd0.github.io/4chan-x/builds/",