diff --git a/CHANGELOG.md b/CHANGELOG.md index cc652595a..809b5b557 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ The attributions below are for work that has been incorporated into the script a 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.9.3.5 +*2014-09-18* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.5/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.5/builds/4chan-X-noupdate.crx "Chromium version")] + +**ccd0** +- Revert a bad "fix" from v1.9.3.2. + +### v1.9.3.4 +*2014-09-18* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.4/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.4/builds/4chan-X-noupdate.crx "Chromium version")] + +**ccd0** +- Archived thread related bugfixes. + ### v1.9.3.3 *2014-09-17* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.3/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.3.3/builds/4chan-X-noupdate.crx "Chromium version")] diff --git a/LICENSE b/LICENSE index 5885cd61f..ad7cc6501 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.9.3.3 +* 4chan X - Version 1.9.3.5 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx index 25985ee86..7bbc299e9 100644 Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js index 82b7e23ed..7c791d59f 100644 --- a/builds/4chan-X-beta.meta.js +++ b/builds/4chan-X-beta.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X beta -// @version 1.9.3.3 +// @version 1.9.3.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js index 440b65d29..d924a4fdd 100644 --- a/builds/4chan-X-beta.user.js +++ b/builds/4chan-X-beta.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X beta -// @version 1.9.3.3 +// @version 1.9.3.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.9.3.3 +* 4chan X - Version 1.9.3.5 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -267,7 +267,7 @@ 'Current Board': [false, 'Only show watched threads from the current board.'], 'Auto Watch': [true, 'Automatically watch threads you start.'], 'Auto Watch Reply': [false, 'Automatically watch threads you reply to.'], - 'Auto Prune': [false, 'Automatically prune 404\'d threads.'], + 'Auto Prune': [false, 'Automatically prune dead threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'] }, filter: { @@ -376,7 +376,7 @@ doc = d.documentElement; g = { - VERSION: '1.9.3.3', + VERSION: '1.9.3.5', NAMESPACE: '4chan X.', NAME: '4chan X', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', @@ -1501,7 +1501,7 @@ }; DataBoard.prototype.clean = function() { - var boardID, now, val, _ref; + var boardID, now, threadID, val, _ref; _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1513,44 +1513,29 @@ if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) { this.data.lastChecked = now; for (boardID in this.data.boards) { - this.ajaxClean(boardID); + for (threadID in this.data.boards[boardID]) { + this.ajaxClean(boardID, threadID); + } } } return this.save(); }; - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e) { - var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; - if (e.target.status !== 200) { + DataBoard.prototype.ajaxClean = function(boardID, threadID) { + return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: (function(_this) { + return function(e) { if (e.target.status === 404) { - _this["delete"]({ - boardID: boardID + return _this["delete"]({ + boardID: boardID, + threadID: threadID }); } - return; - } - board = _this.data.boards[boardID]; - threads = {}; - _ref = e.target.response; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - page = _ref[_i]; - _ref1 = page.threads; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - thread = _ref1[_j]; - if (thread.no in board) { - threads[thread.no] = board[thread.no]; - } - } - } - _this.data.boards[boardID] = threads; - _this.deleteIfEmpty({ - boardID: boardID - }); - return _this.save(); - }; - })(this)); + }; + })(this) + }, { + type: 'head' + }); }; DataBoard.prototype.onSync = function(data) { @@ -4045,7 +4030,6 @@ isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO', cb: cb, endEvents: endEvents, - ready: false, latestEvent: latestEvent, clientHeight: doc.clientHeight, clientWidth: doc.clientWidth, @@ -4056,7 +4040,6 @@ $.asap(function() { return !el.parentNode || asapTest(); }, function() { - o.ready = true; if (el.parentNode) { return o.hover(o.latestEvent); } @@ -4076,9 +4059,6 @@ hover = function(e) { var clientX, clientY, height, left, right, style, threshold, top, _ref; this.latestEvent = e; - if (!this.ready) { - return; - } height = this.el.offsetHeight; clientX = e.clientX, clientY = e.clientY; top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120)); @@ -5971,7 +5951,12 @@ } }, statusCheck: function() { - if (g.DEAD) { + var thread; + if (!QR.nodes) { + return; + } + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { return QR.abort(); } else { return QR.status(); @@ -10129,7 +10114,7 @@ $.on(window, 'online offline', ThreadUpdater.cb.online); $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - if (g.DEAD) { + if (ThreadUpdater.thread.isArchived) { return ThreadUpdater.set('status', 'Archived', 'warning'); } else { return ThreadUpdater.cb.online(); @@ -10143,7 +10128,7 @@ beep: 'data:audio/wav;base64,UklGRjQDAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAc21wbDwAAABBAAADAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkYXRhzAIAAGMms8em0tleMV4zIpLVo8nhfSlcPR102Ki+5JspVEkdVtKzs+K1NEhUIT7DwKrcy0g6WygsrM2k1NpiLl0zIY/WpMrjgCdbPhxw2Kq+5Z4qUkkdU9K1s+K5NkVTITzBwqnczko3WikrqM+l1NxlLF0zIIvXpsnjgydZPhxs2ay95aIrUEkdUdC3suK8N0NUIjq+xKrcz002WioppdGm091pK1w0IIjYp8jkhydXPxxq2K295aUrTkoeTs65suK+OUFUIzi7xqrb0VA0WSoootKm0t5tKlo1H4TYqMfkiydWQBxm16+85actTEseS8y7seHAPD9TIza5yKra01QyWSson9On0d5wKVk2H4DYqcfkjidUQB1j1rG75KsvSkseScu8seDCPz1TJDW2yara1FYxWSwnm9Sn0N9zKVg2H33ZqsXkkihSQR1g1bK65K0wSEsfR8i+seDEQTxUJTOzy6rY1VowWC0mmNWoz993KVc3H3rYq8TklSlRQh1d1LS647AyR0wgRMbAsN/GRDpTJTKwzKrX1l4vVy4lldWpzt97KVY4IXbUr8LZljVPRCxhw7W3z6ZISkw1VK+4sMWvXEhSPk6buay9sm5JVkZNiLWqtrJ+TldNTnquqbCwilZXU1BwpKirrpNgWFhTaZmnpquZbFlbVmWOpaOonHZcXlljhaGhpZ1+YWBdYn2cn6GdhmdhYGN3lp2enIttY2Jjco+bnJuOdGZlZXCImJqakHpoZ2Zug5WYmZJ/bGlobX6RlpeSg3BqaW16jZSVkoZ0bGtteImSk5KIeG5tbnaFkJKRinxxbm91gY2QkIt/c3BwdH6Kj4+LgnZxcXR8iI2OjIR5c3J0e4WLjYuFe3VzdHmCioyLhn52dHR5gIiKioeAeHV1eH+GiYqHgXp2dnh9hIiJh4J8eHd4fIKHiIeDfXl4eHyBhoeHhH96eHmA', cb: { online: function() { - if (g.DEAD) { + if (ThreadUpdater.thread.isDead) { return; } if (ThreadUpdater.online = navigator.onLine) { @@ -10173,7 +10158,7 @@ ThreadUpdater.outdateCount = 0; ThreadUpdater.set('timer', '...'); } - if (!(g.DEAD || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { + if (!(ThreadUpdater.thread.isDead || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { return setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); } ThreadUpdater.setInterval(); @@ -10211,9 +10196,9 @@ req = ThreadUpdater.req; switch (req.status) { case 200: - g.DEAD = !!+req.response.posts[0].archived; ThreadUpdater.parse(req.response.posts); - if (g.DEAD) { + if (!!req.response.posts[0].archived) { + ThreadUpdater.thread.isArchived = true; ThreadUpdater.set('status', 'Archived', 'warning'); ThreadUpdater.kill(); } else { @@ -10242,7 +10227,6 @@ confirmed = false; } if (confirmed) { - g.DEAD = true; ThreadUpdater.set('status', '404', 'warning'); return ThreadUpdater.kill(); } else { @@ -10601,7 +10585,6 @@ }); } else { data.isDead = true; - delete data.unread; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -10641,7 +10624,7 @@ fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; - if (data.isDead) { + if (data.isDead && !Conf['Show Unread Count']) { return; } fetchCount = ThreadWatcher.fetchCount; @@ -10652,7 +10635,7 @@ fetchCount.fetching++; return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { - var lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; + var isDead, lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -10664,6 +10647,15 @@ } ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { + isDead = !!this.response.posts[0].archived; + if (isDead && Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + ThreadWatcher.refresh(); + return; + } lastReadPost = ThreadWatcher.unreaddb.get({ boardID: boardID, threadID: threadID, @@ -10681,7 +10673,8 @@ unread++; } } - if (unread !== data.unread) { + if (isDead !== data.isDead || unread !== data.unread) { + data.isDead = isDead; data.unread = unread; ThreadWatcher.db.set({ boardID: boardID, @@ -10708,8 +10701,6 @@ return ThreadWatcher.refresh(); } } - }, { - type: Conf['Show Unread Count'] ? 'get' : 'head' }); }, getAll: function() { @@ -10733,7 +10724,7 @@ return all; }, makeLine: function(boardID, threadID, data) { - var count, div, fullID, href, link, title, x; + var count, div, fullID, link, title, x; x = $.el('a', { className: 'fa fa-times', href: 'javascript:;' @@ -10747,14 +10738,8 @@ textContent: Conf['Show Unread Count'] && (data.unread != null) ? "\u00A0(" + data.unread + ")" : '', className: 'watcher-unread' }); - if (Conf['404 Redirect'] && data.isDead) { - href = Redirect.to('thread', { - boardID: boardID, - threadID: threadID - }); - } link = $.el('a', { - href: href || ("/" + boardID + "/thread/" + threadID), + href: "/" + boardID + "/thread/" + threadID, title: data.excerpt, className: 'watcher-link' }); @@ -10837,7 +10822,7 @@ val: data }); ThreadWatcher.refresh(); - if (Conf['Show Unread Count'] && !data.isDead) { + if (Conf['Show Unread Count']) { return ThreadWatcher.fetchStatus({ boardID: boardID, threadID: threadID, @@ -10921,7 +10906,7 @@ cb: ThreadWatcher.cb.pruneDeads, entry: { el: $.el('a', { - textContent: 'Prune 404\'d threads' + textContent: 'Prune dead threads' }) }, refresh: function() { @@ -11202,7 +11187,7 @@ } }), saveLastReadPost: $.debounce(2 * $.SECOND, function() { - if (Unread.thread.isDead) { + if (Unread.thread.isDead && !Unread.thread.isArchived) { return; } return Unread.db.set({ @@ -11224,16 +11209,19 @@ } }, update: function() { - var count, countQuotingYou; + var count, countQuotingYou, titleCount, titleDead, titleQuotingYou; count = Unread.posts.length; countQuotingYou = Object.keys(Unread.postsQuotingYou).length; if (Conf['Unread Count']) { - d.title = "" + (Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? Unread.title.replace('-', '- 404 -') : Unread.title); + titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : ''; + titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : ''; + titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title; + d.title = "" + titleQuotingYou + titleCount + titleDead; } if (!Conf['Unread Favicon']) { return; } - Favicon.el.href = g.DEAD ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; + Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; return $.add(d.head, Favicon.el); } }; @@ -12884,7 +12872,7 @@ className: 'dialog' }); $.extend(dialog, { - innerHTML: "
" + innerHTML: "
" }); $.on($('.export', Settings.dialog), 'click', Settings["export"]); $.on($('.import', Settings.dialog), 'click', Settings["import"]); @@ -13693,14 +13681,16 @@ }, initThread: function() { var board, err, errors, postRoot, posts, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1, _ref2; - g.DEAD = !!((_ref = $('.closed')) != null ? _ref.textContent.match(/Thread archived/) : void 0); if (board = $('.board')) { threads = []; posts = []; - _ref1 = $$('.board > .thread', board); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - threadRoot = _ref1[_i]; + _ref = $$('.board > .thread', board); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + threadRoot = _ref[_i]; thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + if (g.VIEW === 'thread') { + thread.isDead = thread.isArchived = !!((_ref1 = $('.closed')) != null ? _ref1.textContent.match(/Thread archived/) : void 0); + } threads.push(thread); _ref2 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx index 5b5446aa5..4d61740c0 100644 Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js index 5a11cde89..3403f9c9f 100644 --- a/builds/4chan-X-noupdate.user.js +++ b/builds/4chan-X-noupdate.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.9.3.3 +// @version 1.9.3.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -23,7 +23,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.9.3.3 +* 4chan X - Version 1.9.3.5 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -266,7 +266,7 @@ 'Current Board': [false, 'Only show watched threads from the current board.'], 'Auto Watch': [true, 'Automatically watch threads you start.'], 'Auto Watch Reply': [false, 'Automatically watch threads you reply to.'], - 'Auto Prune': [false, 'Automatically prune 404\'d threads.'], + 'Auto Prune': [false, 'Automatically prune dead threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'] }, filter: { @@ -375,7 +375,7 @@ doc = d.documentElement; g = { - VERSION: '1.9.3.3', + VERSION: '1.9.3.5', NAMESPACE: '4chan X.', NAME: '4chan X', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', @@ -1500,7 +1500,7 @@ }; DataBoard.prototype.clean = function() { - var boardID, now, val, _ref; + var boardID, now, threadID, val, _ref; _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1512,44 +1512,29 @@ if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) { this.data.lastChecked = now; for (boardID in this.data.boards) { - this.ajaxClean(boardID); + for (threadID in this.data.boards[boardID]) { + this.ajaxClean(boardID, threadID); + } } } return this.save(); }; - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e) { - var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; - if (e.target.status !== 200) { + DataBoard.prototype.ajaxClean = function(boardID, threadID) { + return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: (function(_this) { + return function(e) { if (e.target.status === 404) { - _this["delete"]({ - boardID: boardID + return _this["delete"]({ + boardID: boardID, + threadID: threadID }); } - return; - } - board = _this.data.boards[boardID]; - threads = {}; - _ref = e.target.response; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - page = _ref[_i]; - _ref1 = page.threads; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - thread = _ref1[_j]; - if (thread.no in board) { - threads[thread.no] = board[thread.no]; - } - } - } - _this.data.boards[boardID] = threads; - _this.deleteIfEmpty({ - boardID: boardID - }); - return _this.save(); - }; - })(this)); + }; + })(this) + }, { + type: 'head' + }); }; DataBoard.prototype.onSync = function(data) { @@ -4044,7 +4029,6 @@ isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO', cb: cb, endEvents: endEvents, - ready: false, latestEvent: latestEvent, clientHeight: doc.clientHeight, clientWidth: doc.clientWidth, @@ -4055,7 +4039,6 @@ $.asap(function() { return !el.parentNode || asapTest(); }, function() { - o.ready = true; if (el.parentNode) { return o.hover(o.latestEvent); } @@ -4075,9 +4058,6 @@ hover = function(e) { var clientX, clientY, height, left, right, style, threshold, top, _ref; this.latestEvent = e; - if (!this.ready) { - return; - } height = this.el.offsetHeight; clientX = e.clientX, clientY = e.clientY; top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120)); @@ -5970,7 +5950,12 @@ } }, statusCheck: function() { - if (g.DEAD) { + var thread; + if (!QR.nodes) { + return; + } + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { return QR.abort(); } else { return QR.status(); @@ -10128,7 +10113,7 @@ $.on(window, 'online offline', ThreadUpdater.cb.online); $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - if (g.DEAD) { + if (ThreadUpdater.thread.isArchived) { return ThreadUpdater.set('status', 'Archived', 'warning'); } else { return ThreadUpdater.cb.online(); @@ -10142,7 +10127,7 @@ beep: 'data:audio/wav;base64,UklGRjQDAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAc21wbDwAAABBAAADAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkYXRhzAIAAGMms8em0tleMV4zIpLVo8nhfSlcPR102Ki+5JspVEkdVtKzs+K1NEhUIT7DwKrcy0g6WygsrM2k1NpiLl0zIY/WpMrjgCdbPhxw2Kq+5Z4qUkkdU9K1s+K5NkVTITzBwqnczko3WikrqM+l1NxlLF0zIIvXpsnjgydZPhxs2ay95aIrUEkdUdC3suK8N0NUIjq+xKrcz002WioppdGm091pK1w0IIjYp8jkhydXPxxq2K295aUrTkoeTs65suK+OUFUIzi7xqrb0VA0WSoootKm0t5tKlo1H4TYqMfkiydWQBxm16+85actTEseS8y7seHAPD9TIza5yKra01QyWSson9On0d5wKVk2H4DYqcfkjidUQB1j1rG75KsvSkseScu8seDCPz1TJDW2yara1FYxWSwnm9Sn0N9zKVg2H33ZqsXkkihSQR1g1bK65K0wSEsfR8i+seDEQTxUJTOzy6rY1VowWC0mmNWoz993KVc3H3rYq8TklSlRQh1d1LS647AyR0wgRMbAsN/GRDpTJTKwzKrX1l4vVy4lldWpzt97KVY4IXbUr8LZljVPRCxhw7W3z6ZISkw1VK+4sMWvXEhSPk6buay9sm5JVkZNiLWqtrJ+TldNTnquqbCwilZXU1BwpKirrpNgWFhTaZmnpquZbFlbVmWOpaOonHZcXlljhaGhpZ1+YWBdYn2cn6GdhmdhYGN3lp2enIttY2Jjco+bnJuOdGZlZXCImJqakHpoZ2Zug5WYmZJ/bGlobX6RlpeSg3BqaW16jZSVkoZ0bGtteImSk5KIeG5tbnaFkJKRinxxbm91gY2QkIt/c3BwdH6Kj4+LgnZxcXR8iI2OjIR5c3J0e4WLjYuFe3VzdHmCioyLhn52dHR5gIiKioeAeHV1eH+GiYqHgXp2dnh9hIiJh4J8eHd4fIKHiIeDfXl4eHyBhoeHhH96eHmA', cb: { online: function() { - if (g.DEAD) { + if (ThreadUpdater.thread.isDead) { return; } if (ThreadUpdater.online = navigator.onLine) { @@ -10172,7 +10157,7 @@ ThreadUpdater.outdateCount = 0; ThreadUpdater.set('timer', '...'); } - if (!(g.DEAD || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { + if (!(ThreadUpdater.thread.isDead || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { return setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); } ThreadUpdater.setInterval(); @@ -10210,9 +10195,9 @@ req = ThreadUpdater.req; switch (req.status) { case 200: - g.DEAD = !!+req.response.posts[0].archived; ThreadUpdater.parse(req.response.posts); - if (g.DEAD) { + if (!!req.response.posts[0].archived) { + ThreadUpdater.thread.isArchived = true; ThreadUpdater.set('status', 'Archived', 'warning'); ThreadUpdater.kill(); } else { @@ -10241,7 +10226,6 @@ confirmed = false; } if (confirmed) { - g.DEAD = true; ThreadUpdater.set('status', '404', 'warning'); return ThreadUpdater.kill(); } else { @@ -10600,7 +10584,6 @@ }); } else { data.isDead = true; - delete data.unread; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -10640,7 +10623,7 @@ fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; - if (data.isDead) { + if (data.isDead && !Conf['Show Unread Count']) { return; } fetchCount = ThreadWatcher.fetchCount; @@ -10651,7 +10634,7 @@ fetchCount.fetching++; return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { - var lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; + var isDead, lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -10663,6 +10646,15 @@ } ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { + isDead = !!this.response.posts[0].archived; + if (isDead && Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + ThreadWatcher.refresh(); + return; + } lastReadPost = ThreadWatcher.unreaddb.get({ boardID: boardID, threadID: threadID, @@ -10680,7 +10672,8 @@ unread++; } } - if (unread !== data.unread) { + if (isDead !== data.isDead || unread !== data.unread) { + data.isDead = isDead; data.unread = unread; ThreadWatcher.db.set({ boardID: boardID, @@ -10707,8 +10700,6 @@ return ThreadWatcher.refresh(); } } - }, { - type: Conf['Show Unread Count'] ? 'get' : 'head' }); }, getAll: function() { @@ -10732,7 +10723,7 @@ return all; }, makeLine: function(boardID, threadID, data) { - var count, div, fullID, href, link, title, x; + var count, div, fullID, link, title, x; x = $.el('a', { className: 'fa fa-times', href: 'javascript:;' @@ -10746,14 +10737,8 @@ textContent: Conf['Show Unread Count'] && (data.unread != null) ? "\u00A0(" + data.unread + ")" : '', className: 'watcher-unread' }); - if (Conf['404 Redirect'] && data.isDead) { - href = Redirect.to('thread', { - boardID: boardID, - threadID: threadID - }); - } link = $.el('a', { - href: href || ("/" + boardID + "/thread/" + threadID), + href: "/" + boardID + "/thread/" + threadID, title: data.excerpt, className: 'watcher-link' }); @@ -10836,7 +10821,7 @@ val: data }); ThreadWatcher.refresh(); - if (Conf['Show Unread Count'] && !data.isDead) { + if (Conf['Show Unread Count']) { return ThreadWatcher.fetchStatus({ boardID: boardID, threadID: threadID, @@ -10920,7 +10905,7 @@ cb: ThreadWatcher.cb.pruneDeads, entry: { el: $.el('a', { - textContent: 'Prune 404\'d threads' + textContent: 'Prune dead threads' }) }, refresh: function() { @@ -11201,7 +11186,7 @@ } }), saveLastReadPost: $.debounce(2 * $.SECOND, function() { - if (Unread.thread.isDead) { + if (Unread.thread.isDead && !Unread.thread.isArchived) { return; } return Unread.db.set({ @@ -11223,16 +11208,19 @@ } }, update: function() { - var count, countQuotingYou; + var count, countQuotingYou, titleCount, titleDead, titleQuotingYou; count = Unread.posts.length; countQuotingYou = Object.keys(Unread.postsQuotingYou).length; if (Conf['Unread Count']) { - d.title = "" + (Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? Unread.title.replace('-', '- 404 -') : Unread.title); + titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : ''; + titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : ''; + titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title; + d.title = "" + titleQuotingYou + titleCount + titleDead; } if (!Conf['Unread Favicon']) { return; } - Favicon.el.href = g.DEAD ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; + Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; return $.add(d.head, Favicon.el); } }; @@ -12883,7 +12871,7 @@ className: 'dialog' }); $.extend(dialog, { - innerHTML: "
" + innerHTML: "
" }); $.on($('.export', Settings.dialog), 'click', Settings["export"]); $.on($('.import', Settings.dialog), 'click', Settings["import"]); @@ -13692,14 +13680,16 @@ }, initThread: function() { var board, err, errors, postRoot, posts, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1, _ref2; - g.DEAD = !!((_ref = $('.closed')) != null ? _ref.textContent.match(/Thread archived/) : void 0); if (board = $('.board')) { threads = []; posts = []; - _ref1 = $$('.board > .thread', board); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - threadRoot = _ref1[_i]; + _ref = $$('.board > .thread', board); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + threadRoot = _ref[_i]; thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + if (g.VIEW === 'thread') { + thread.isDead = thread.isArchived = !!((_ref1 = $('.closed')) != null ? _ref1.textContent.match(/Thread archived/) : void 0); + } threads.push(thread); _ref2 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx index 943e00f12..4764f5007 100644 Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index 157c89e8b..bc63fc090 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.9.3.3 +// @version 1.9.3.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 9fb438979..85cb2769b 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.9.3.3 +// @version 1.9.3.5 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.9.3.3 +* 4chan X - Version 1.9.3.5 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -267,7 +267,7 @@ 'Current Board': [false, 'Only show watched threads from the current board.'], 'Auto Watch': [true, 'Automatically watch threads you start.'], 'Auto Watch Reply': [false, 'Automatically watch threads you reply to.'], - 'Auto Prune': [false, 'Automatically prune 404\'d threads.'], + 'Auto Prune': [false, 'Automatically prune dead threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'] }, filter: { @@ -376,7 +376,7 @@ doc = d.documentElement; g = { - VERSION: '1.9.3.3', + VERSION: '1.9.3.5', NAMESPACE: '4chan X.', NAME: '4chan X', FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions', @@ -1501,7 +1501,7 @@ }; DataBoard.prototype.clean = function() { - var boardID, now, val, _ref; + var boardID, now, threadID, val, _ref; _ref = this.data.boards; for (boardID in _ref) { val = _ref[boardID]; @@ -1513,44 +1513,29 @@ if ((this.data.lastChecked || 0) < now - 2 * $.HOUR) { this.data.lastChecked = now; for (boardID in this.data.boards) { - this.ajaxClean(boardID); + for (threadID in this.data.boards[boardID]) { + this.ajaxClean(boardID, threadID); + } } } return this.save(); }; - DataBoard.prototype.ajaxClean = function(boardID) { - return $.cache("//a.4cdn.org/" + boardID + "/threads.json", (function(_this) { - return function(e) { - var board, page, thread, threads, _i, _j, _len, _len1, _ref, _ref1; - if (e.target.status !== 200) { + DataBoard.prototype.ajaxClean = function(boardID, threadID) { + return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + onloadend: (function(_this) { + return function(e) { if (e.target.status === 404) { - _this["delete"]({ - boardID: boardID + return _this["delete"]({ + boardID: boardID, + threadID: threadID }); } - return; - } - board = _this.data.boards[boardID]; - threads = {}; - _ref = e.target.response; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - page = _ref[_i]; - _ref1 = page.threads; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - thread = _ref1[_j]; - if (thread.no in board) { - threads[thread.no] = board[thread.no]; - } - } - } - _this.data.boards[boardID] = threads; - _this.deleteIfEmpty({ - boardID: boardID - }); - return _this.save(); - }; - })(this)); + }; + })(this) + }, { + type: 'head' + }); }; DataBoard.prototype.onSync = function(data) { @@ -4045,7 +4030,6 @@ isImage: (_ref = el.nodeName) === 'IMG' || _ref === 'VIDEO', cb: cb, endEvents: endEvents, - ready: false, latestEvent: latestEvent, clientHeight: doc.clientHeight, clientWidth: doc.clientWidth, @@ -4056,7 +4040,6 @@ $.asap(function() { return !el.parentNode || asapTest(); }, function() { - o.ready = true; if (el.parentNode) { return o.hover(o.latestEvent); } @@ -4076,9 +4059,6 @@ hover = function(e) { var clientX, clientY, height, left, right, style, threshold, top, _ref; this.latestEvent = e; - if (!this.ready) { - return; - } height = this.el.offsetHeight; clientX = e.clientX, clientY = e.clientY; top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120)); @@ -5971,7 +5951,12 @@ } }, statusCheck: function() { - if (g.DEAD) { + var thread; + if (!QR.nodes) { + return; + } + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { return QR.abort(); } else { return QR.status(); @@ -10129,7 +10114,7 @@ $.on(window, 'online offline', ThreadUpdater.cb.online); $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - if (g.DEAD) { + if (ThreadUpdater.thread.isArchived) { return ThreadUpdater.set('status', 'Archived', 'warning'); } else { return ThreadUpdater.cb.online(); @@ -10143,7 +10128,7 @@ beep: 'data:audio/wav;base64,UklGRjQDAABXQVZFZm10IBAAAAABAAEAgD4AAIA+AAABAAgAc21wbDwAAABBAAADAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkYXRhzAIAAGMms8em0tleMV4zIpLVo8nhfSlcPR102Ki+5JspVEkdVtKzs+K1NEhUIT7DwKrcy0g6WygsrM2k1NpiLl0zIY/WpMrjgCdbPhxw2Kq+5Z4qUkkdU9K1s+K5NkVTITzBwqnczko3WikrqM+l1NxlLF0zIIvXpsnjgydZPhxs2ay95aIrUEkdUdC3suK8N0NUIjq+xKrcz002WioppdGm091pK1w0IIjYp8jkhydXPxxq2K295aUrTkoeTs65suK+OUFUIzi7xqrb0VA0WSoootKm0t5tKlo1H4TYqMfkiydWQBxm16+85actTEseS8y7seHAPD9TIza5yKra01QyWSson9On0d5wKVk2H4DYqcfkjidUQB1j1rG75KsvSkseScu8seDCPz1TJDW2yara1FYxWSwnm9Sn0N9zKVg2H33ZqsXkkihSQR1g1bK65K0wSEsfR8i+seDEQTxUJTOzy6rY1VowWC0mmNWoz993KVc3H3rYq8TklSlRQh1d1LS647AyR0wgRMbAsN/GRDpTJTKwzKrX1l4vVy4lldWpzt97KVY4IXbUr8LZljVPRCxhw7W3z6ZISkw1VK+4sMWvXEhSPk6buay9sm5JVkZNiLWqtrJ+TldNTnquqbCwilZXU1BwpKirrpNgWFhTaZmnpquZbFlbVmWOpaOonHZcXlljhaGhpZ1+YWBdYn2cn6GdhmdhYGN3lp2enIttY2Jjco+bnJuOdGZlZXCImJqakHpoZ2Zug5WYmZJ/bGlobX6RlpeSg3BqaW16jZSVkoZ0bGtteImSk5KIeG5tbnaFkJKRinxxbm91gY2QkIt/c3BwdH6Kj4+LgnZxcXR8iI2OjIR5c3J0e4WLjYuFe3VzdHmCioyLhn52dHR5gIiKioeAeHV1eH+GiYqHgXp2dnh9hIiJh4J8eHd4fIKHiIeDfXl4eHyBhoeHhH96eHmA', cb: { online: function() { - if (g.DEAD) { + if (ThreadUpdater.thread.isDead) { return; } if (ThreadUpdater.online = navigator.onLine) { @@ -10173,7 +10158,7 @@ ThreadUpdater.outdateCount = 0; ThreadUpdater.set('timer', '...'); } - if (!(g.DEAD || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { + if (!(ThreadUpdater.thread.isDead || ThreadUpdater.foundPost || ThreadUpdater.checkPostCount >= 5)) { return setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); } ThreadUpdater.setInterval(); @@ -10211,9 +10196,9 @@ req = ThreadUpdater.req; switch (req.status) { case 200: - g.DEAD = !!+req.response.posts[0].archived; ThreadUpdater.parse(req.response.posts); - if (g.DEAD) { + if (!!req.response.posts[0].archived) { + ThreadUpdater.thread.isArchived = true; ThreadUpdater.set('status', 'Archived', 'warning'); ThreadUpdater.kill(); } else { @@ -10242,7 +10227,6 @@ confirmed = false; } if (confirmed) { - g.DEAD = true; ThreadUpdater.set('status', '404', 'warning'); return ThreadUpdater.kill(); } else { @@ -10601,7 +10585,6 @@ }); } else { data.isDead = true; - delete data.unread; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -10641,7 +10624,7 @@ fetchStatus: function(_arg) { var boardID, data, fetchCount, threadID; boardID = _arg.boardID, threadID = _arg.threadID, data = _arg.data; - if (data.isDead) { + if (data.isDead && !Conf['Show Unread Count']) { return; } fetchCount = ThreadWatcher.fetchCount; @@ -10652,7 +10635,7 @@ fetchCount.fetching++; return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { - var lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; + var isDead, lastReadPost, postObj, status, unread, _i, _len, _ref, _ref1; fetchCount.fetched++; if (fetchCount.fetched === fetchCount.fetching) { fetchCount.fetched = 0; @@ -10664,6 +10647,15 @@ } ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { + isDead = !!this.response.posts[0].archived; + if (isDead && Conf['Auto Prune']) { + ThreadWatcher.db["delete"]({ + boardID: boardID, + threadID: threadID + }); + ThreadWatcher.refresh(); + return; + } lastReadPost = ThreadWatcher.unreaddb.get({ boardID: boardID, threadID: threadID, @@ -10681,7 +10673,8 @@ unread++; } } - if (unread !== data.unread) { + if (isDead !== data.isDead || unread !== data.unread) { + data.isDead = isDead; data.unread = unread; ThreadWatcher.db.set({ boardID: boardID, @@ -10708,8 +10701,6 @@ return ThreadWatcher.refresh(); } } - }, { - type: Conf['Show Unread Count'] ? 'get' : 'head' }); }, getAll: function() { @@ -10733,7 +10724,7 @@ return all; }, makeLine: function(boardID, threadID, data) { - var count, div, fullID, href, link, title, x; + var count, div, fullID, link, title, x; x = $.el('a', { className: 'fa fa-times', href: 'javascript:;' @@ -10747,14 +10738,8 @@ textContent: Conf['Show Unread Count'] && (data.unread != null) ? "\u00A0(" + data.unread + ")" : '', className: 'watcher-unread' }); - if (Conf['404 Redirect'] && data.isDead) { - href = Redirect.to('thread', { - boardID: boardID, - threadID: threadID - }); - } link = $.el('a', { - href: href || ("/" + boardID + "/thread/" + threadID), + href: "/" + boardID + "/thread/" + threadID, title: data.excerpt, className: 'watcher-link' }); @@ -10837,7 +10822,7 @@ val: data }); ThreadWatcher.refresh(); - if (Conf['Show Unread Count'] && !data.isDead) { + if (Conf['Show Unread Count']) { return ThreadWatcher.fetchStatus({ boardID: boardID, threadID: threadID, @@ -10921,7 +10906,7 @@ cb: ThreadWatcher.cb.pruneDeads, entry: { el: $.el('a', { - textContent: 'Prune 404\'d threads' + textContent: 'Prune dead threads' }) }, refresh: function() { @@ -11202,7 +11187,7 @@ } }), saveLastReadPost: $.debounce(2 * $.SECOND, function() { - if (Unread.thread.isDead) { + if (Unread.thread.isDead && !Unread.thread.isArchived) { return; } return Unread.db.set({ @@ -11224,16 +11209,19 @@ } }, update: function() { - var count, countQuotingYou; + var count, countQuotingYou, titleCount, titleDead, titleQuotingYou; count = Unread.posts.length; countQuotingYou = Object.keys(Unread.postsQuotingYou).length; if (Conf['Unread Count']) { - d.title = "" + (Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '') + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? Unread.title.replace('-', '- 404 -') : Unread.title); + titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : ''; + titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : ''; + titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title; + d.title = "" + titleQuotingYou + titleCount + titleDead; } if (!Conf['Unread Favicon']) { return; } - Favicon.el.href = g.DEAD ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; + Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"]; return $.add(d.head, Favicon.el); } }; @@ -12884,7 +12872,7 @@ className: 'dialog' }); $.extend(dialog, { - innerHTML: "
" + innerHTML: "
" }); $.on($('.export', Settings.dialog), 'click', Settings["export"]); $.on($('.import', Settings.dialog), 'click', Settings["import"]); @@ -13693,14 +13681,16 @@ }, initThread: function() { var board, err, errors, postRoot, posts, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1, _ref2; - g.DEAD = !!((_ref = $('.closed')) != null ? _ref.textContent.match(/Thread archived/) : void 0); if (board = $('.board')) { threads = []; posts = []; - _ref1 = $$('.board > .thread', board); - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - threadRoot = _ref1[_i]; + _ref = $$('.board > .thread', board); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + threadRoot = _ref[_i]; thread = new Thread(+threadRoot.id.slice(1), g.BOARD); + if (g.VIEW === 'thread') { + thread.isDead = thread.isArchived = !!((_ref1 = $('.closed')) != null ? _ref1.textContent.match(/Thread archived/) : void 0); + } threads.push(thread); _ref2 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip index e6d55f274..84b69f927 100644 Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml index 09b49afdf..a8ab6876c 100644 --- a/builds/updates-beta.xml +++ b/builds/updates-beta.xml @@ -1,7 +1,7 @@ - + diff --git a/builds/updates.xml b/builds/updates.xml index 2e5c015eb..2efd69bfe 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/package.json b/package.json index 71efc248d..a8c3e9e7e 100755 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X", - "version": "1.9.3.3", + "version": "1.9.3.5", "repo": "https://github.com/ccd0/4chan-x/", "page": "https://github.com/ccd0/4chan-x", "downloads": "https://ccd0.github.io/4chan-x/builds/", diff --git a/src/General/Config.coffee b/src/General/Config.coffee index 3d68cfd1c..45408e983 100755 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -476,7 +476,7 @@ Config = ] 'Auto Prune': [ false - 'Automatically prune 404\'d threads.' + 'Automatically prune dead threads.' ] 'Show Unread Count': [ true diff --git a/src/General/Main.coffee b/src/General/Main.coffee index f789700c8..2b725b9e4 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -160,14 +160,13 @@ Main = new Notice 'warning', 'Cookies need to be enabled on 4chan for <%= meta.name %> to operate properly.', 30 initThread: -> - g.DEAD = !!$('.closed')?.textContent.match(/Thread archived/) - if board = $ '.board' threads = [] posts = [] for threadRoot in $$ '.board > .thread', board thread = new Thread +threadRoot.id[1..], g.BOARD + thread.isDead = thread.isArchived = !!$('.closed')?.textContent.match(/Thread archived/) if g.VIEW is 'thread' threads.push thread for postRoot in $$ '.thread > .postContainer', threadRoot try diff --git a/src/General/UI.coffee b/src/General/UI.coffee index 44eec8030..fa30d32d6 100755 --- a/src/General/UI.coffee +++ b/src/General/UI.coffee @@ -310,7 +310,6 @@ UI = do -> isImage: el.nodeName in ['IMG', 'VIDEO'] cb endEvents - ready: false latestEvent clientHeight: doc.clientHeight clientWidth: doc.clientWidth @@ -322,7 +321,6 @@ UI = do -> $.asap -> !el.parentNode or asapTest() , -> - o.ready = true o.hover o.latestEvent if el.parentNode $.on root, endEvents, o.hoverend @@ -337,7 +335,6 @@ UI = do -> hover = (e) -> @latestEvent = e - return unless @ready height = @el.offsetHeight {clientX, clientY} = e diff --git a/src/General/lib/databoard.class b/src/General/lib/databoard.class index 923e4b8b4..f0567d78d 100755 --- a/src/General/lib/databoard.class +++ b/src/General/lib/databoard.class @@ -70,23 +70,17 @@ class DataBoard if (@data.lastChecked or 0) < now - 2 * $.HOUR @data.lastChecked = now for boardID of @data.boards - @ajaxClean boardID + for threadID of @data.boards[boardID] + @ajaxClean boardID, threadID @save() - ajaxClean: (boardID) -> - $.cache "//a.4cdn.org/#{boardID}/threads.json", (e) => - if e.target.status isnt 200 - @delete {boardID} if e.target.status is 404 - return - board = @data.boards[boardID] - threads = {} - for page in e.target.response - for thread in page.threads - if thread.no of board - threads[thread.no] = board[thread.no] - @data.boards[boardID] = threads - @deleteIfEmpty {boardID} - @save() + ajaxClean: (boardID, threadID) -> + $.ajax "//a.4cdn.org/#{boardID}/thread/#{threadID}.json", + onloadend: (e) => + if e.target.status is 404 + @delete {boardID, threadID} + , + type: 'head' onSync: (data) => @data = data or boards: {} diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index eb5ca6764..5130262c4 100755 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -74,7 +74,7 @@ ThreadUpdater = $.on d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost $.on d, 'visibilitychange', ThreadUpdater.cb.visibility - if g.DEAD + if ThreadUpdater.thread.isArchived ThreadUpdater.set 'status', 'Archived', 'warning' else ThreadUpdater.cb.online() @@ -87,7 +87,7 @@ ThreadUpdater = cb: online: -> - return if g.DEAD + return if ThreadUpdater.thread.isDead if ThreadUpdater.online = navigator.onLine ThreadUpdater.outdateCount = 0 ThreadUpdater.setInterval() @@ -105,7 +105,7 @@ ThreadUpdater = ThreadUpdater.seconds = 0 ThreadUpdater.outdateCount = 0 ThreadUpdater.set 'timer', '...' - unless g.DEAD or ThreadUpdater.foundPost or ThreadUpdater.checkPostCount >= 5 + unless ThreadUpdater.thread.isDead or ThreadUpdater.foundPost or ThreadUpdater.checkPostCount >= 5 return setTimeout ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND ThreadUpdater.setInterval() ThreadUpdater.checkPostCount = 0 @@ -131,9 +131,9 @@ ThreadUpdater = {req} = ThreadUpdater switch req.status when 200 - g.DEAD = !!+req.response.posts[0].archived ThreadUpdater.parse req.response.posts - if g.DEAD + if !!req.response.posts[0].archived + ThreadUpdater.thread.isArchived = true ThreadUpdater.set 'status', 'Archived', 'warning' ThreadUpdater.kill() else @@ -151,7 +151,6 @@ ThreadUpdater = else confirmed = false if confirmed - g.DEAD = true ThreadUpdater.set 'status', '404', 'warning' ThreadUpdater.kill() else diff --git a/src/Monitoring/ThreadWatcher.coffee b/src/Monitoring/ThreadWatcher.coffee index b9d8ccebb..596e118dc 100755 --- a/src/Monitoring/ThreadWatcher.coffee +++ b/src/Monitoring/ThreadWatcher.coffee @@ -102,13 +102,12 @@ ThreadWatcher = ThreadWatcher.db.delete {boardID, threadID} else data.isDead = true - delete data.unread ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.refresh() onThreadRefresh: (e) -> thread = g.threads[e.detail.threadID] return unless e.detail[404] and ThreadWatcher.db.get {boardID: thread.board.ID, threadID: thread.ID} - # Update 404 status. + # Update dead status. ThreadWatcher.add thread fetchCount: @@ -120,7 +119,7 @@ ThreadWatcher = ThreadWatcher.fetchStatus thread return fetchStatus: ({boardID, threadID, data}) -> - return if data.isDead + return if data.isDead and !Conf['Show Unread Count'] {fetchCount} = ThreadWatcher if fetchCount.fetching is 0 ThreadWatcher.status.textContent = '...' @@ -139,6 +138,12 @@ ThreadWatcher = ThreadWatcher.status.textContent = status if @status is 200 and @response + isDead = !!@response.posts[0].archived + if isDead and Conf['Auto Prune'] + ThreadWatcher.db.delete {boardID, threadID} + ThreadWatcher.refresh() + return + lastReadPost = ThreadWatcher.unreaddb.get boardID: boardID threadID: threadID @@ -150,7 +155,8 @@ ThreadWatcher = if postObj.no > lastReadPost and !QR.db?.get {boardID, threadID, postID: postObj.no} unread++ - if unread isnt data.unread + if isDead isnt data.isDead or unread isnt data.unread + data.isDead = isDead data.unread = unread ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.refresh() @@ -163,8 +169,6 @@ ThreadWatcher = delete data.unread ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.refresh() - , - type: if Conf['Show Unread Count'] then 'get' else 'head' getAll: -> all = [] @@ -189,10 +193,8 @@ ThreadWatcher = textContent: if Conf['Show Unread Count'] and data.unread? then "\u00A0(#{data.unread})" else '' className: 'watcher-unread' - if Conf['404 Redirect'] and data.isDead - href = Redirect.to 'thread', {boardID, threadID} link = $.el 'a', - href: href or "/#{boardID}/thread/#{threadID}" + href: "/#{boardID}/thread/#{threadID}" title: data.excerpt className: 'watcher-link' $.add link, [title, count] @@ -245,7 +247,7 @@ ThreadWatcher = data.excerpt = Get.threadExcerpt thread ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.refresh() - if Conf['Show Unread Count'] and !data.isDead + if Conf['Show Unread Count'] ThreadWatcher.fetchStatus {boardID, threadID, data} rm: (boardID, threadID) -> ThreadWatcher.db.delete {boardID, threadID} @@ -296,12 +298,12 @@ ThreadWatcher = textContent: 'Open all threads' refresh: -> (if ThreadWatcher.list.firstElementChild then $.rmClass else $.addClass) @el, 'disabled' - # `Prune 404'd threads` entry + # `Prune dead threads` entry entries.push cb: ThreadWatcher.cb.pruneDeads entry: el: $.el 'a', - textContent: 'Prune 404\'d threads' + textContent: 'Prune dead threads' refresh: -> (if $('.dead-thread', ThreadWatcher.list) then $.rmClass else $.addClass) @el, 'disabled' # `Settings` entries: diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 5dc497441..a8db0b9ec 100755 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -163,7 +163,7 @@ Unread = Unread.update() if e saveLastReadPost: $.debounce 2 * $.SECOND, -> - return if Unread.thread.isDead + return if Unread.thread.isDead and !Unread.thread.isArchived Unread.db.set boardID: Unread.thread.board.ID threadID: Unread.thread.ID @@ -180,12 +180,18 @@ Unread = countQuotingYou = Object.keys(Unread.postsQuotingYou).length if Conf['Unread Count'] - d.title = "#{if Conf['Quoted Title'] and countQuotingYou then '(!) ' else ''}#{if count or !Conf['Hide Unread Count at (0)'] then "(#{count}) " else ''}#{if g.DEAD then Unread.title.replace '-', '- 404 -' else Unread.title}" + titleQuotingYou = if Conf['Quoted Title'] and countQuotingYou then '(!) ' else '' + titleCount = if count or !Conf['Hide Unread Count at (0)'] then "(#{count}) " else '' + titleDead = if Unread.thread.isDead + Unread.title.replace '-', (if Unread.thread.isArchived then '- Archived -' else '- 404 -') + else + Unread.title + d.title = "#{titleQuotingYou}#{titleCount}#{titleDead}" return unless Conf['Unread Favicon'] Favicon.el.href = - if g.DEAD + if Unread.thread.isDead if countQuotingYou Favicon.unreadDeadY else if count diff --git a/src/Posting/QR.coffee b/src/Posting/QR.coffee index 453dfcda9..cd88b1503 100644 --- a/src/Posting/QR.coffee +++ b/src/Posting/QR.coffee @@ -80,7 +80,9 @@ QR = QR.hide() if Conf['Auto-Hide QR'] statusCheck: -> - if g.DEAD + return unless QR.nodes + {thread} = QR.posts[0] + if thread isnt 'new' and g.threads["#{g.BOARD}.#{thread}"].isDead QR.abort() else QR.status()