diff --git a/CHANGELOG.md b/CHANGELOG.md index 017472b8f..99afbb135 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ Sometimes the changelog has notes (not comprehensive) acknowledging people's wor The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x). +### v1.10.13 + +**v1.10.13.0** *(2015-05-26)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.13.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.13.0/builds/4chan-X-noupdate.crx "Chromium version")] +- Based on v1.10.12.8. +- You can now manually update the page number in thread stats by clicking on it. +- Page number in thread stats does not show on /f/. +- Change default gallery slideshow toggle keybind from `s` to `Ctrl+Right`. +- Add IJKL as an alternative to the arrow keys for the image captcha. +- Clicking on the thread watcher refresh button while it's loading threads aborts it. +- Make thread watcher a bit more efficient by fixing some cases where it wasn't sending `If-Modified-Since`. +- Restore clearing the unread count in the thread watcher when a thread 404's. +- Various minor bugfixes. + ### v1.10.12 **v1.10.12.8** *(2015-05-22)* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.12.8/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.10.12.8/builds/4chan-X-noupdate.crx "Chromium version")] diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx index 5b4434c27..4169a3cb1 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 657fdbf88..a62e2ae3a 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.10.12.8 +// @version 1.10.13.0 // @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 7b4379aec..d8cb62fb9 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.10.12.8 +// @version 1.10.13.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -346,7 +346,7 @@ 'Expand images': ['e', 'Expand all images.'], 'Open Gallery': ['g', 'Opens the gallery.'], 'Pause': ['p', 'Pause/play videos in the gallery.'], - 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'], + 'Slideshow': ['Ctrl+Right', 'Toggle the gallery slideshow mode.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'Front page': ['1', 'Jump to front page.'], @@ -396,7 +396,7 @@ doc = d.documentElement; g = { - VERSION: '1.10.12.8', + VERSION: '1.10.13.0', NAMESPACE: '4chan X.', boards: {} }; @@ -506,7 +506,7 @@ }); }; return function(url, options, extra) { - var err, form, r, type, upCallbacks, whenModified; + var err, form, r, ref, type, upCallbacks, whenModified; if (extra == null) { extra = {}; } @@ -524,11 +524,11 @@ return; } if (whenModified) { - if (url in lastModified) { - r.setRequestHeader('If-Modified-Since', lastModified[url]); + if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); } $.on(r, 'load', function() { - return lastModified[url] = r.getResponseHeader('Last-Modified'); + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); }); } if (/\.json$/.test(url)) { @@ -3625,7 +3625,7 @@ return Index.load(e, state); } }, { - whenModified: true + whenModified: 'Index' }); return $.addClass(Index.button, 'fa-spin'); }, @@ -6221,7 +6221,7 @@ }, mouseover: function(e) { var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; - if ($.hasClass(this, 'inlined')) { + if ($.hasClass(this, 'inlined') || !d.contains(this)) { return; } ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; @@ -7736,7 +7736,11 @@ 38: 9, 40: 3, 37: 11, - 39: 1 + 39: 1, + 73: 9, + 75: 3, + 74: 11, + 76: 1 }[e.keyCode])) { return; } @@ -11999,13 +12003,13 @@ return; } statsHTML = { - innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") + innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / ?" : "") }; statsTitle = 'Posts / Files'; if (Conf['IP Count in Stats']) { statsTitle += ' / IPs'; } - if (Conf['Page Count in Stats']) { + if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') { statsTitle += ' / Page'; } if (Conf['Updater and Stats in Header']) { @@ -12030,6 +12034,9 @@ this.fileCountEl = $('#file-count', sc); this.ipCountEl = $('#ip-count', sc); this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } return Thread.callbacks.push({ name: 'Thread Stats', cb: this.node @@ -12044,7 +12051,7 @@ if (post.file) { fileCount++; } - if (Conf["Page Count in Stats"]) { + if (ThreadStats.pageCountEl) { return ThreadStats.lastPost = post.info.date; } }); @@ -12060,13 +12067,13 @@ } ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts; ThreadStats.update(postCount, fileCount, ipCount); - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } if (newPosts.length) { ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; } - if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { + if (((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { return ThreadStats.fetchPage(); } }, @@ -12075,14 +12082,14 @@ thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; - if ((ipCount != null) && Conf["IP Count in Stats"]) { + if ((ipCount != null) && ipCountEl) { ipCountEl.textContent = ipCount; } (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); }, fetchPage: function() { - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } clearTimeout(ThreadStats.timeout); @@ -12095,28 +12102,37 @@ return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { onload: ThreadStats.onThreadsLoad }, { - whenModified: true + whenModified: 'ThreadStats' }); }, onThreadsLoad: function() { var k, len1, len2, page, q, ref, ref1, thread; - if (!(Conf["Page Count in Stats"] && this.status === 200)) { - return; - } - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (!(thread.no === ThreadStats.thread.ID)) { - continue; + if (this.status === 200) { + ref = this.response; + for (k = 0, len1 = ref.length; k < len1; k++) { + page = ref[k]; + ref1 = page.threads; + for (q = 0, len2 = ref1.length; q < len2; q++) { + thread = ref1[q]; + if (!(thread.no === ThreadStats.thread.ID)) { + continue; + } + ThreadStats.pageCountEl.textContent = page.page; + (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); + ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); + ThreadStats.retry(); + return; } - ThreadStats.pageCountEl.textContent = page.page; - (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); - ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); - return; } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); } } }; @@ -12411,7 +12427,7 @@ onloadend: ThreadUpdater.cb.load, timeout: $.MINUTE }, { - whenModified: true + whenModified: 'ThreadUpdater' }); }, updateThreadStatus: function(type, status) { @@ -12569,7 +12585,7 @@ this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); $.on(d, 'QRPostSuccessful', this.cb.post); $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.fetchAllStatus); + $.on(this.refreshButton, 'click', this.buttonFetchAll); $.on(this.closeButton, 'click', this.toggleWatcher); $.on(d, '4chanXInitFinished', this.ready); switch (g.VIEW) { @@ -12649,7 +12665,7 @@ if (ThreadWatcher.isWatched(this.thread)) { $.addClass(this.nodes.root, 'watched'); } - return $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { + $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { return function(e) { if (!(e.button === 0 && e.altKey)) { return; @@ -12658,6 +12674,11 @@ return e.preventDefault(); }; })(this)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); }, ready: function() { $.off(d, '4chanXInitFinished', ThreadWatcher.ready); @@ -12750,13 +12771,20 @@ data = ref[threadID]; if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - ThreadWatcher.db["delete"]({ + db["delete"]({ boardID: boardID, threadID: threadID }); } else { + if (Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } data.isDead = true; - ThreadWatcher.db.set({ + db.set({ boardID: boardID, threadID: threadID, val: data @@ -12778,9 +12806,24 @@ return ThreadWatcher.add(thread); } }, - fetchCount: { - fetched: 0, - fetching: 0 + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var k, len1, ref, req; + ref = ThreadWatcher.requests; + for (k = 0, len1 = ref.length; k < len1; k++) { + req = ref[k]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); }, fetchAuto: function() { var db, interval, now; @@ -12798,6 +12841,13 @@ } return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, fetchAllStatus: function() { var k, len1, ref, thread, threads; ThreadWatcher.db.forceSync(); @@ -12814,37 +12864,34 @@ } }, fetchStatus: function(thread, force) { - var boardID, data, fetchCount, threadID; + var boardID, data, req, threadID; boardID = thread.boardID, threadID = thread.threadID, data = thread.data; if (data.isDead && !force) { return; } - fetchCount = ThreadWatcher.fetchCount; - if (fetchCount.fetching === 0) { + if (ThreadWatcher.requests.length === 0) { ThreadWatcher.status.textContent = '...'; $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); } - fetchCount.fetching++; - return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { return ThreadWatcher.parseStatus.call(this, thread); - } + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' }); + return ThreadWatcher.requests.push(req); }, parseStatus: function(arg) { - var boardID, data, fetchCount, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, status, threadID, unread; + var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - fetchCount = ThreadWatcher.fetchCount; - fetchCount.fetched++; - if (fetchCount.fetched === fetchCount.fetching) { - fetchCount.fetched = 0; - fetchCount.fetching = 0; - status = ''; - $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); } else { - status = (Math.round(fetchCount.fetched / fetchCount.fetching * 100)) + "%"; + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; } - ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { isDead = !!this.response.posts[0].archived; if (isDead && Conf['Auto Prune']) { @@ -12913,6 +12960,8 @@ }); } else { data.isDead = true; + delete data.unread; + delete data.quotingYou; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -14585,21 +14634,25 @@ }); }, code: function() { - var i, k, len1, pre, ref; if (this.isClone) { return; } - ref = $$('.prettyprint', this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } + return $.ready((function(_this) { + return function() { + var i, k, len1, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); }, math: function() { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { @@ -18118,6 +18171,9 @@ ":root.float #thread-stats {\n" + " padding: 0px 3px;\n" + "}\n" + +"#page-count {\n" + +" cursor: pointer;\n" + +"}\n" + "/* Quote */\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + " color: #789922;\n" + diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx index 79360c968..25b873ca0 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 b70f286a8..9a0e0b91d 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.10.12.8 +// @version 1.10.13.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -345,7 +345,7 @@ 'Expand images': ['e', 'Expand all images.'], 'Open Gallery': ['g', 'Opens the gallery.'], 'Pause': ['p', 'Pause/play videos in the gallery.'], - 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'], + 'Slideshow': ['Ctrl+Right', 'Toggle the gallery slideshow mode.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'Front page': ['1', 'Jump to front page.'], @@ -395,7 +395,7 @@ doc = d.documentElement; g = { - VERSION: '1.10.12.8', + VERSION: '1.10.13.0', NAMESPACE: '4chan X.', boards: {} }; @@ -505,7 +505,7 @@ }); }; return function(url, options, extra) { - var err, form, r, type, upCallbacks, whenModified; + var err, form, r, ref, type, upCallbacks, whenModified; if (extra == null) { extra = {}; } @@ -523,11 +523,11 @@ return; } if (whenModified) { - if (url in lastModified) { - r.setRequestHeader('If-Modified-Since', lastModified[url]); + if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); } $.on(r, 'load', function() { - return lastModified[url] = r.getResponseHeader('Last-Modified'); + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); }); } if (/\.json$/.test(url)) { @@ -3624,7 +3624,7 @@ return Index.load(e, state); } }, { - whenModified: true + whenModified: 'Index' }); return $.addClass(Index.button, 'fa-spin'); }, @@ -6220,7 +6220,7 @@ }, mouseover: function(e) { var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; - if ($.hasClass(this, 'inlined')) { + if ($.hasClass(this, 'inlined') || !d.contains(this)) { return; } ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; @@ -7735,7 +7735,11 @@ 38: 9, 40: 3, 37: 11, - 39: 1 + 39: 1, + 73: 9, + 75: 3, + 74: 11, + 76: 1 }[e.keyCode])) { return; } @@ -11998,13 +12002,13 @@ return; } statsHTML = { - innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") + innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / ?" : "") }; statsTitle = 'Posts / Files'; if (Conf['IP Count in Stats']) { statsTitle += ' / IPs'; } - if (Conf['Page Count in Stats']) { + if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') { statsTitle += ' / Page'; } if (Conf['Updater and Stats in Header']) { @@ -12029,6 +12033,9 @@ this.fileCountEl = $('#file-count', sc); this.ipCountEl = $('#ip-count', sc); this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } return Thread.callbacks.push({ name: 'Thread Stats', cb: this.node @@ -12043,7 +12050,7 @@ if (post.file) { fileCount++; } - if (Conf["Page Count in Stats"]) { + if (ThreadStats.pageCountEl) { return ThreadStats.lastPost = post.info.date; } }); @@ -12059,13 +12066,13 @@ } ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts; ThreadStats.update(postCount, fileCount, ipCount); - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } if (newPosts.length) { ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; } - if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { + if (((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { return ThreadStats.fetchPage(); } }, @@ -12074,14 +12081,14 @@ thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; - if ((ipCount != null) && Conf["IP Count in Stats"]) { + if ((ipCount != null) && ipCountEl) { ipCountEl.textContent = ipCount; } (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); }, fetchPage: function() { - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } clearTimeout(ThreadStats.timeout); @@ -12094,28 +12101,37 @@ return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { onload: ThreadStats.onThreadsLoad }, { - whenModified: true + whenModified: 'ThreadStats' }); }, onThreadsLoad: function() { var k, len1, len2, page, q, ref, ref1, thread; - if (!(Conf["Page Count in Stats"] && this.status === 200)) { - return; - } - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (!(thread.no === ThreadStats.thread.ID)) { - continue; + if (this.status === 200) { + ref = this.response; + for (k = 0, len1 = ref.length; k < len1; k++) { + page = ref[k]; + ref1 = page.threads; + for (q = 0, len2 = ref1.length; q < len2; q++) { + thread = ref1[q]; + if (!(thread.no === ThreadStats.thread.ID)) { + continue; + } + ThreadStats.pageCountEl.textContent = page.page; + (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); + ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); + ThreadStats.retry(); + return; } - ThreadStats.pageCountEl.textContent = page.page; - (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); - ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); - return; } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); } } }; @@ -12410,7 +12426,7 @@ onloadend: ThreadUpdater.cb.load, timeout: $.MINUTE }, { - whenModified: true + whenModified: 'ThreadUpdater' }); }, updateThreadStatus: function(type, status) { @@ -12568,7 +12584,7 @@ this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); $.on(d, 'QRPostSuccessful', this.cb.post); $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.fetchAllStatus); + $.on(this.refreshButton, 'click', this.buttonFetchAll); $.on(this.closeButton, 'click', this.toggleWatcher); $.on(d, '4chanXInitFinished', this.ready); switch (g.VIEW) { @@ -12648,7 +12664,7 @@ if (ThreadWatcher.isWatched(this.thread)) { $.addClass(this.nodes.root, 'watched'); } - return $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { + $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { return function(e) { if (!(e.button === 0 && e.altKey)) { return; @@ -12657,6 +12673,11 @@ return e.preventDefault(); }; })(this)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); }, ready: function() { $.off(d, '4chanXInitFinished', ThreadWatcher.ready); @@ -12749,13 +12770,20 @@ data = ref[threadID]; if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - ThreadWatcher.db["delete"]({ + db["delete"]({ boardID: boardID, threadID: threadID }); } else { + if (Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } data.isDead = true; - ThreadWatcher.db.set({ + db.set({ boardID: boardID, threadID: threadID, val: data @@ -12777,9 +12805,24 @@ return ThreadWatcher.add(thread); } }, - fetchCount: { - fetched: 0, - fetching: 0 + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var k, len1, ref, req; + ref = ThreadWatcher.requests; + for (k = 0, len1 = ref.length; k < len1; k++) { + req = ref[k]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); }, fetchAuto: function() { var db, interval, now; @@ -12797,6 +12840,13 @@ } return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, fetchAllStatus: function() { var k, len1, ref, thread, threads; ThreadWatcher.db.forceSync(); @@ -12813,37 +12863,34 @@ } }, fetchStatus: function(thread, force) { - var boardID, data, fetchCount, threadID; + var boardID, data, req, threadID; boardID = thread.boardID, threadID = thread.threadID, data = thread.data; if (data.isDead && !force) { return; } - fetchCount = ThreadWatcher.fetchCount; - if (fetchCount.fetching === 0) { + if (ThreadWatcher.requests.length === 0) { ThreadWatcher.status.textContent = '...'; $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); } - fetchCount.fetching++; - return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { return ThreadWatcher.parseStatus.call(this, thread); - } + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' }); + return ThreadWatcher.requests.push(req); }, parseStatus: function(arg) { - var boardID, data, fetchCount, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, status, threadID, unread; + var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - fetchCount = ThreadWatcher.fetchCount; - fetchCount.fetched++; - if (fetchCount.fetched === fetchCount.fetching) { - fetchCount.fetched = 0; - fetchCount.fetching = 0; - status = ''; - $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); } else { - status = (Math.round(fetchCount.fetched / fetchCount.fetching * 100)) + "%"; + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; } - ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { isDead = !!this.response.posts[0].archived; if (isDead && Conf['Auto Prune']) { @@ -12912,6 +12959,8 @@ }); } else { data.isDead = true; + delete data.unread; + delete data.quotingYou; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -14584,21 +14633,25 @@ }); }, code: function() { - var i, k, len1, pre, ref; if (this.isClone) { return; } - ref = $$('.prettyprint', this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } + return $.ready((function(_this) { + return function() { + var i, k, len1, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); }, math: function() { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { @@ -18117,6 +18170,9 @@ ":root.float #thread-stats {\n" + " padding: 0px 3px;\n" + "}\n" + +"#page-count {\n" + +" cursor: pointer;\n" + +"}\n" + "/* Quote */\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + " color: #789922;\n" + diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx index 3157fb627..b41d6512b 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 51de66ef6..aceeea2e8 100644 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.10.12.8 +// @version 1.10.13.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index b50e4c44e..6a44e53a5 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.10.12.8 +// @version 1.10.13.0 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -346,7 +346,7 @@ 'Expand images': ['e', 'Expand all images.'], 'Open Gallery': ['g', 'Opens the gallery.'], 'Pause': ['p', 'Pause/play videos in the gallery.'], - 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'], + 'Slideshow': ['Ctrl+Right', 'Toggle the gallery slideshow mode.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'Front page': ['1', 'Jump to front page.'], @@ -396,7 +396,7 @@ doc = d.documentElement; g = { - VERSION: '1.10.12.8', + VERSION: '1.10.13.0', NAMESPACE: '4chan X.', boards: {} }; @@ -506,7 +506,7 @@ }); }; return function(url, options, extra) { - var err, form, r, type, upCallbacks, whenModified; + var err, form, r, ref, type, upCallbacks, whenModified; if (extra == null) { extra = {}; } @@ -524,11 +524,11 @@ return; } if (whenModified) { - if (url in lastModified) { - r.setRequestHeader('If-Modified-Since', lastModified[url]); + if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) { + r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]); } $.on(r, 'load', function() { - return lastModified[url] = r.getResponseHeader('Last-Modified'); + return (lastModified[whenModified] || (lastModified[whenModified] = {}))[url] = r.getResponseHeader('Last-Modified'); }); } if (/\.json$/.test(url)) { @@ -3625,7 +3625,7 @@ return Index.load(e, state); } }, { - whenModified: true + whenModified: 'Index' }); return $.addClass(Index.button, 'fa-spin'); }, @@ -6221,7 +6221,7 @@ }, mouseover: function(e) { var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; - if ($.hasClass(this, 'inlined')) { + if ($.hasClass(this, 'inlined') || !d.contains(this)) { return; } ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; @@ -7736,7 +7736,11 @@ 38: 9, 40: 3, 37: 11, - 39: 1 + 39: 1, + 73: 9, + 75: 3, + 74: 11, + 76: 1 }[e.keyCode])) { return; } @@ -11999,13 +12003,13 @@ return; } statsHTML = { - innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] ? " / ?" : "") + innerHTML: "? / ?" + (Conf["IP Count in Stats"] ? " / ?" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / ?" : "") }; statsTitle = 'Posts / Files'; if (Conf['IP Count in Stats']) { statsTitle += ' / IPs'; } - if (Conf['Page Count in Stats']) { + if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') { statsTitle += ' / Page'; } if (Conf['Updater and Stats in Header']) { @@ -12030,6 +12034,9 @@ this.fileCountEl = $('#file-count', sc); this.ipCountEl = $('#ip-count', sc); this.pageCountEl = $('#page-count', sc); + if (this.pageCountEl) { + $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); + } return Thread.callbacks.push({ name: 'Thread Stats', cb: this.node @@ -12044,7 +12051,7 @@ if (post.file) { fileCount++; } - if (Conf["Page Count in Stats"]) { + if (ThreadStats.pageCountEl) { return ThreadStats.lastPost = post.info.date; } }); @@ -12060,13 +12067,13 @@ } ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts; ThreadStats.update(postCount, fileCount, ipCount); - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } if (newPosts.length) { ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; } - if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { + if (((ref1 = ThreadStats.pageCountEl) != null ? ref1.textContent : void 0) !== '1') { return ThreadStats.fetchPage(); } }, @@ -12075,14 +12082,14 @@ thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; postCountEl.textContent = postCount; fileCountEl.textContent = fileCount; - if ((ipCount != null) && Conf["IP Count in Stats"]) { + if ((ipCount != null) && ipCountEl) { ipCountEl.textContent = ipCount; } (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); }, fetchPage: function() { - if (!Conf["Page Count in Stats"]) { + if (!ThreadStats.pageCountEl) { return; } clearTimeout(ThreadStats.timeout); @@ -12095,28 +12102,37 @@ return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { onload: ThreadStats.onThreadsLoad }, { - whenModified: true + whenModified: 'ThreadStats' }); }, onThreadsLoad: function() { var k, len1, len2, page, q, ref, ref1, thread; - if (!(Conf["Page Count in Stats"] && this.status === 200)) { - return; - } - ref = this.response; - for (k = 0, len1 = ref.length; k < len1; k++) { - page = ref[k]; - ref1 = page.threads; - for (q = 0, len2 = ref1.length; q < len2; q++) { - thread = ref1[q]; - if (!(thread.no === ThreadStats.thread.ID)) { - continue; + if (this.status === 200) { + ref = this.response; + for (k = 0, len1 = ref.length; k < len1; k++) { + page = ref[k]; + ref1 = page.threads; + for (q = 0, len2 = ref1.length; q < len2; q++) { + thread = ref1[q]; + if (!(thread.no === ThreadStats.thread.ID)) { + continue; + } + ThreadStats.pageCountEl.textContent = page.page; + (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); + ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); + ThreadStats.retry(); + return; } - ThreadStats.pageCountEl.textContent = page.page; - (page.page === this.response.length ? $.addClass : $.rmClass)(ThreadStats.pageCountEl, 'warning'); - ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); - return; } + } else if (this.status === 304) { + return ThreadStats.retry(); + } + }, + retry: function() { + var ref; + if (ThreadStats.lastPost > ThreadStats.lastPageUpdate && ((ref = ThreadStats.pageCountEl) != null ? ref.textContent : void 0) !== '1') { + clearTimeout(ThreadStats.timeout); + return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); } } }; @@ -12411,7 +12427,7 @@ onloadend: ThreadUpdater.cb.load, timeout: $.MINUTE }, { - whenModified: true + whenModified: 'ThreadUpdater' }); }, updateThreadStatus: function(type, status) { @@ -12569,7 +12585,7 @@ this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); $.on(d, 'QRPostSuccessful', this.cb.post); $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.fetchAllStatus); + $.on(this.refreshButton, 'click', this.buttonFetchAll); $.on(this.closeButton, 'click', this.toggleWatcher); $.on(d, '4chanXInitFinished', this.ready); switch (g.VIEW) { @@ -12649,7 +12665,7 @@ if (ThreadWatcher.isWatched(this.thread)) { $.addClass(this.nodes.root, 'watched'); } - return $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { + $.on(this.nodes.thumb.parentNode, 'click', (function(_this) { return function(e) { if (!(e.button === 0 && e.altKey)) { return; @@ -12658,6 +12674,11 @@ return e.preventDefault(); }; })(this)); + return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) { + if (e.button === 0 && e.altKey) { + return e.preventDefault(); + } + }); }, ready: function() { $.off(d, '4chanXInitFinished', ThreadWatcher.ready); @@ -12750,13 +12771,20 @@ data = ref[threadID]; if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - ThreadWatcher.db["delete"]({ + db["delete"]({ boardID: boardID, threadID: threadID }); } else { + if (Conf['Show Unread Count']) { + ThreadWatcher.fetchStatus({ + boardID: boardID, + threadID: threadID, + data: data + }); + } data.isDead = true; - ThreadWatcher.db.set({ + db.set({ boardID: boardID, threadID: threadID, val: data @@ -12778,9 +12806,24 @@ return ThreadWatcher.add(thread); } }, - fetchCount: { - fetched: 0, - fetching: 0 + requests: [], + fetched: 0, + clearRequests: function() { + ThreadWatcher.requests = []; + ThreadWatcher.fetched = 0; + ThreadWatcher.status.textContent = ''; + return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + }, + abort: function() { + var k, len1, ref, req; + ref = ThreadWatcher.requests; + for (k = 0, len1 = ref.length; k < len1; k++) { + req = ref[k]; + if (req.readyState !== 4) { + req.abort(); + } + } + return ThreadWatcher.clearRequests(); }, fetchAuto: function() { var db, interval, now; @@ -12798,6 +12841,13 @@ } return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); }, + buttonFetchAll: function() { + if (ThreadWatcher.requests.length) { + return ThreadWatcher.abort(); + } else { + return ThreadWatcher.fetchAllStatus(); + } + }, fetchAllStatus: function() { var k, len1, ref, thread, threads; ThreadWatcher.db.forceSync(); @@ -12814,37 +12864,34 @@ } }, fetchStatus: function(thread, force) { - var boardID, data, fetchCount, threadID; + var boardID, data, req, threadID; boardID = thread.boardID, threadID = thread.threadID, data = thread.data; if (data.isDead && !force) { return; } - fetchCount = ThreadWatcher.fetchCount; - if (fetchCount.fetching === 0) { + if (ThreadWatcher.requests.length === 0) { ThreadWatcher.status.textContent = '...'; $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); } - fetchCount.fetching++; - return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { + req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", { onloadend: function() { return ThreadWatcher.parseStatus.call(this, thread); - } + }, + timeout: $.MINUTE + }, { + whenModified: force ? false : 'ThreadWatcher' }); + return ThreadWatcher.requests.push(req); }, parseStatus: function(arg) { - var boardID, data, fetchCount, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, status, threadID, unread; + var boardID, data, isDead, k, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, regexp, threadID, unread; boardID = arg.boardID, threadID = arg.threadID, data = arg.data; - fetchCount = ThreadWatcher.fetchCount; - fetchCount.fetched++; - if (fetchCount.fetched === fetchCount.fetching) { - fetchCount.fetched = 0; - fetchCount.fetching = 0; - status = ''; - $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); + ThreadWatcher.fetched++; + if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { + ThreadWatcher.clearRequests(); } else { - status = (Math.round(fetchCount.fetched / fetchCount.fetching * 100)) + "%"; + ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; } - ThreadWatcher.status.textContent = status; if (this.status === 200 && this.response) { isDead = !!this.response.posts[0].archived; if (isDead && Conf['Auto Prune']) { @@ -12913,6 +12960,8 @@ }); } else { data.isDead = true; + delete data.unread; + delete data.quotingYou; ThreadWatcher.db.set({ boardID: boardID, threadID: threadID, @@ -14585,21 +14634,25 @@ }); }, code: function() { - var i, k, len1, pre, ref; if (this.isClone) { return; } - ref = $$('.prettyprint', this.nodes.comment); - for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } + return $.ready((function(_this) { + return function() { + var i, k, len1, pre, ref; + ref = $$('.prettyprint', _this.nodes.comment); + for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { + pre = ref[i]; + if (!$.hasClass(pre, 'prettyprinted')) { + $.event('prettyprint', { + ID: _this.fullID, + i: i, + html: pre.innerHTML + }, window); + } + } + }; + })(this)); }, math: function() { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { @@ -18118,6 +18171,9 @@ ":root.float #thread-stats {\n" + " padding: 0px 3px;\n" + "}\n" + +"#page-count {\n" + +" cursor: pointer;\n" + +"}\n" + "/* Quote */\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + " color: #789922;\n" + diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip index e91fcf4e2..19f25396e 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 faf578856..93bb6a15f 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 3bbe3fcea..5713c8ca0 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/package.json b/package.json index 7b4470fc6..93008767b 100755 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X", - "version": "1.10.12.8", - "date": "2015-05-22T20:36:38.853Z", + "version": "1.10.13.0", + "date": "2015-05-27T03:12:34.213Z", "repo": "https://github.com/ccd0/4chan-x/", "page": "https://github.com/ccd0/4chan-x", "downloads": "https://ccd0.github.io/4chan-x/builds/",