Merge branch 'v3'
Conflicts: CHANGELOG.md LICENSE builds/4chan-X.js builds/4chan-X.meta.js builds/4chan-X.user.js builds/crx/manifest.json builds/crx/script.js latest.js package.json src/General/Main.coffee src/General/css/style.css src/Posting/QuickReply.coffee
This commit is contained in:
commit
70d1d758ec
@ -9,6 +9,9 @@
|
|||||||
**zixaphir**:
|
**zixaphir**:
|
||||||
- Make new archive selection not depend on a JSON file
|
- Make new archive selection not depend on a JSON file
|
||||||
- Remove some code that sends user errors back to us (we didn't have a working link anyway)
|
- Remove some code that sends user errors back to us (we didn't have a working link anyway)
|
||||||
|
- Add board selection to archiver options
|
||||||
|
- Fix bug where image hover would close when hitting Enter while typing
|
||||||
|
- Add `Quoted Title` option which adds (!) text to title when user is quoted
|
||||||
|
|
||||||
### v2.0.3
|
### v2.0.3
|
||||||
*2013-05-10*
|
*2013-05-10*
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* appchan x - Version 2.0.3 - 2013-05-14
|
* appchan x - Version 2.0.3 - 2013-05-15
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* appchan x - Version 2.0.3 - 2013-05-14
|
* appchan x - Version 2.0.3 - 2013-05-15
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
@ -202,7 +202,8 @@
|
|||||||
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
||||||
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
||||||
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
||||||
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.']
|
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.'],
|
||||||
|
'Captcha Warning Notifications': [true, 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.']
|
||||||
},
|
},
|
||||||
'Quote Links': {
|
'Quote Links': {
|
||||||
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
||||||
@ -214,7 +215,7 @@
|
|||||||
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
||||||
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
||||||
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
||||||
'Quoted Title': ['Change the page title to reflect you\'ve been quoted.', false],
|
'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.'],
|
||||||
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
||||||
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
||||||
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
||||||
@ -2579,7 +2580,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\npadding-left: 20px;\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
||||||
},
|
},
|
||||||
"Frost": {
|
"Frost": {
|
||||||
"Author": "Zixaphir",
|
"Author": "Zixaphir",
|
||||||
@ -2630,7 +2631,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\n padding-left: 20px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3621,12 +3622,18 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
DataBoard.prototype.clean = function() {
|
DataBoard.prototype.clean = function() {
|
||||||
var boardID, now;
|
var boardID, now, val, _ref;
|
||||||
|
|
||||||
for (boardID in this.data.boards) {
|
_ref = this.data.boards;
|
||||||
this.deleteIfEmpty({
|
for (boardID in _ref) {
|
||||||
boardID: boardID
|
val = _ref[boardID];
|
||||||
});
|
if (!val) {
|
||||||
|
delete this.data.boards[boardID];
|
||||||
|
} else {
|
||||||
|
this.deleteIfEmpty({
|
||||||
|
boardID: boardID
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
||||||
@ -4925,6 +4932,10 @@
|
|||||||
}
|
}
|
||||||
for (key in Config.filter) {
|
for (key in Config.filter) {
|
||||||
this.filters[key] = [];
|
this.filters[key] = [];
|
||||||
|
if (Conf[key] === void 0) {
|
||||||
|
$["delete"](key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ref = Conf[key].split('\n');
|
_ref = Conf[key].split('\n');
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
filter = _ref[_i];
|
filter = _ref[_i];
|
||||||
@ -6975,6 +6986,9 @@
|
|||||||
QR.cleanNotifications();
|
QR.cleanNotifications();
|
||||||
d.activeElement.blur();
|
d.activeElement.blur();
|
||||||
$.rmClass(QR.nodes.el, 'dump');
|
$.rmClass(QR.nodes.el, 'dump');
|
||||||
|
if (!Conf['Captcha Warning Notifications']) {
|
||||||
|
$.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
}
|
||||||
if (Conf['QR Shortcut']) {
|
if (Conf['QR Shortcut']) {
|
||||||
$.toggleClass($('.qr-shortcut'), 'disabled');
|
$.toggleClass($('.qr-shortcut'), 'disabled');
|
||||||
}
|
}
|
||||||
@ -7020,6 +7034,16 @@
|
|||||||
}
|
}
|
||||||
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
||||||
QR.captcha.nodes.input.focus();
|
QR.captcha.nodes.input.focus();
|
||||||
|
if (Conf['Captcha Warning Notifications']) {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
|
} else {
|
||||||
|
$.addClass(QR.captcha.nodes.input, 'error');
|
||||||
|
$.on(QR.captcha.nodes.input, 'keydown', function() {
|
||||||
|
return $.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
}
|
}
|
||||||
if (d.hidden) {
|
if (d.hidden) {
|
||||||
alert(el.textContent);
|
alert(el.textContent);
|
||||||
@ -8121,13 +8145,13 @@
|
|||||||
err = 'No valid captcha.';
|
err = 'No valid captcha.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QR.cleanNotifications();
|
||||||
if (err) {
|
if (err) {
|
||||||
QR.cooldown.auto = false;
|
QR.cooldown.auto = false;
|
||||||
QR.status();
|
QR.status();
|
||||||
QR.error(err);
|
QR.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QR.cleanNotifications();
|
|
||||||
QR.cooldown.auto = QR.posts.length > 1;
|
QR.cooldown.auto = QR.posts.length > 1;
|
||||||
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
||||||
QR.hide();
|
QR.hide();
|
||||||
@ -9847,13 +9871,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unread.addPosts(posts);
|
Unread.addPosts(posts);
|
||||||
if (!Conf['Scroll to Last Read Post']) {
|
if (Conf['Scroll to Last Read Post']) {
|
||||||
return;
|
return Unread.scroll();
|
||||||
}
|
}
|
||||||
return Unread.scroll();
|
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var hash, onload, post, posts, prevID, root;
|
var hash, post, posts, prevID, root;
|
||||||
|
|
||||||
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
||||||
return;
|
return;
|
||||||
@ -9870,17 +9893,11 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onload = function() {
|
root.scrollIntoView(false);
|
||||||
return root.scrollIntoView(false);
|
return;
|
||||||
};
|
|
||||||
} else {
|
|
||||||
posts = Object.keys(Unread.thread.posts);
|
|
||||||
post = Unread.thread.posts[posts[posts.length - 1]];
|
|
||||||
onload = function() {
|
|
||||||
return Header.scrollToPost(post.nodes.root);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return $.on(window, 'load', onload);
|
posts = Object.keys(Unread.thread.posts);
|
||||||
|
return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var lastReadPost;
|
||||||
@ -13120,7 +13137,7 @@
|
|||||||
|
|
||||||
Sauce = {
|
Sauce = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var link, links, _i, _len, _ref;
|
var err, link, links, _i, _len, _ref;
|
||||||
|
|
||||||
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
||||||
return;
|
return;
|
||||||
@ -13132,7 +13149,12 @@
|
|||||||
if (link[0] === '#') {
|
if (link[0] === '#') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
links.push(this.createSauceLink(link.trim()));
|
try {
|
||||||
|
links.push(this.createSauceLink(link.trim()));
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!links.length) {
|
if (!links.length) {
|
||||||
return;
|
return;
|
||||||
@ -13546,6 +13568,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
$.get(Conf, function(Conf) {
|
$.get(Conf, function(Conf) {
|
||||||
|
delete Conf['archives'];
|
||||||
data.Conf = Conf;
|
data.Conf = Conf;
|
||||||
return Settings["export"](now, data);
|
return Settings["export"](now, data);
|
||||||
});
|
});
|
||||||
@ -14500,6 +14523,9 @@
|
|||||||
Conf = items;
|
Conf = items;
|
||||||
pathname = location.pathname.split('/');
|
pathname = location.pathname.split('/');
|
||||||
g.BOARD = new Board(pathname[1]);
|
g.BOARD = new Board(pathname[1]);
|
||||||
|
if (g.BOARD.ID === 'z') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g.VIEW = (function() {
|
g.VIEW = (function() {
|
||||||
switch (pathname[2]) {
|
switch (pathname[2]) {
|
||||||
case 'res':
|
case 'res':
|
||||||
@ -14698,6 +14724,12 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
localStorage.getItem('4chan-settings');
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
new Notification('warning', 'Cookies need to be enabled on 4chan for appchan x to properly function.', 30);
|
||||||
|
}
|
||||||
$.event('4chanXInitFinished');
|
$.event('4chanXInitFinished');
|
||||||
return Main.checkUpdate();
|
return Main.checkUpdate();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* appchan x - Version 2.0.3 - 2013-05-14
|
* appchan x - Version 2.0.3 - 2013-05-15
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
@ -203,7 +203,8 @@
|
|||||||
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
||||||
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
||||||
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
||||||
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.']
|
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.'],
|
||||||
|
'Captcha Warning Notifications': [true, 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.']
|
||||||
},
|
},
|
||||||
'Quote Links': {
|
'Quote Links': {
|
||||||
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
||||||
@ -215,7 +216,7 @@
|
|||||||
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
||||||
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
||||||
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
||||||
'Quoted Title': ['Change the page title to reflect you\'ve been quoted.', false],
|
'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.'],
|
||||||
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
||||||
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
||||||
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
||||||
@ -2576,7 +2577,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\npadding-left: 20px;\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
||||||
},
|
},
|
||||||
"Frost": {
|
"Frost": {
|
||||||
"Author": "Zixaphir",
|
"Author": "Zixaphir",
|
||||||
@ -2627,7 +2628,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\n padding-left: 20px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3617,12 +3618,18 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
DataBoard.prototype.clean = function() {
|
DataBoard.prototype.clean = function() {
|
||||||
var boardID, now;
|
var boardID, now, val, _ref;
|
||||||
|
|
||||||
for (boardID in this.data.boards) {
|
_ref = this.data.boards;
|
||||||
this.deleteIfEmpty({
|
for (boardID in _ref) {
|
||||||
boardID: boardID
|
val = _ref[boardID];
|
||||||
});
|
if (!val) {
|
||||||
|
delete this.data.boards[boardID];
|
||||||
|
} else {
|
||||||
|
this.deleteIfEmpty({
|
||||||
|
boardID: boardID
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
||||||
@ -4921,6 +4928,10 @@
|
|||||||
}
|
}
|
||||||
for (key in Config.filter) {
|
for (key in Config.filter) {
|
||||||
this.filters[key] = [];
|
this.filters[key] = [];
|
||||||
|
if (Conf[key] === void 0) {
|
||||||
|
$["delete"](key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ref = Conf[key].split('\n');
|
_ref = Conf[key].split('\n');
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
filter = _ref[_i];
|
filter = _ref[_i];
|
||||||
@ -6959,6 +6970,9 @@
|
|||||||
QR.cleanNotifications();
|
QR.cleanNotifications();
|
||||||
d.activeElement.blur();
|
d.activeElement.blur();
|
||||||
$.rmClass(QR.nodes.el, 'dump');
|
$.rmClass(QR.nodes.el, 'dump');
|
||||||
|
if (!Conf['Captcha Warning Notifications']) {
|
||||||
|
$.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
}
|
||||||
if (Conf['QR Shortcut']) {
|
if (Conf['QR Shortcut']) {
|
||||||
$.toggleClass($('.qr-shortcut'), 'disabled');
|
$.toggleClass($('.qr-shortcut'), 'disabled');
|
||||||
}
|
}
|
||||||
@ -7004,6 +7018,16 @@
|
|||||||
}
|
}
|
||||||
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
||||||
QR.captcha.nodes.input.focus();
|
QR.captcha.nodes.input.focus();
|
||||||
|
if (Conf['Captcha Warning Notifications']) {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
|
} else {
|
||||||
|
$.addClass(QR.captcha.nodes.input, 'error');
|
||||||
|
$.on(QR.captcha.nodes.input, 'keydown', function() {
|
||||||
|
return $.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
}
|
}
|
||||||
if (d.hidden) {
|
if (d.hidden) {
|
||||||
alert(el.textContent);
|
alert(el.textContent);
|
||||||
@ -8131,13 +8155,13 @@
|
|||||||
err = 'No valid captcha.';
|
err = 'No valid captcha.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QR.cleanNotifications();
|
||||||
if (err) {
|
if (err) {
|
||||||
QR.cooldown.auto = false;
|
QR.cooldown.auto = false;
|
||||||
QR.status();
|
QR.status();
|
||||||
QR.error(err);
|
QR.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QR.cleanNotifications();
|
|
||||||
QR.cooldown.auto = QR.posts.length > 1;
|
QR.cooldown.auto = QR.posts.length > 1;
|
||||||
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
||||||
QR.hide();
|
QR.hide();
|
||||||
@ -9856,13 +9880,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unread.addPosts(posts);
|
Unread.addPosts(posts);
|
||||||
if (!Conf['Scroll to Last Read Post']) {
|
if (Conf['Scroll to Last Read Post']) {
|
||||||
return;
|
return Unread.scroll();
|
||||||
}
|
}
|
||||||
return Unread.scroll();
|
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var hash, onload, post, posts, prevID, root;
|
var hash, post, posts, prevID, root;
|
||||||
|
|
||||||
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
||||||
return;
|
return;
|
||||||
@ -9879,17 +9902,11 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onload = function() {
|
root.scrollIntoView(false);
|
||||||
return root.scrollIntoView(false);
|
return;
|
||||||
};
|
|
||||||
} else {
|
|
||||||
posts = Object.keys(Unread.thread.posts);
|
|
||||||
post = Unread.thread.posts[posts[posts.length - 1]];
|
|
||||||
onload = function() {
|
|
||||||
return Header.scrollToPost(post.nodes.root);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return $.on(window, 'load', onload);
|
posts = Object.keys(Unread.thread.posts);
|
||||||
|
return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var lastReadPost;
|
||||||
@ -13129,7 +13146,7 @@
|
|||||||
|
|
||||||
Sauce = {
|
Sauce = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var link, links, _i, _len, _ref;
|
var err, link, links, _i, _len, _ref;
|
||||||
|
|
||||||
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
||||||
return;
|
return;
|
||||||
@ -13141,7 +13158,12 @@
|
|||||||
if (link[0] === '#') {
|
if (link[0] === '#') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
links.push(this.createSauceLink(link.trim()));
|
try {
|
||||||
|
links.push(this.createSauceLink(link.trim()));
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!links.length) {
|
if (!links.length) {
|
||||||
return;
|
return;
|
||||||
@ -13555,6 +13577,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
$.get(Conf, function(Conf) {
|
$.get(Conf, function(Conf) {
|
||||||
|
delete Conf['archives'];
|
||||||
data.Conf = Conf;
|
data.Conf = Conf;
|
||||||
return Settings["export"](now, data);
|
return Settings["export"](now, data);
|
||||||
});
|
});
|
||||||
@ -14507,6 +14530,9 @@
|
|||||||
Conf = items;
|
Conf = items;
|
||||||
pathname = location.pathname.split('/');
|
pathname = location.pathname.split('/');
|
||||||
g.BOARD = new Board(pathname[1]);
|
g.BOARD = new Board(pathname[1]);
|
||||||
|
if (g.BOARD.ID === 'z') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g.VIEW = (function() {
|
g.VIEW = (function() {
|
||||||
switch (pathname[2]) {
|
switch (pathname[2]) {
|
||||||
case 'res':
|
case 'res':
|
||||||
@ -14705,6 +14731,12 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
localStorage.getItem('4chan-settings');
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
new Notification('warning', 'Cookies need to be enabled on 4chan for appchan x to properly function.', 30);
|
||||||
|
}
|
||||||
$.event('4chanXInitFinished');
|
$.event('4chanXInitFinished');
|
||||||
return Main.checkUpdate();
|
return Main.checkUpdate();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Generated by CoffeeScript
|
// Generated by CoffeeScript
|
||||||
/*
|
/*
|
||||||
* appchan x - Version 2.0.3 - 2013-05-14
|
* appchan x - Version 2.0.3 - 2013-05-15
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
@ -183,7 +183,8 @@
|
|||||||
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
'Remember QR Size': [false, 'Remember the size of the quick reply\'s comment field.'],
|
||||||
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
'Cooldown': [true, 'Indicate the remaining time before posting again.'],
|
||||||
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
'Cooldown Prediction': [true, 'Decrease the cooldown time by taking into account upload speed. Disable it if it\'s inaccurate for you.'],
|
||||||
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.']
|
'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.'],
|
||||||
|
'Captcha Warning Notifications': [true, 'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.']
|
||||||
},
|
},
|
||||||
'Quote Links': {
|
'Quote Links': {
|
||||||
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
'Quote Backlinks': [true, 'Add quote backlinks.'],
|
||||||
@ -195,7 +196,7 @@
|
|||||||
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
'Quote Highlighting': [true, 'Highlight the previewed post.'],
|
||||||
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
'Resurrect Quotes': [true, 'Link dead quotes to the archives.'],
|
||||||
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.'],
|
||||||
'Quoted Title': ['Change the page title to reflect you\'ve been quoted.', false],
|
'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.'],
|
||||||
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
'Highlight Posts Quoting You': [false, 'Highlights any posts that contain a quote to your post.'],
|
||||||
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
'Highlight Own Posts': [false, 'Highlights own posts if Mark Quotes of You is enabled.'],
|
||||||
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'],
|
||||||
@ -2556,7 +2557,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\npadding-left: 20px;\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\npadding: 2px;\nbox-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3) inset, rgba(70,70,70,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, 0.2) inset, rgba(70,70,70,.3) 1px 1px;\n}\n#qr .selectrice {\nbox-shadow: none;\n}\n#header-bar {\npadding: 1px 3px;\n}\n.dialog {\nbox-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);\n}\n.threadContainer {\nborder: none;\nbox-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;\npadding: 2px 0;\nmargin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\nbox-shadow:inset rgba(0,0,0,.2) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\ntransition:background .2s,box-shadow .2s;\n}"
|
||||||
},
|
},
|
||||||
"Frost": {
|
"Frost": {
|
||||||
"Author": "Zixaphir",
|
"Author": "Zixaphir",
|
||||||
@ -2607,7 +2608,7 @@
|
|||||||
"Timestamps": "rgb(100,100,100)",
|
"Timestamps": "rgb(100,100,100)",
|
||||||
"Warnings": "rgb(215,0,0)",
|
"Warnings": "rgb(215,0,0)",
|
||||||
"Shadow Color": "rgba(0,0,0,.1)",
|
"Shadow Color": "rgba(0,0,0,.1)",
|
||||||
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.thread > .replyContainer\n.threadContainer > .replyContainer {\n padding-left: 20px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
"Custom CSS": ".thread {\n padding: 2px;\n box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n#header-bar,\ninput,\ntextarea,\n.field,\n.inline .op,\n.pagelist,\n.prettyprint,\n.post.reply,\n.rice,\n.selectrice {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.8) 1px 1px;\n}\n#qr .selectrice {\n box-shadow: none;\n}\n#header-bar {\n padding: 1px 3px;\n}\n.dialog {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n}\n.threadContainer {\n border: none;\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;\n padding: 2px 0;\n margin-left: 20px;\n}\ninput[type=password]:hover,\ninput[type=text]:not([disabled]):hover,\ninput#fs_search:hover,\ninput.field:hover,\n.webkit select:hover,\ntextarea:hover,\n#appchanx-settings input:not([type=checkbox]):hover {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\ninput[type=password]:focus,\ninput[type=text]:focus,\ninput#fs_search:focus,\ninput.field:focus,\n.webkit select:focus,\ntextarea:focus,\n#appchanx-settings input:focus {\n box-shadow: inset rgba(0,0,0,.1) 0 1px 2px;\n}\nbutton,\ninput,\ntextarea,\n.rice {\n transition: background .2s,box-shadow .2s;\n}"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3618,12 +3619,18 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
DataBoard.prototype.clean = function() {
|
DataBoard.prototype.clean = function() {
|
||||||
var boardID, now;
|
var boardID, now, val, _ref;
|
||||||
|
|
||||||
for (boardID in this.data.boards) {
|
_ref = this.data.boards;
|
||||||
this.deleteIfEmpty({
|
for (boardID in _ref) {
|
||||||
boardID: boardID
|
val = _ref[boardID];
|
||||||
});
|
if (!val) {
|
||||||
|
delete this.data.boards[boardID];
|
||||||
|
} else {
|
||||||
|
this.deleteIfEmpty({
|
||||||
|
boardID: boardID
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
now = Date.now();
|
now = Date.now();
|
||||||
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) {
|
||||||
@ -4922,6 +4929,10 @@
|
|||||||
}
|
}
|
||||||
for (key in Config.filter) {
|
for (key in Config.filter) {
|
||||||
this.filters[key] = [];
|
this.filters[key] = [];
|
||||||
|
if (Conf[key] === void 0) {
|
||||||
|
$["delete"](key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ref = Conf[key].split('\n');
|
_ref = Conf[key].split('\n');
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
filter = _ref[_i];
|
filter = _ref[_i];
|
||||||
@ -6961,6 +6972,9 @@
|
|||||||
QR.cleanNotifications();
|
QR.cleanNotifications();
|
||||||
d.activeElement.blur();
|
d.activeElement.blur();
|
||||||
$.rmClass(QR.nodes.el, 'dump');
|
$.rmClass(QR.nodes.el, 'dump');
|
||||||
|
if (!Conf['Captcha Warning Notifications']) {
|
||||||
|
$.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
}
|
||||||
if (Conf['QR Shortcut']) {
|
if (Conf['QR Shortcut']) {
|
||||||
$.toggleClass($('.qr-shortcut'), 'disabled');
|
$.toggleClass($('.qr-shortcut'), 'disabled');
|
||||||
}
|
}
|
||||||
@ -7006,6 +7020,16 @@
|
|||||||
}
|
}
|
||||||
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
if (QR.captcha.isEnabled && /captcha|verification/i.test(el.textContent)) {
|
||||||
QR.captcha.nodes.input.focus();
|
QR.captcha.nodes.input.focus();
|
||||||
|
if (Conf['Captcha Warning Notifications']) {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
|
} else {
|
||||||
|
$.addClass(QR.captcha.nodes.input, 'error');
|
||||||
|
$.on(QR.captcha.nodes.input, 'keydown', function() {
|
||||||
|
return $.rmClass(QR.captcha.nodes.input, 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QR.notifications.push(new Notification('warning', el));
|
||||||
}
|
}
|
||||||
if (d.hidden) {
|
if (d.hidden) {
|
||||||
alert(el.textContent);
|
alert(el.textContent);
|
||||||
@ -8108,13 +8132,13 @@
|
|||||||
err = 'No valid captcha.';
|
err = 'No valid captcha.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QR.cleanNotifications();
|
||||||
if (err) {
|
if (err) {
|
||||||
QR.cooldown.auto = false;
|
QR.cooldown.auto = false;
|
||||||
QR.status();
|
QR.status();
|
||||||
QR.error(err);
|
QR.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QR.cleanNotifications();
|
|
||||||
QR.cooldown.auto = QR.posts.length > 1;
|
QR.cooldown.auto = QR.posts.length > 1;
|
||||||
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
if (Conf['Auto Hide QR'] && !QR.cooldown.auto) {
|
||||||
QR.hide();
|
QR.hide();
|
||||||
@ -9833,13 +9857,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unread.addPosts(posts);
|
Unread.addPosts(posts);
|
||||||
if (!Conf['Scroll to Last Read Post']) {
|
if (Conf['Scroll to Last Read Post']) {
|
||||||
return;
|
return Unread.scroll();
|
||||||
}
|
}
|
||||||
return Unread.scroll();
|
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var hash, onload, post, posts, prevID, root;
|
var hash, post, posts, prevID, root;
|
||||||
|
|
||||||
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
||||||
return;
|
return;
|
||||||
@ -9856,17 +9879,11 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onload = function() {
|
root.scrollIntoView(false);
|
||||||
return root.scrollIntoView(false);
|
return;
|
||||||
};
|
|
||||||
} else {
|
|
||||||
posts = Object.keys(Unread.thread.posts);
|
|
||||||
post = Unread.thread.posts[posts[posts.length - 1]];
|
|
||||||
onload = function() {
|
|
||||||
return Header.scrollToPost(post.nodes.root);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return $.on(window, 'load', onload);
|
posts = Object.keys(Unread.thread.posts);
|
||||||
|
return Header.scrollToPost(Unread.thread.posts[posts[posts.length - 1]].nodes.root);
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var lastReadPost;
|
||||||
@ -13111,7 +13128,7 @@
|
|||||||
|
|
||||||
Sauce = {
|
Sauce = {
|
||||||
init: function() {
|
init: function() {
|
||||||
var link, links, _i, _len, _ref;
|
var err, link, links, _i, _len, _ref;
|
||||||
|
|
||||||
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
if (g.VIEW === 'catalog' || !Conf['Sauce']) {
|
||||||
return;
|
return;
|
||||||
@ -13123,7 +13140,12 @@
|
|||||||
if (link[0] === '#') {
|
if (link[0] === '#') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
links.push(this.createSauceLink(link.trim()));
|
try {
|
||||||
|
links.push(this.createSauceLink(link.trim()));
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!links.length) {
|
if (!links.length) {
|
||||||
return;
|
return;
|
||||||
@ -13537,6 +13559,7 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
$.get(Conf, function(Conf) {
|
$.get(Conf, function(Conf) {
|
||||||
|
delete Conf['archives'];
|
||||||
data.Conf = Conf;
|
data.Conf = Conf;
|
||||||
return Settings["export"](now, data);
|
return Settings["export"](now, data);
|
||||||
});
|
});
|
||||||
@ -14491,6 +14514,9 @@
|
|||||||
Conf = items;
|
Conf = items;
|
||||||
pathname = location.pathname.split('/');
|
pathname = location.pathname.split('/');
|
||||||
g.BOARD = new Board(pathname[1]);
|
g.BOARD = new Board(pathname[1]);
|
||||||
|
if (g.BOARD.ID === 'z') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g.VIEW = (function() {
|
g.VIEW = (function() {
|
||||||
switch (pathname[2]) {
|
switch (pathname[2]) {
|
||||||
case 'res':
|
case 'res':
|
||||||
@ -14689,6 +14715,12 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
localStorage.getItem('4chan-settings');
|
||||||
|
} catch (_error) {
|
||||||
|
err = _error;
|
||||||
|
new Notification('warning', 'Cookies need to be enabled on 4chan for appchan x to properly function.', 30);
|
||||||
|
}
|
||||||
$.event('4chanXInitFinished');
|
$.event('4chanXInitFinished');
|
||||||
return Main.checkUpdate();
|
return Main.checkUpdate();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -8,6 +8,11 @@ Filter =
|
|||||||
|
|
||||||
for key of Config.filter
|
for key of Config.filter
|
||||||
@filters[key] = []
|
@filters[key] = []
|
||||||
|
if Conf[key] is undefined
|
||||||
|
# XXX hopefully tmp fix for the rare people getting this mysterious error:
|
||||||
|
# "Filter" initialization crashed. TypeError: Cannot call method 'split' of undefined
|
||||||
|
$.delete key
|
||||||
|
continue
|
||||||
for filter in Conf[key].split '\n'
|
for filter in Conf[key].split '\n'
|
||||||
continue if filter[0] is '#'
|
continue if filter[0] is '#'
|
||||||
|
|
||||||
@ -272,4 +277,4 @@ Filter =
|
|||||||
ta = $ 'textarea', section
|
ta = $ 'textarea', section
|
||||||
tl = ta.textLength
|
tl = ta.textLength
|
||||||
ta.setSelectionRange tl, tl
|
ta.setSelectionRange tl, tl
|
||||||
ta.focus()
|
ta.focus()
|
||||||
|
|||||||
@ -289,6 +289,10 @@ Config =
|
|||||||
true
|
true
|
||||||
'Show notifications on successful post creation or file uploading.'
|
'Show notifications on successful post creation or file uploading.'
|
||||||
]
|
]
|
||||||
|
'Captcha Warning Notifications': [
|
||||||
|
true
|
||||||
|
'When disabled, shows a red border on the CAPTCHA input until a key is pressed instead of a notification.'
|
||||||
|
]
|
||||||
|
|
||||||
'Quote Links':
|
'Quote Links':
|
||||||
'Quote Backlinks': [
|
'Quote Backlinks': [
|
||||||
@ -328,8 +332,8 @@ Config =
|
|||||||
'Add \'(You)\' to quotes linking to your posts.'
|
'Add \'(You)\' to quotes linking to your posts.'
|
||||||
]
|
]
|
||||||
'Quoted Title': [
|
'Quoted Title': [
|
||||||
'Change the page title to reflect you\'ve been quoted.'
|
|
||||||
false
|
false
|
||||||
|
'Change the page title to reflect you\'ve been quoted.'
|
||||||
]
|
]
|
||||||
'Highlight Posts Quoting You': [
|
'Highlight Posts Quoting You': [
|
||||||
false
|
false
|
||||||
|
|||||||
@ -2884,10 +2884,6 @@ textarea,
|
|||||||
.dialog {
|
.dialog {
|
||||||
box-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);
|
box-shadow: 0px 0px 4px rgba(0, 0, 0, .3) inset, 1px 1px 5px rgba(0,0,0,0.2);
|
||||||
}
|
}
|
||||||
.thread > .replyContainer
|
|
||||||
.threadContainer > .replyContainer {
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.threadContainer {
|
.threadContainer {
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;
|
box-shadow: 0px 0px 3px rgba(0, 0, 0, .3) inset, rgba(70,70,70,.3) 1px 1px;
|
||||||
@ -2994,10 +2990,6 @@ textarea,
|
|||||||
.dialog {
|
.dialog {
|
||||||
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;
|
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;
|
||||||
}
|
}
|
||||||
.thread > .replyContainer
|
|
||||||
.threadContainer > .replyContainer {
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.threadContainer {
|
.threadContainer {
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;
|
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.1) inset, rgba(255,255,255,.5) 1px 1px;
|
||||||
|
|||||||
@ -32,6 +32,7 @@ Main =
|
|||||||
|
|
||||||
pathname = location.pathname.split '/'
|
pathname = location.pathname.split '/'
|
||||||
g.BOARD = new Board pathname[1]
|
g.BOARD = new Board pathname[1]
|
||||||
|
return if g.BOARD.ID is 'z'
|
||||||
g.VIEW =
|
g.VIEW =
|
||||||
switch pathname[2]
|
switch pathname[2]
|
||||||
when 'res'
|
when 'res'
|
||||||
@ -207,6 +208,10 @@ Main =
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try
|
||||||
|
localStorage.getItem '4chan-settings'
|
||||||
|
catch err
|
||||||
|
new Notification 'warning', 'Cookies need to be enabled on 4chan for <%= meta.name %> to properly function.', 30
|
||||||
|
|
||||||
$.event '4chanXInitFinished'
|
$.event '4chanXInitFinished'
|
||||||
Main.checkUpdate()
|
Main.checkUpdate()
|
||||||
|
|||||||
@ -176,6 +176,8 @@ Settings =
|
|||||||
Conf[db] = boards: {}
|
Conf[db] = boards: {}
|
||||||
# Make sure to export the most recent data.
|
# Make sure to export the most recent data.
|
||||||
$.get Conf, (Conf) ->
|
$.get Conf, (Conf) ->
|
||||||
|
# XXX don't export archives.
|
||||||
|
delete Conf['archives']
|
||||||
data.Conf = Conf
|
data.Conf = Conf
|
||||||
Settings.export now, data
|
Settings.export now, data
|
||||||
return
|
return
|
||||||
|
|||||||
@ -35,12 +35,6 @@
|
|||||||
background-color: #282A2E;
|
background-color: #282A2E;
|
||||||
border-color: #111;
|
border-color: #111;
|
||||||
}
|
}
|
||||||
:root.tomorrow #qr select {
|
|
||||||
color: #C5C8C6;
|
|
||||||
}
|
|
||||||
:root.tomorrow #qr option {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
:root.tomorrow .qr-preview {
|
:root.tomorrow .qr-preview {
|
||||||
background-color: rgba(255, 255, 255, .15);
|
background-color: rgba(255, 255, 255, .15);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,8 +59,13 @@ class DataBoard
|
|||||||
val or defaultValue
|
val or defaultValue
|
||||||
|
|
||||||
clean: ->
|
clean: ->
|
||||||
for boardID of @data.boards
|
for boardID, val of @data.boards
|
||||||
@deleteIfEmpty {boardID}
|
# XXX tmp fix for users that had the `null`
|
||||||
|
# value for a board with the Unread features:
|
||||||
|
unless val
|
||||||
|
delete @data.boards[boardID]
|
||||||
|
else
|
||||||
|
@deleteIfEmpty {boardID}
|
||||||
|
|
||||||
now = Date.now()
|
now = Date.now()
|
||||||
if (@data.lastChecked or 0) < now - 2 * $.HOUR
|
if (@data.lastChecked or 0) < now - 2 * $.HOUR
|
||||||
|
|||||||
@ -5,7 +5,11 @@ Sauce =
|
|||||||
links = []
|
links = []
|
||||||
for link in Conf['sauces'].split '\n'
|
for link in Conf['sauces'].split '\n'
|
||||||
continue if link[0] is '#'
|
continue if link[0] is '#'
|
||||||
links.push @createSauceLink link.trim()
|
try
|
||||||
|
links.push @createSauceLink link.trim()
|
||||||
|
catch err
|
||||||
|
# Don't add random text plz.
|
||||||
|
continue
|
||||||
return unless links.length
|
return unless links.length
|
||||||
@links = links
|
@links = links
|
||||||
@link = $.el 'a', target: '_blank'
|
@link = $.el 'a', target: '_blank'
|
||||||
@ -39,4 +43,4 @@ Sauce =
|
|||||||
for link in Sauce.links
|
for link in Sauce.links
|
||||||
# \u00A0 is nbsp
|
# \u00A0 is nbsp
|
||||||
nodes.push $.tn('\u00A0'), link @, Sauce.link.cloneNode true
|
nodes.push $.tn('\u00A0'), link @, Sauce.link.cloneNode true
|
||||||
$.add @file.info, nodes
|
$.add @file.info, nodes
|
||||||
|
|||||||
@ -30,8 +30,7 @@ Unread =
|
|||||||
for ID, post of Unread.thread.posts
|
for ID, post of Unread.thread.posts
|
||||||
posts.push post if post.isReply
|
posts.push post if post.isReply
|
||||||
Unread.addPosts posts
|
Unread.addPosts posts
|
||||||
return unless Conf['Scroll to Last Read Post']
|
Unread.scroll() if Conf['Scroll to Last Read Post']
|
||||||
Unread.scroll()
|
|
||||||
|
|
||||||
scroll: ->
|
scroll: ->
|
||||||
# Let the header's onload callback handle it.
|
# Let the header's onload callback handle it.
|
||||||
@ -44,15 +43,11 @@ Unread =
|
|||||||
break if prevID is post.ID
|
break if prevID is post.ID
|
||||||
prevID = post.ID
|
prevID = post.ID
|
||||||
break unless post.isHidden
|
break unless post.isHidden
|
||||||
onload = -> root.scrollIntoView false
|
root.scrollIntoView false
|
||||||
else
|
return
|
||||||
# Scroll to the last read post.
|
# Scroll to the last read post.
|
||||||
posts = Object.keys Unread.thread.posts
|
posts = Object.keys Unread.thread.posts
|
||||||
post = Unread.thread.posts[posts[posts.length - 1]]
|
Header.scrollToPost Unread.thread.posts[posts[posts.length - 1]].nodes.root
|
||||||
onload = -> Header.scrollToPost post.nodes.root
|
|
||||||
# Prevent the browser to scroll back to
|
|
||||||
# the previous scroll location on page load.
|
|
||||||
$.on window, 'load', onload
|
|
||||||
|
|
||||||
sync: ->
|
sync: ->
|
||||||
lastReadPost = Unread.db.get
|
lastReadPost = Unread.db.get
|
||||||
|
|||||||
@ -87,6 +87,8 @@ QR =
|
|||||||
QR.cleanNotifications()
|
QR.cleanNotifications()
|
||||||
d.activeElement.blur()
|
d.activeElement.blur()
|
||||||
$.rmClass QR.nodes.el, 'dump'
|
$.rmClass QR.nodes.el, 'dump'
|
||||||
|
unless Conf['Captcha Warning Notifications']
|
||||||
|
$.rmClass QR.captcha.nodes.input, 'error'
|
||||||
if Conf['QR Shortcut']
|
if Conf['QR Shortcut']
|
||||||
$.toggleClass $('.qr-shortcut'), 'disabled'
|
$.toggleClass $('.qr-shortcut'), 'disabled'
|
||||||
for i in QR.posts
|
for i in QR.posts
|
||||||
@ -125,6 +127,14 @@ QR =
|
|||||||
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
|
if QR.captcha.isEnabled and /captcha|verification/i.test el.textContent
|
||||||
# Focus the captcha input on captcha error.
|
# Focus the captcha input on captcha error.
|
||||||
QR.captcha.nodes.input.focus()
|
QR.captcha.nodes.input.focus()
|
||||||
|
if Conf['Captcha Warning Notifications']
|
||||||
|
QR.notifications.push new Notification 'warning', el
|
||||||
|
else
|
||||||
|
$.addClass QR.captcha.nodes.input, 'error'
|
||||||
|
$.on QR.captcha.nodes.input, 'keydown', ->
|
||||||
|
$.rmClass QR.captcha.nodes.input, 'error'
|
||||||
|
else
|
||||||
|
QR.notifications.push new Notification 'warning', el
|
||||||
alert el.textContent if d.hidden
|
alert el.textContent if d.hidden
|
||||||
QR.notifications.push new Notification 'warning', el
|
QR.notifications.push new Notification 'warning', el
|
||||||
|
|
||||||
@ -1046,13 +1056,13 @@ QR =
|
|||||||
{challenge, response} = QR.captcha.getOne()
|
{challenge, response} = QR.captcha.getOne()
|
||||||
err = 'No valid captcha.' unless response
|
err = 'No valid captcha.' unless response
|
||||||
|
|
||||||
|
QR.cleanNotifications()
|
||||||
if err
|
if err
|
||||||
# stop auto-posting
|
# stop auto-posting
|
||||||
QR.cooldown.auto = false
|
QR.cooldown.auto = false
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.error err
|
QR.error err
|
||||||
return
|
return
|
||||||
QR.cleanNotifications()
|
|
||||||
|
|
||||||
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
# Enable auto-posting if we have stuff to post, disable it otherwise.
|
||||||
QR.cooldown.auto = QR.posts.length > 1
|
QR.cooldown.auto = QR.posts.length > 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user