Release 4chan X v1.10.13.0.

This commit is contained in:
ccd0 2015-05-26 20:13:53 -07:00
parent dfc3f8a9cc
commit 68ba762907
13 changed files with 394 additions and 213 deletions

View File

@ -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). 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
**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")] **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")]

Binary file not shown.

View File

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

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X beta // @name 4chan X beta
// @version 1.10.12.8 // @version 1.10.13.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -346,7 +346,7 @@
'Expand images': ['e', 'Expand all images.'], 'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'], 'Open Gallery': ['g', 'Opens the gallery.'],
'Pause': ['p', 'Pause/play videos in 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.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'], 'Front page': ['1', 'Jump to front page.'],
@ -396,7 +396,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.12.8', VERSION: '1.10.13.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -506,7 +506,7 @@
}); });
}; };
return function(url, options, extra) { return function(url, options, extra) {
var err, form, r, type, upCallbacks, whenModified; var err, form, r, ref, type, upCallbacks, whenModified;
if (extra == null) { if (extra == null) {
extra = {}; extra = {};
} }
@ -524,11 +524,11 @@
return; return;
} }
if (whenModified) { if (whenModified) {
if (url in lastModified) { if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) {
r.setRequestHeader('If-Modified-Since', lastModified[url]); r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]);
} }
$.on(r, 'load', function() { $.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)) { if (/\.json$/.test(url)) {
@ -3625,7 +3625,7 @@
return Index.load(e, state); return Index.load(e, state);
} }
}, { }, {
whenModified: true whenModified: 'Index'
}); });
return $.addClass(Index.button, 'fa-spin'); return $.addClass(Index.button, 'fa-spin');
}, },
@ -6221,7 +6221,7 @@
}, },
mouseover: function(e) { mouseover: function(e) {
var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; 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; return;
} }
ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID;
@ -7736,7 +7736,11 @@
38: 9, 38: 9,
40: 3, 40: 3,
37: 11, 37: 11,
39: 1 39: 1,
73: 9,
75: 3,
74: 11,
76: 1
}[e.keyCode])) { }[e.keyCode])) {
return; return;
} }
@ -11999,13 +12003,13 @@
return; return;
} }
statsHTML = { statsHTML = {
innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] ? " / <span id=\"page-count\">?</span>" : "") innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / <span id=\"page-count\">?</span>" : "")
}; };
statsTitle = 'Posts / Files'; statsTitle = 'Posts / Files';
if (Conf['IP Count in Stats']) { if (Conf['IP Count in Stats']) {
statsTitle += ' / IPs'; statsTitle += ' / IPs';
} }
if (Conf['Page Count in Stats']) { if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') {
statsTitle += ' / Page'; statsTitle += ' / Page';
} }
if (Conf['Updater and Stats in Header']) { if (Conf['Updater and Stats in Header']) {
@ -12030,6 +12034,9 @@
this.fileCountEl = $('#file-count', sc); this.fileCountEl = $('#file-count', sc);
this.ipCountEl = $('#ip-count', sc); this.ipCountEl = $('#ip-count', sc);
this.pageCountEl = $('#page-count', sc); this.pageCountEl = $('#page-count', sc);
if (this.pageCountEl) {
$.on(this.pageCountEl, 'click', ThreadStats.fetchPage);
}
return Thread.callbacks.push({ return Thread.callbacks.push({
name: 'Thread Stats', name: 'Thread Stats',
cb: this.node cb: this.node
@ -12044,7 +12051,7 @@
if (post.file) { if (post.file) {
fileCount++; fileCount++;
} }
if (Conf["Page Count in Stats"]) { if (ThreadStats.pageCountEl) {
return ThreadStats.lastPost = post.info.date; 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; ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts;
ThreadStats.update(postCount, fileCount, ipCount); ThreadStats.update(postCount, fileCount, ipCount);
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
if (newPosts.length) { if (newPosts.length) {
ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; 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(); return ThreadStats.fetchPage();
} }
}, },
@ -12075,14 +12082,14 @@
thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl;
postCountEl.textContent = postCount; postCountEl.textContent = postCount;
fileCountEl.textContent = fileCount; fileCountEl.textContent = fileCount;
if ((ipCount != null) && Conf["IP Count in Stats"]) { if ((ipCount != null) && ipCountEl) {
ipCountEl.textContent = ipCount; ipCountEl.textContent = ipCount;
} }
(thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning');
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
}, },
fetchPage: function() { fetchPage: function() {
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
clearTimeout(ThreadStats.timeout); clearTimeout(ThreadStats.timeout);
@ -12095,28 +12102,37 @@
return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", {
onload: ThreadStats.onThreadsLoad onload: ThreadStats.onThreadsLoad
}, { }, {
whenModified: true whenModified: 'ThreadStats'
}); });
}, },
onThreadsLoad: function() { onThreadsLoad: function() {
var k, len1, len2, page, q, ref, ref1, thread; var k, len1, len2, page, q, ref, ref1, thread;
if (!(Conf["Page Count in Stats"] && this.status === 200)) { if (this.status === 200) {
return; ref = this.response;
} for (k = 0, len1 = ref.length; k < len1; k++) {
ref = this.response; page = ref[k];
for (k = 0, len1 = ref.length; k < len1; k++) { ref1 = page.threads;
page = ref[k]; for (q = 0, len2 = ref1.length; q < len2; q++) {
ref1 = page.threads; thread = ref1[q];
for (q = 0, len2 = ref1.length; q < len2; q++) { if (!(thread.no === ThreadStats.thread.ID)) {
thread = ref1[q]; continue;
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, onloadend: ThreadUpdater.cb.load,
timeout: $.MINUTE timeout: $.MINUTE
}, { }, {
whenModified: true whenModified: 'ThreadUpdater'
}); });
}, },
updateThreadStatus: function(type, status) { updateThreadStatus: function(type, status) {
@ -12569,7 +12585,7 @@
this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
$.on(d, 'QRPostSuccessful', this.cb.post); $.on(d, 'QRPostSuccessful', this.cb.post);
$.on(sc, 'click', this.toggleWatcher); $.on(sc, 'click', this.toggleWatcher);
$.on(this.refreshButton, 'click', this.fetchAllStatus); $.on(this.refreshButton, 'click', this.buttonFetchAll);
$.on(this.closeButton, 'click', this.toggleWatcher); $.on(this.closeButton, 'click', this.toggleWatcher);
$.on(d, '4chanXInitFinished', this.ready); $.on(d, '4chanXInitFinished', this.ready);
switch (g.VIEW) { switch (g.VIEW) {
@ -12649,7 +12665,7 @@
if (ThreadWatcher.isWatched(this.thread)) { if (ThreadWatcher.isWatched(this.thread)) {
$.addClass(this.nodes.root, 'watched'); $.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) { return function(e) {
if (!(e.button === 0 && e.altKey)) { if (!(e.button === 0 && e.altKey)) {
return; return;
@ -12658,6 +12674,11 @@
return e.preventDefault(); return e.preventDefault();
}; };
})(this)); })(this));
return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) {
if (e.button === 0 && e.altKey) {
return e.preventDefault();
}
});
}, },
ready: function() { ready: function() {
$.off(d, '4chanXInitFinished', ThreadWatcher.ready); $.off(d, '4chanXInitFinished', ThreadWatcher.ready);
@ -12750,13 +12771,20 @@
data = ref[threadID]; data = ref[threadID];
if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) {
if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) {
ThreadWatcher.db["delete"]({ db["delete"]({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else { } else {
if (Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({
boardID: boardID,
threadID: threadID,
data: data
});
}
data.isDead = true; data.isDead = true;
ThreadWatcher.db.set({ db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
val: data val: data
@ -12778,9 +12806,24 @@
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
fetchCount: { requests: [],
fetched: 0, fetched: 0,
fetching: 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() { fetchAuto: function() {
var db, interval, now; var db, interval, now;
@ -12798,6 +12841,13 @@
} }
return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval);
}, },
buttonFetchAll: function() {
if (ThreadWatcher.requests.length) {
return ThreadWatcher.abort();
} else {
return ThreadWatcher.fetchAllStatus();
}
},
fetchAllStatus: function() { fetchAllStatus: function() {
var k, len1, ref, thread, threads; var k, len1, ref, thread, threads;
ThreadWatcher.db.forceSync(); ThreadWatcher.db.forceSync();
@ -12814,37 +12864,34 @@
} }
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, fetchCount, threadID; var boardID, data, req, threadID;
boardID = thread.boardID, threadID = thread.threadID, data = thread.data; boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
fetchCount = ThreadWatcher.fetchCount; if (ThreadWatcher.requests.length === 0) {
if (fetchCount.fetching === 0) {
ThreadWatcher.status.textContent = '...'; ThreadWatcher.status.textContent = '...';
$.addClass(ThreadWatcher.refreshButton, 'fa-spin'); $.addClass(ThreadWatcher.refreshButton, 'fa-spin');
} }
fetchCount.fetching++; req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
onloadend: function() { onloadend: function() {
return ThreadWatcher.parseStatus.call(this, thread); return ThreadWatcher.parseStatus.call(this, thread);
} },
timeout: $.MINUTE
}, {
whenModified: force ? false : 'ThreadWatcher'
}); });
return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { 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; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
fetchCount = ThreadWatcher.fetchCount; ThreadWatcher.fetched++;
fetchCount.fetched++; if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
if (fetchCount.fetched === fetchCount.fetching) { ThreadWatcher.clearRequests();
fetchCount.fetched = 0;
fetchCount.fetching = 0;
status = '';
$.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
} else { } 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) { if (this.status === 200 && this.response) {
isDead = !!this.response.posts[0].archived; isDead = !!this.response.posts[0].archived;
if (isDead && Conf['Auto Prune']) { if (isDead && Conf['Auto Prune']) {
@ -12913,6 +12960,8 @@
}); });
} else { } else {
data.isDead = true; data.isDead = true;
delete data.unread;
delete data.quotingYou;
ThreadWatcher.db.set({ ThreadWatcher.db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -14585,21 +14634,25 @@
}); });
}, },
code: function() { code: function() {
var i, k, len1, pre, ref;
if (this.isClone) { if (this.isClone) {
return; return;
} }
ref = $$('.prettyprint', this.nodes.comment); return $.ready((function(_this) {
for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { return function() {
pre = ref[i]; var i, k, len1, pre, ref;
if (!$.hasClass(pre, 'prettyprinted')) { ref = $$('.prettyprint', _this.nodes.comment);
$.event('prettyprint', { for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
ID: this.fullID, pre = ref[i];
i: i, if (!$.hasClass(pre, 'prettyprinted')) {
html: pre.innerHTML $.event('prettyprint', {
}, window); ID: _this.fullID,
} i: i,
} html: pre.innerHTML
}, window);
}
}
};
})(this));
}, },
math: function() { math: function() {
if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) {
@ -18118,6 +18171,9 @@
":root.float #thread-stats {\n" + ":root.float #thread-stats {\n" +
" padding: 0px 3px;\n" + " padding: 0px 3px;\n" +
"}\n" + "}\n" +
"#page-count {\n" +
" cursor: pointer;\n" +
"}\n" +
"/* Quote */\n" + "/* Quote */\n" +
".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" +
" color: #789922;\n" + " color: #789922;\n" +

Binary file not shown.

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.10.12.8 // @version 1.10.13.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -345,7 +345,7 @@
'Expand images': ['e', 'Expand all images.'], 'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'], 'Open Gallery': ['g', 'Opens the gallery.'],
'Pause': ['p', 'Pause/play videos in 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.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'], 'Front page': ['1', 'Jump to front page.'],
@ -395,7 +395,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.12.8', VERSION: '1.10.13.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -505,7 +505,7 @@
}); });
}; };
return function(url, options, extra) { return function(url, options, extra) {
var err, form, r, type, upCallbacks, whenModified; var err, form, r, ref, type, upCallbacks, whenModified;
if (extra == null) { if (extra == null) {
extra = {}; extra = {};
} }
@ -523,11 +523,11 @@
return; return;
} }
if (whenModified) { if (whenModified) {
if (url in lastModified) { if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) {
r.setRequestHeader('If-Modified-Since', lastModified[url]); r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]);
} }
$.on(r, 'load', function() { $.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)) { if (/\.json$/.test(url)) {
@ -3624,7 +3624,7 @@
return Index.load(e, state); return Index.load(e, state);
} }
}, { }, {
whenModified: true whenModified: 'Index'
}); });
return $.addClass(Index.button, 'fa-spin'); return $.addClass(Index.button, 'fa-spin');
}, },
@ -6220,7 +6220,7 @@
}, },
mouseover: function(e) { mouseover: function(e) {
var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; 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; return;
} }
ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID;
@ -7735,7 +7735,11 @@
38: 9, 38: 9,
40: 3, 40: 3,
37: 11, 37: 11,
39: 1 39: 1,
73: 9,
75: 3,
74: 11,
76: 1
}[e.keyCode])) { }[e.keyCode])) {
return; return;
} }
@ -11998,13 +12002,13 @@
return; return;
} }
statsHTML = { statsHTML = {
innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] ? " / <span id=\"page-count\">?</span>" : "") innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / <span id=\"page-count\">?</span>" : "")
}; };
statsTitle = 'Posts / Files'; statsTitle = 'Posts / Files';
if (Conf['IP Count in Stats']) { if (Conf['IP Count in Stats']) {
statsTitle += ' / IPs'; statsTitle += ' / IPs';
} }
if (Conf['Page Count in Stats']) { if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') {
statsTitle += ' / Page'; statsTitle += ' / Page';
} }
if (Conf['Updater and Stats in Header']) { if (Conf['Updater and Stats in Header']) {
@ -12029,6 +12033,9 @@
this.fileCountEl = $('#file-count', sc); this.fileCountEl = $('#file-count', sc);
this.ipCountEl = $('#ip-count', sc); this.ipCountEl = $('#ip-count', sc);
this.pageCountEl = $('#page-count', sc); this.pageCountEl = $('#page-count', sc);
if (this.pageCountEl) {
$.on(this.pageCountEl, 'click', ThreadStats.fetchPage);
}
return Thread.callbacks.push({ return Thread.callbacks.push({
name: 'Thread Stats', name: 'Thread Stats',
cb: this.node cb: this.node
@ -12043,7 +12050,7 @@
if (post.file) { if (post.file) {
fileCount++; fileCount++;
} }
if (Conf["Page Count in Stats"]) { if (ThreadStats.pageCountEl) {
return ThreadStats.lastPost = post.info.date; 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; ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts;
ThreadStats.update(postCount, fileCount, ipCount); ThreadStats.update(postCount, fileCount, ipCount);
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
if (newPosts.length) { if (newPosts.length) {
ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; 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(); return ThreadStats.fetchPage();
} }
}, },
@ -12074,14 +12081,14 @@
thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl;
postCountEl.textContent = postCount; postCountEl.textContent = postCount;
fileCountEl.textContent = fileCount; fileCountEl.textContent = fileCount;
if ((ipCount != null) && Conf["IP Count in Stats"]) { if ((ipCount != null) && ipCountEl) {
ipCountEl.textContent = ipCount; ipCountEl.textContent = ipCount;
} }
(thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning');
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
}, },
fetchPage: function() { fetchPage: function() {
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
clearTimeout(ThreadStats.timeout); clearTimeout(ThreadStats.timeout);
@ -12094,28 +12101,37 @@
return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", {
onload: ThreadStats.onThreadsLoad onload: ThreadStats.onThreadsLoad
}, { }, {
whenModified: true whenModified: 'ThreadStats'
}); });
}, },
onThreadsLoad: function() { onThreadsLoad: function() {
var k, len1, len2, page, q, ref, ref1, thread; var k, len1, len2, page, q, ref, ref1, thread;
if (!(Conf["Page Count in Stats"] && this.status === 200)) { if (this.status === 200) {
return; ref = this.response;
} for (k = 0, len1 = ref.length; k < len1; k++) {
ref = this.response; page = ref[k];
for (k = 0, len1 = ref.length; k < len1; k++) { ref1 = page.threads;
page = ref[k]; for (q = 0, len2 = ref1.length; q < len2; q++) {
ref1 = page.threads; thread = ref1[q];
for (q = 0, len2 = ref1.length; q < len2; q++) { if (!(thread.no === ThreadStats.thread.ID)) {
thread = ref1[q]; continue;
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, onloadend: ThreadUpdater.cb.load,
timeout: $.MINUTE timeout: $.MINUTE
}, { }, {
whenModified: true whenModified: 'ThreadUpdater'
}); });
}, },
updateThreadStatus: function(type, status) { updateThreadStatus: function(type, status) {
@ -12568,7 +12584,7 @@
this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
$.on(d, 'QRPostSuccessful', this.cb.post); $.on(d, 'QRPostSuccessful', this.cb.post);
$.on(sc, 'click', this.toggleWatcher); $.on(sc, 'click', this.toggleWatcher);
$.on(this.refreshButton, 'click', this.fetchAllStatus); $.on(this.refreshButton, 'click', this.buttonFetchAll);
$.on(this.closeButton, 'click', this.toggleWatcher); $.on(this.closeButton, 'click', this.toggleWatcher);
$.on(d, '4chanXInitFinished', this.ready); $.on(d, '4chanXInitFinished', this.ready);
switch (g.VIEW) { switch (g.VIEW) {
@ -12648,7 +12664,7 @@
if (ThreadWatcher.isWatched(this.thread)) { if (ThreadWatcher.isWatched(this.thread)) {
$.addClass(this.nodes.root, 'watched'); $.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) { return function(e) {
if (!(e.button === 0 && e.altKey)) { if (!(e.button === 0 && e.altKey)) {
return; return;
@ -12657,6 +12673,11 @@
return e.preventDefault(); return e.preventDefault();
}; };
})(this)); })(this));
return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) {
if (e.button === 0 && e.altKey) {
return e.preventDefault();
}
});
}, },
ready: function() { ready: function() {
$.off(d, '4chanXInitFinished', ThreadWatcher.ready); $.off(d, '4chanXInitFinished', ThreadWatcher.ready);
@ -12749,13 +12770,20 @@
data = ref[threadID]; data = ref[threadID];
if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) {
if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) {
ThreadWatcher.db["delete"]({ db["delete"]({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else { } else {
if (Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({
boardID: boardID,
threadID: threadID,
data: data
});
}
data.isDead = true; data.isDead = true;
ThreadWatcher.db.set({ db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
val: data val: data
@ -12777,9 +12805,24 @@
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
fetchCount: { requests: [],
fetched: 0, fetched: 0,
fetching: 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() { fetchAuto: function() {
var db, interval, now; var db, interval, now;
@ -12797,6 +12840,13 @@
} }
return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval);
}, },
buttonFetchAll: function() {
if (ThreadWatcher.requests.length) {
return ThreadWatcher.abort();
} else {
return ThreadWatcher.fetchAllStatus();
}
},
fetchAllStatus: function() { fetchAllStatus: function() {
var k, len1, ref, thread, threads; var k, len1, ref, thread, threads;
ThreadWatcher.db.forceSync(); ThreadWatcher.db.forceSync();
@ -12813,37 +12863,34 @@
} }
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, fetchCount, threadID; var boardID, data, req, threadID;
boardID = thread.boardID, threadID = thread.threadID, data = thread.data; boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
fetchCount = ThreadWatcher.fetchCount; if (ThreadWatcher.requests.length === 0) {
if (fetchCount.fetching === 0) {
ThreadWatcher.status.textContent = '...'; ThreadWatcher.status.textContent = '...';
$.addClass(ThreadWatcher.refreshButton, 'fa-spin'); $.addClass(ThreadWatcher.refreshButton, 'fa-spin');
} }
fetchCount.fetching++; req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
onloadend: function() { onloadend: function() {
return ThreadWatcher.parseStatus.call(this, thread); return ThreadWatcher.parseStatus.call(this, thread);
} },
timeout: $.MINUTE
}, {
whenModified: force ? false : 'ThreadWatcher'
}); });
return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { 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; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
fetchCount = ThreadWatcher.fetchCount; ThreadWatcher.fetched++;
fetchCount.fetched++; if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
if (fetchCount.fetched === fetchCount.fetching) { ThreadWatcher.clearRequests();
fetchCount.fetched = 0;
fetchCount.fetching = 0;
status = '';
$.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
} else { } 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) { if (this.status === 200 && this.response) {
isDead = !!this.response.posts[0].archived; isDead = !!this.response.posts[0].archived;
if (isDead && Conf['Auto Prune']) { if (isDead && Conf['Auto Prune']) {
@ -12912,6 +12959,8 @@
}); });
} else { } else {
data.isDead = true; data.isDead = true;
delete data.unread;
delete data.quotingYou;
ThreadWatcher.db.set({ ThreadWatcher.db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -14584,21 +14633,25 @@
}); });
}, },
code: function() { code: function() {
var i, k, len1, pre, ref;
if (this.isClone) { if (this.isClone) {
return; return;
} }
ref = $$('.prettyprint', this.nodes.comment); return $.ready((function(_this) {
for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { return function() {
pre = ref[i]; var i, k, len1, pre, ref;
if (!$.hasClass(pre, 'prettyprinted')) { ref = $$('.prettyprint', _this.nodes.comment);
$.event('prettyprint', { for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
ID: this.fullID, pre = ref[i];
i: i, if (!$.hasClass(pre, 'prettyprinted')) {
html: pre.innerHTML $.event('prettyprint', {
}, window); ID: _this.fullID,
} i: i,
} html: pre.innerHTML
}, window);
}
}
};
})(this));
}, },
math: function() { math: function() {
if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) {
@ -18117,6 +18170,9 @@
":root.float #thread-stats {\n" + ":root.float #thread-stats {\n" +
" padding: 0px 3px;\n" + " padding: 0px 3px;\n" +
"}\n" + "}\n" +
"#page-count {\n" +
" cursor: pointer;\n" +
"}\n" +
"/* Quote */\n" + "/* Quote */\n" +
".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" +
" color: #789922;\n" + " color: #789922;\n" +

Binary file not shown.

View File

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

View File

@ -1,7 +1,7 @@
// Generated by CoffeeScript // Generated by CoffeeScript
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.10.12.8 // @version 1.10.13.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -346,7 +346,7 @@
'Expand images': ['e', 'Expand all images.'], 'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'], 'Open Gallery': ['g', 'Opens the gallery.'],
'Pause': ['p', 'Pause/play videos in 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.'], 'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'], 'Front page': ['1', 'Jump to front page.'],
@ -396,7 +396,7 @@
doc = d.documentElement; doc = d.documentElement;
g = { g = {
VERSION: '1.10.12.8', VERSION: '1.10.13.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -506,7 +506,7 @@
}); });
}; };
return function(url, options, extra) { return function(url, options, extra) {
var err, form, r, type, upCallbacks, whenModified; var err, form, r, ref, type, upCallbacks, whenModified;
if (extra == null) { if (extra == null) {
extra = {}; extra = {};
} }
@ -524,11 +524,11 @@
return; return;
} }
if (whenModified) { if (whenModified) {
if (url in lastModified) { if (((ref = lastModified[whenModified]) != null ? ref[url] : void 0) != null) {
r.setRequestHeader('If-Modified-Since', lastModified[url]); r.setRequestHeader('If-Modified-Since', lastModified[whenModified][url]);
} }
$.on(r, 'load', function() { $.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)) { if (/\.json$/.test(url)) {
@ -3625,7 +3625,7 @@
return Index.load(e, state); return Index.load(e, state);
} }
}, { }, {
whenModified: true whenModified: 'Index'
}); });
return $.addClass(Index.button, 'fa-spin'); return $.addClass(Index.button, 'fa-spin');
}, },
@ -6221,7 +6221,7 @@
}, },
mouseover: function(e) { mouseover: function(e) {
var boardID, clone, k, len1, len2, origin, post, postID, posts, q, qp, quote, quoterID, ref, ref1, threadID; 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; return;
} }
ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID;
@ -7736,7 +7736,11 @@
38: 9, 38: 9,
40: 3, 40: 3,
37: 11, 37: 11,
39: 1 39: 1,
73: 9,
75: 3,
74: 11,
76: 1
}[e.keyCode])) { }[e.keyCode])) {
return; return;
} }
@ -11999,13 +12003,13 @@
return; return;
} }
statsHTML = { statsHTML = {
innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] ? " / <span id=\"page-count\">?</span>" : "") innerHTML: "<span id=\"post-count\">?</span> / <span id=\"file-count\">?</span>" + (Conf["IP Count in Stats"] ? " / <span id=\"ip-count\">?</span>" : "") + (Conf["Page Count in Stats"] && g.BOARD.ID !== "f" ? " / <span id=\"page-count\">?</span>" : "")
}; };
statsTitle = 'Posts / Files'; statsTitle = 'Posts / Files';
if (Conf['IP Count in Stats']) { if (Conf['IP Count in Stats']) {
statsTitle += ' / IPs'; statsTitle += ' / IPs';
} }
if (Conf['Page Count in Stats']) { if (Conf['Page Count in Stats'] && g.BOARD.ID !== 'f') {
statsTitle += ' / Page'; statsTitle += ' / Page';
} }
if (Conf['Updater and Stats in Header']) { if (Conf['Updater and Stats in Header']) {
@ -12030,6 +12034,9 @@
this.fileCountEl = $('#file-count', sc); this.fileCountEl = $('#file-count', sc);
this.ipCountEl = $('#ip-count', sc); this.ipCountEl = $('#ip-count', sc);
this.pageCountEl = $('#page-count', sc); this.pageCountEl = $('#page-count', sc);
if (this.pageCountEl) {
$.on(this.pageCountEl, 'click', ThreadStats.fetchPage);
}
return Thread.callbacks.push({ return Thread.callbacks.push({
name: 'Thread Stats', name: 'Thread Stats',
cb: this.node cb: this.node
@ -12044,7 +12051,7 @@
if (post.file) { if (post.file) {
fileCount++; fileCount++;
} }
if (Conf["Page Count in Stats"]) { if (ThreadStats.pageCountEl) {
return ThreadStats.lastPost = post.info.date; 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; ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount, ipCount = ref.ipCount, newPosts = ref.newPosts;
ThreadStats.update(postCount, fileCount, ipCount); ThreadStats.update(postCount, fileCount, ipCount);
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
if (newPosts.length) { if (newPosts.length) {
ThreadStats.lastPost = g.posts[newPosts[newPosts.length - 1]].info.date; 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(); return ThreadStats.fetchPage();
} }
}, },
@ -12075,14 +12082,14 @@
thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl;
postCountEl.textContent = postCount; postCountEl.textContent = postCount;
fileCountEl.textContent = fileCount; fileCountEl.textContent = fileCount;
if ((ipCount != null) && Conf["IP Count in Stats"]) { if ((ipCount != null) && ipCountEl) {
ipCountEl.textContent = ipCount; ipCountEl.textContent = ipCount;
} }
(thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning'); (thread.postLimit && !thread.isSticky ? $.addClass : $.rmClass)(postCountEl, 'warning');
return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning'); return (thread.fileLimit && !thread.isSticky ? $.addClass : $.rmClass)(fileCountEl, 'warning');
}, },
fetchPage: function() { fetchPage: function() {
if (!Conf["Page Count in Stats"]) { if (!ThreadStats.pageCountEl) {
return; return;
} }
clearTimeout(ThreadStats.timeout); clearTimeout(ThreadStats.timeout);
@ -12095,28 +12102,37 @@
return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", { return $.ajax("//a.4cdn.org/" + ThreadStats.thread.board + "/threads.json", {
onload: ThreadStats.onThreadsLoad onload: ThreadStats.onThreadsLoad
}, { }, {
whenModified: true whenModified: 'ThreadStats'
}); });
}, },
onThreadsLoad: function() { onThreadsLoad: function() {
var k, len1, len2, page, q, ref, ref1, thread; var k, len1, len2, page, q, ref, ref1, thread;
if (!(Conf["Page Count in Stats"] && this.status === 200)) { if (this.status === 200) {
return; ref = this.response;
} for (k = 0, len1 = ref.length; k < len1; k++) {
ref = this.response; page = ref[k];
for (k = 0, len1 = ref.length; k < len1; k++) { ref1 = page.threads;
page = ref[k]; for (q = 0, len2 = ref1.length; q < len2; q++) {
ref1 = page.threads; thread = ref1[q];
for (q = 0, len2 = ref1.length; q < len2; q++) { if (!(thread.no === ThreadStats.thread.ID)) {
thread = ref1[q]; continue;
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, onloadend: ThreadUpdater.cb.load,
timeout: $.MINUTE timeout: $.MINUTE
}, { }, {
whenModified: true whenModified: 'ThreadUpdater'
}); });
}, },
updateThreadStatus: function(type, status) { updateThreadStatus: function(type, status) {
@ -12569,7 +12585,7 @@
this.unreaddb = Unread.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || new DataBoard('lastReadPosts');
$.on(d, 'QRPostSuccessful', this.cb.post); $.on(d, 'QRPostSuccessful', this.cb.post);
$.on(sc, 'click', this.toggleWatcher); $.on(sc, 'click', this.toggleWatcher);
$.on(this.refreshButton, 'click', this.fetchAllStatus); $.on(this.refreshButton, 'click', this.buttonFetchAll);
$.on(this.closeButton, 'click', this.toggleWatcher); $.on(this.closeButton, 'click', this.toggleWatcher);
$.on(d, '4chanXInitFinished', this.ready); $.on(d, '4chanXInitFinished', this.ready);
switch (g.VIEW) { switch (g.VIEW) {
@ -12649,7 +12665,7 @@
if (ThreadWatcher.isWatched(this.thread)) { if (ThreadWatcher.isWatched(this.thread)) {
$.addClass(this.nodes.root, 'watched'); $.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) { return function(e) {
if (!(e.button === 0 && e.altKey)) { if (!(e.button === 0 && e.altKey)) {
return; return;
@ -12658,6 +12674,11 @@
return e.preventDefault(); return e.preventDefault();
}; };
})(this)); })(this));
return $.on(this.nodes.thumb.parentNode, 'mousedown', function(e) {
if (e.button === 0 && e.altKey) {
return e.preventDefault();
}
});
}, },
ready: function() { ready: function() {
$.off(d, '4chanXInitFinished', ThreadWatcher.ready); $.off(d, '4chanXInitFinished', ThreadWatcher.ready);
@ -12750,13 +12771,20 @@
data = ref[threadID]; data = ref[threadID];
if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) { if (!(data != null ? data.isDead : void 0) && !(threadID in g.BOARD.threads)) {
if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { if (Conf['Auto Prune'] || !(data && typeof data === 'object')) {
ThreadWatcher.db["delete"]({ db["delete"]({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else { } else {
if (Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({
boardID: boardID,
threadID: threadID,
data: data
});
}
data.isDead = true; data.isDead = true;
ThreadWatcher.db.set({ db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
val: data val: data
@ -12778,9 +12806,24 @@
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
fetchCount: { requests: [],
fetched: 0, fetched: 0,
fetching: 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() { fetchAuto: function() {
var db, interval, now; var db, interval, now;
@ -12798,6 +12841,13 @@
} }
return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval);
}, },
buttonFetchAll: function() {
if (ThreadWatcher.requests.length) {
return ThreadWatcher.abort();
} else {
return ThreadWatcher.fetchAllStatus();
}
},
fetchAllStatus: function() { fetchAllStatus: function() {
var k, len1, ref, thread, threads; var k, len1, ref, thread, threads;
ThreadWatcher.db.forceSync(); ThreadWatcher.db.forceSync();
@ -12814,37 +12864,34 @@
} }
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, fetchCount, threadID; var boardID, data, req, threadID;
boardID = thread.boardID, threadID = thread.threadID, data = thread.data; boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
fetchCount = ThreadWatcher.fetchCount; if (ThreadWatcher.requests.length === 0) {
if (fetchCount.fetching === 0) {
ThreadWatcher.status.textContent = '...'; ThreadWatcher.status.textContent = '...';
$.addClass(ThreadWatcher.refreshButton, 'fa-spin'); $.addClass(ThreadWatcher.refreshButton, 'fa-spin');
} }
fetchCount.fetching++; req = $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
return $.ajax("//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json", {
onloadend: function() { onloadend: function() {
return ThreadWatcher.parseStatus.call(this, thread); return ThreadWatcher.parseStatus.call(this, thread);
} },
timeout: $.MINUTE
}, {
whenModified: force ? false : 'ThreadWatcher'
}); });
return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { 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; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
fetchCount = ThreadWatcher.fetchCount; ThreadWatcher.fetched++;
fetchCount.fetched++; if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
if (fetchCount.fetched === fetchCount.fetching) { ThreadWatcher.clearRequests();
fetchCount.fetched = 0;
fetchCount.fetching = 0;
status = '';
$.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
} else { } 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) { if (this.status === 200 && this.response) {
isDead = !!this.response.posts[0].archived; isDead = !!this.response.posts[0].archived;
if (isDead && Conf['Auto Prune']) { if (isDead && Conf['Auto Prune']) {
@ -12913,6 +12960,8 @@
}); });
} else { } else {
data.isDead = true; data.isDead = true;
delete data.unread;
delete data.quotingYou;
ThreadWatcher.db.set({ ThreadWatcher.db.set({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -14585,21 +14634,25 @@
}); });
}, },
code: function() { code: function() {
var i, k, len1, pre, ref;
if (this.isClone) { if (this.isClone) {
return; return;
} }
ref = $$('.prettyprint', this.nodes.comment); return $.ready((function(_this) {
for (i = k = 0, len1 = ref.length; k < len1; i = ++k) { return function() {
pre = ref[i]; var i, k, len1, pre, ref;
if (!$.hasClass(pre, 'prettyprinted')) { ref = $$('.prettyprint', _this.nodes.comment);
$.event('prettyprint', { for (i = k = 0, len1 = ref.length; k < len1; i = ++k) {
ID: this.fullID, pre = ref[i];
i: i, if (!$.hasClass(pre, 'prettyprinted')) {
html: pre.innerHTML $.event('prettyprint', {
}, window); ID: _this.fullID,
} i: i,
} html: pre.innerHTML
}, window);
}
}
};
})(this));
}, },
math: function() { math: function() {
if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) { if ((this.isClone && doc.contains(this.origin.nodes.root)) || !$('.math', this.nodes.comment)) {
@ -18118,6 +18171,9 @@
":root.float #thread-stats {\n" + ":root.float #thread-stats {\n" +
" padding: 0px 3px;\n" + " padding: 0px 3px;\n" +
"}\n" + "}\n" +
"#page-count {\n" +
" cursor: pointer;\n" +
"}\n" +
"/* Quote */\n" + "/* Quote */\n" +
".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" + ".catalog-thread > .comment > span.quote, #arc-list span.quote {\n" +
" color: #789922;\n" + " color: #789922;\n" +

Binary file not shown.

View File

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

View File

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

View File

@ -3,8 +3,8 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.", "description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": { "meta": {
"name": "4chan X", "name": "4chan X",
"version": "1.10.12.8", "version": "1.10.13.0",
"date": "2015-05-22T20:36:38.853Z", "date": "2015-05-27T03:12:34.213Z",
"repo": "https://github.com/ccd0/4chan-x/", "repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x", "page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/", "downloads": "https://ccd0.github.io/4chan-x/builds/",