Release 4chan X v1.14.5.0.

This commit is contained in:
ccd0 2018-12-05 20:28:53 -08:00
parent 7b5759cc09
commit c9906c488e
15 changed files with 894 additions and 512 deletions

View File

@ -2,6 +2,13 @@
-Sometimes the changelog has notes (not comprehensive) acknowledging people's work. This does not mean the changes are their fault, only that their code was used. All changes to the script are chosen by and the fault of the maintainer (ccd0). -Sometimes the changelog has notes (not comprehensive) acknowledging people's work. This does not mean the changes are their fault, only that their code was used. All changes to the script are chosen by and the fault of the maintainer (ccd0).
### v1.14.5
**v1.14.5.0** *(2018-12-06)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.5.0/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.5.0/builds/4chan-X-noupdate.crx)]
- Based on v1.14.4.7.
- Show threads from other sites in Thread Watcher. When threads from multiple sites are shown, a prefix is added before the board name to distinguish sites. The prefix can be disabled by unchecking `Show Site Prefix` preference in thread watcher menu. More work remains; refreshing is still only working on 4chan, and the unread count still only works for 4chan threads.
- Fix bug affecting boards with names containing characters escaped in URLs.
### v1.14.4 ### v1.14.4
**v1.14.4.7** *(2018-12-04)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.4.7/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.4.7/builds/4chan-X-noupdate.crx)] **v1.14.4.7** *(2018-12-04)* - [[Userscript](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.4.7/builds/4chan-X-noupdate.user.js)] [[Chrome extension](https://raw.githubusercontent.com/ccd0/4chan-x/1.14.4.7/builds/4chan-X-noupdate.crx)]

Binary file not shown.

View File

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

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan X beta // @name 4chan X beta
// @version 1.14.4.7 // @version 1.14.5.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -198,7 +198,7 @@ docSet = function() {
}; };
g = { g = {
VERSION: '1.14.4.7', VERSION: '1.14.5.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -411,6 +411,7 @@ Config = (function() {
'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'], 'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'],
'Auto Prune': [false, 'Automatically remove dead threads.'], 'Auto Prune': [false, 'Automatically remove dead threads.'],
'Show Unread Count': [true, 'Show number of unread posts in watched threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'],
'Show Site Prefix': [true, 'When multiple sites are shown in the thread watcher, add a prefix to board names to distinguish them.'],
'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.'] 'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.']
}, },
filter: { filter: {
@ -553,8 +554,7 @@ Config = (function() {
'updater.position': 'bottom: 0px; left: 0px;', 'updater.position': 'bottom: 0px; left: 0px;',
'thread-watcher.position': 'top: 50px; left: 0px;', 'thread-watcher.position': 'top: 50px; left: 0px;',
'qr.position': 'top: 50px; right: 0px;' 'qr.position': 'top: 50px; right: 0px;'
}, }
siteSoftware: "4chan.org yotsuba\n4channel.org yotsuba\n4cdn.org yotsuba"
}; };
return Config; return Config;
@ -5753,16 +5753,21 @@ DataBoard = (function() {
$.on(d, '4chanXInitFinished', init); $.on(d, '4chanXInitFinished', init);
} }
DataBoard.prototype.initData = function(allData) { DataBoard.prototype.initData = function(data1) {
var base, name; var base, boards, lastChecked, name, ref;
this.allData = allData; this.data = data1;
if (Site.hostname === '4chan.org' && this.allData.boards) { if (this.data.boards) {
return this.data = this.allData; ref = this.data, boards = ref.boards, lastChecked = ref.lastChecked;
} else { this.data['4chan.org'] = {
return this.data = ((base = this.allData)[name = Site.hostname] || (base[name] = { boards: boards,
boards: {} lastChecked: lastChecked
})); };
delete this.data.boards;
delete this.data.lastChecked;
} }
return (base = this.data)[name = Site.hostname] || (base[name] = {
boards: {}
});
}; };
DataBoard.prototype.changes = []; DataBoard.prototype.changes = [];
@ -5778,7 +5783,7 @@ DataBoard = (function() {
if (!_this.changes.length) { if (!_this.changes.length) {
return; return;
} }
needSync = (items[_this.key].version || 0) > (_this.allData.version || 0); needSync = (items[_this.key].version || 0) > (_this.data.version || 0);
if (needSync) { if (needSync) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
@ -5788,8 +5793,8 @@ DataBoard = (function() {
} }
} }
_this.changes = []; _this.changes = [];
_this.allData.version = (_this.allData.version || 0) + 1; _this.data.version = (_this.data.version || 0) + 1;
return $.set(_this.key, _this.allData, function() { return $.set(_this.key, _this.data, function() {
if (needSync) { if (needSync) {
if (typeof _this.sync === "function") { if (typeof _this.sync === "function") {
_this.sync(); _this.sync();
@ -5807,7 +5812,7 @@ DataBoard = (function() {
}, (function(_this) { }, (function(_this) {
return function(items) { return function(items) {
var change, i, len, ref; var change, i, len, ref;
if ((items[_this.key].version || 0) > (_this.allData.version || 0)) { if ((items[_this.key].version || 0) > (_this.data.version || 0)) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
@ -5824,47 +5829,51 @@ DataBoard = (function() {
}; };
DataBoard.prototype["delete"] = function(arg) { DataBoard.prototype["delete"] = function(arg) {
var boardID, postID, threadID; var boardID, postID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID;
siteID || (siteID = Site.hostname);
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var ref; var ref;
if (postID) { if (postID) {
if (!((ref = _this.data.boards[boardID]) != null ? ref[threadID] : void 0)) { if (!((ref = _this.data[siteID].boards[boardID]) != null ? ref[threadID] : void 0)) {
return; return;
} }
delete _this.data.boards[boardID][threadID][postID]; delete _this.data[siteID].boards[boardID][threadID][postID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else if (threadID) { } else if (threadID) {
if (!_this.data.boards[boardID]) { if (!_this.data[siteID].boards[boardID]) {
return; return;
} }
delete _this.data.boards[boardID][threadID]; delete _this.data[siteID].boards[boardID][threadID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} else { } else {
return delete _this.data.boards[boardID]; return delete _this.data[siteID].boards[boardID];
} }
}; };
})(this)); })(this));
}; };
DataBoard.prototype.deleteIfEmpty = function(arg) { DataBoard.prototype.deleteIfEmpty = function(arg) {
var boardID, threadID; var boardID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
if (threadID) { if (threadID) {
if (!Object.keys(this.data.boards[boardID][threadID]).length) { if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
delete this.data.boards[boardID][threadID]; delete this.data[siteID].boards[boardID][threadID];
return this.deleteIfEmpty({ return this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
} else if (!Object.keys(this.data.boards[boardID]).length) { } else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
return delete this.data.boards[boardID]; return delete this.data[siteID].boards[boardID];
} }
}; };
@ -5877,24 +5886,26 @@ DataBoard = (function() {
}; };
DataBoard.prototype.setUnsafe = function(arg) { DataBoard.prototype.setUnsafe = function(arg) {
var base, base1, base2, boardID, postID, threadID, val; var base, base1, base2, boardID, postID, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val;
siteID || (siteID = Site.hostname);
if (postID !== void 0) { if (postID !== void 0) {
return ((base = ((base1 = this.data.boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val; return ((base = ((base1 = this.data[siteID].boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val;
} else if (threadID !== void 0) { } else if (threadID !== void 0) {
return ((base2 = this.data.boards)[boardID] || (base2[boardID] = {}))[threadID] = val; return ((base2 = this.data[siteID].boards)[boardID] || (base2[boardID] = {}))[threadID] = val;
} else { } else {
return this.data.boards[boardID] = val; return this.data[siteID].boards[boardID] = val;
} }
}; };
DataBoard.prototype.extend = function(arg, cb) { DataBoard.prototype.extend = function(arg, cb) {
var boardID, postID, rm, threadID, val; var boardID, postID, rm, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm;
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var i, key, len, oldVal, ref; var i, key, len, oldVal, ref;
oldVal = _this.get({ oldVal = _this.get({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5907,6 +5918,7 @@ DataBoard = (function() {
} }
$.extend(oldVal, val); $.extend(oldVal, val);
return _this.setUnsafe({ return _this.setUnsafe({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5916,18 +5928,22 @@ DataBoard = (function() {
})(this), cb); })(this), cb);
}; };
DataBoard.prototype.setLastChecked = function() { DataBoard.prototype.setLastChecked = function(siteID) {
if (siteID == null) {
siteID = Site.hostname;
}
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
return _this.data.lastChecked = Date.now(); return _this.data[siteID].lastChecked = Date.now();
}; };
})(this)); })(this));
}; };
DataBoard.prototype.get = function(arg) { DataBoard.prototype.get = function(arg) {
var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; var ID, board, boardID, defaultValue, i, len, postID, siteID, thread, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue;
if (board = this.data.boards[boardID]) { siteID || (siteID = Site.hostname);
if (board = this.data[siteID].boards[boardID]) {
if (threadID == null) { if (threadID == null) {
if (postID != null) { if (postID != null) {
for (thread = i = 0, len = board.length; i < len; thread = ++i) { for (thread = i = 0, len = board.length; i < len; thread = ++i) {
@ -5948,21 +5964,23 @@ DataBoard = (function() {
}; };
DataBoard.prototype.clean = function() { DataBoard.prototype.clean = function() {
var boardID, now, ref, ref1, val; var boardID, now, ref, ref1, siteID, val;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
ref = this.data.boards; siteID = Site.hostname;
ref = this.data[siteID].boards;
for (boardID in ref) { for (boardID in ref) {
val = ref[boardID]; val = ref[boardID];
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
now = Date.now(); now = Date.now();
if (!((now - 2 * $.HOUR < (ref1 = this.data.lastChecked || 0) && ref1 <= now))) { if (!((now - 2 * $.HOUR < (ref1 = this.data[siteID].lastChecked || 0) && ref1 <= now))) {
this.data.lastChecked = now; this.data[siteID].lastChecked = now;
for (boardID in this.data.boards) { for (boardID in this.data[siteID].boards) {
this.ajaxClean(boardID); this.ajaxClean(boardID);
} }
} }
@ -5987,8 +6005,9 @@ DataBoard = (function() {
}; };
DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) {
var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; var ID, board, i, j, k, len, len1, len2, page, ref, siteID, thread, threads;
if (!(board = this.data.boards[boardID])) { siteID = Site.hostname;
if (!(board = this.data[siteID].boards[boardID])) {
return; return;
} }
threads = {}; threads = {};
@ -6013,15 +6032,16 @@ DataBoard = (function() {
} }
} }
} }
this.data.boards[boardID] = threads; this.data[siteID].boards[boardID] = threads;
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
return $.set(this.key, this.allData); return $.set(this.key, this.data);
}; };
DataBoard.prototype.onSync = function(data) { DataBoard.prototype.onSync = function(data) {
if (!((data.version || 0) > (this.allData.version || 0))) { if (!((data.version || 0) > (this.data.version || 0))) {
return; return;
} }
this.initData(data); this.initData(data);
@ -7262,21 +7282,30 @@ SW = {};
isOPContainerThread: true, isOPContainerThread: true,
disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'], disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'],
detect: function() { detect: function() {
var i, len, ref, script; var i, len, m, properties, ref, root, script;
ref = $$('script:not([src])', d.head); ref = $$('script:not([src])', d.head);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
script = ref[i]; script = ref[i];
if (/\bvar configRoot=".*?"/.test(script.textContent)) { if ((m = script.textContent.match(/\bvar configRoot=(".*?")/))) {
return true; properties = {};
try {
root = JSON.parse(m[1]);
if (root[0] === '/') {
properties.root = location.origin + root;
} else if (/^https?:/.test(root)) {
properties.root = root;
}
} catch (_error) {}
return properties;
} }
} }
return false; return false;
}, },
urls: { urls: {
thread: function(arg) { thread: function(arg) {
var boardID, threadID; var boardID, ref, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
return location.origin + "/" + boardID + "/res/" + threadID + ".html"; return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/res/" + threadID + ".html";
} }
}, },
selectors: { selectors: {
@ -7566,49 +7595,65 @@ Site = (function() {
var Site; var Site;
Site = { Site = {
init: function(cb) { defaultProperties: {
var hostname, i, len, line, ref, ref1, software, swDict; '4chan.org': {
swDict = {}; software: 'yotsuba'
ref = Conf['siteSoftware'].split('\n'); },
for (i = 0, len = ref.length; i < len; i++) { '4channel.org': {
line = ref[i]; software: 'yotsuba'
if (!(line[0] !== '#')) { },
continue; '4cdn.org': {
} software: 'yotsuba'
ref1 = line.split(' '), hostname = ref1[0], software = ref1[1];
if (software in SW) {
swDict[hostname] = software;
}
}
hostname = location.hostname;
while (hostname && !(hostname in swDict)) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname === '4channel.org') {
hostname = '4chan.org';
}
if (hostname) {
this.set(hostname, swDict[hostname]);
return cb();
} else {
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base;
for (software in SW) {
if (typeof (base = SW[software]).detect === "function" ? base.detect() : void 0) {
_this.set(location.hostname.replace(/^www\./, ''), software);
Conf['siteSoftware'] += "\n" + _this.hostname + " " + _this.software;
$.set('siteSoftware', Conf['siteSoftware']);
cb();
}
}
};
})(this));
} }
}, },
set: function(hostname1, software1) { init: function(cb) {
var hostname;
$.extend(Conf['siteProperties'], Site.defaultProperties);
hostname = location.hostname;
while (hostname && !(hostname in Conf['siteProperties'])) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname && Conf['siteProperties'][hostname].software in SW) {
this.set(hostname);
cb();
}
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base, base1, changed, changes, key, properties, software;
for (software in SW) {
if (!((changes = typeof (base = SW[software]).detect === "function" ? base.detect() : void 0))) {
continue;
}
changes.software = software;
hostname = location.hostname.replace(/^www\./, '');
properties = ((base1 = Conf['siteProperties'])[hostname] || (base1[hostname] = {}));
changed = 0;
for (key in changes) {
if (!(properties[key] !== changes[key])) {
continue;
}
properties[key] = changes[key];
changed++;
}
if (changed) {
$.set('siteProperties', Conf['siteProperties']);
}
if (!_this.hostname) {
_this.set(hostname);
cb();
}
return;
}
};
})(this));
},
set: function(hostname1) {
this.hostname = hostname1; this.hostname = hostname1;
this.software = software1; this.properties = Conf['siteProperties'][this.hostname];
this.software = this.properties.software;
if (this.software === 'yotsuba') {
this.hostname = '4chan.org';
}
return $.extend(this, SW[this.software]); return $.extend(this, SW[this.software]);
} }
}; };
@ -9368,7 +9413,7 @@ Get = (function() {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, ref, ref1; var OP, excerpt, ref, ref1;
OP = thread.OP; OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP)); excerpt = ("/" + (decodeURIComponent(thread.board.ID)) + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP));
if (excerpt.length > 73) { if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "..."; return excerpt.slice(0, 70) + "...";
} }
@ -11950,7 +11995,7 @@ Settings = (function() {
} }
}, },
upgrade: function(data, version) { upgrade: function(data, version) {
var addCSS, addSauces, boardID, changes, compareString, corrupted, j, k, key, len, len1, list, name, record, ref, ref1, ref2, ref3, ref4, ref5, ref6, rice, set, setD, type, uids, val, val2, value; var addCSS, addSauces, boardID, boards, changes, compareString, corrupted, db, hostname, j, k, key, l, lastChecked, len, len1, len2, len3, line, list, m, name, record, ref, ref1, ref10, ref11, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rice, set, setD, siteProperties, software, type, uids, val, val2, value;
changes = {}; changes = {};
set = function(key, value) { set = function(key, value) {
return data[key] = changes[key] = value; return data[key] = changes[key] = value;
@ -12198,6 +12243,34 @@ Settings = (function() {
set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba'); set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba');
} }
} }
if (compareString < '00001.00014.00005.00000') {
ref7 = DataBoard.keys;
for (l = 0, len2 = ref7.length; l < len2; l++) {
db = ref7[l];
if ((ref8 = data[db]) != null ? ref8.boards : void 0) {
ref9 = data[db], boards = ref9.boards, lastChecked = ref9.lastChecked;
data[db]['4chan.org'] = {
boards: boards,
lastChecked: lastChecked
};
delete data[db].boards;
delete data[db].lastChecked;
set(db, data[db]);
}
}
if ((data['siteSoftware'] != null) && (data['siteProperties'] == null)) {
siteProperties = {};
ref10 = data['siteSoftware'].split('\n');
for (m = 0, len3 = ref10.length; m < len3; m++) {
line = ref10[m];
ref11 = line.split(' '), hostname = ref11[0], software = ref11[1];
siteProperties[hostname] = {
software: software
};
}
set('siteProperties', siteProperties);
}
}
return changes; return changes;
}, },
loadSettings: function(data, cb) { loadSettings: function(data, cb) {
@ -19684,7 +19757,7 @@ ThreadWatcher = (function() {
this.refreshButton = $('.refresh', this.dialog); this.refreshButton = $('.refresh', this.dialog);
this.closeButton = $('.move > .close', this.dialog); this.closeButton = $('.move > .close', this.dialog);
this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts');
this.unreadEnabled = Conf['Remember Last Read Post'] && Site.software === 'yotsuba'; this.unreadEnabled = Conf['Remember Last Read Post'];
$.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.buttonFetchAll); $.on(this.refreshButton, 'click', this.buttonFetchAll);
@ -19837,27 +19910,28 @@ ThreadWatcher = (function() {
}, },
cb: { cb: {
openAll: function() { openAll: function() {
var a, i, len, ref; var a, i, len1, ref;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = $$('a[title]', ThreadWatcher.list); ref = $$('a[title]', ThreadWatcher.list);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
a = ref[i]; a = ref[i];
$.open(a.href); $.open(a.href);
} }
return $.event('CloseMenu'); return $.event('CloseMenu');
}, },
pruneDeads: function() { pruneDeads: function() {
var boardID, data, i, len, ref, ref1, threadID; var boardID, data, i, len1, ref, ref1, siteID, threadID;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = ThreadWatcher.getAll(); ref = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; ref1 = ref[i], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data;
if (data.isDead) { if (data.isDead) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -19872,9 +19946,10 @@ ThreadWatcher = (function() {
return ThreadWatcher.toggle(thread); return ThreadWatcher.toggle(thread);
}, },
rm: function() { rm: function() {
var boardID, ref, threadID; var boardID, ref, siteID, threadID;
siteID = this.parentNode.dataset.siteID;
ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1];
return ThreadWatcher.rm(boardID, +threadID); return ThreadWatcher.rm(siteID, boardID, +threadID);
}, },
post: function(e) { post: function(e) {
var boardID, postID, ref, threadID; var boardID, postID, ref, threadID;
@ -19888,11 +19963,12 @@ ThreadWatcher = (function() {
} }
}, },
onIndexUpdate: function(e) { onIndexUpdate: function(e) {
var boardID, data, db, nKilled, ref, ref1, threadID; var boardID, data, db, nKilled, ref, ref1, siteID, threadID;
db = ThreadWatcher.db; db = ThreadWatcher.db;
siteID = Site.hostname;
boardID = g.BOARD.ID; boardID = g.BOARD.ID;
nKilled = 0; nKilled = 0;
ref = db.data.boards[boardID]; ref = db.data[siteID].boards[boardID];
for (threadID in ref) { for (threadID in ref) {
data = ref[threadID]; data = ref[threadID];
if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) { if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) {
@ -19919,6 +19995,7 @@ ThreadWatcher = (function() {
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({ ThreadWatcher.fetchStatus({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
@ -19948,9 +20025,9 @@ ThreadWatcher = (function() {
return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
}, },
abort: function() { abort: function() {
var i, len, ref, req; var i, len1, ref, req;
ref = ThreadWatcher.requests; ref = ThreadWatcher.requests;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
req = ref[i]; req = ref[i];
if (req.readyState !== 4) { if (req.readyState !== 4) {
req.abort(); req.abort();
@ -19970,7 +20047,7 @@ ThreadWatcher = (function() {
db = ThreadWatcher.db; db = ThreadWatcher.db;
interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR; interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR;
now = Date.now(); now = Date.now();
if (!((now - interval < (ref = db.data.lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) { if (!((now - interval < (ref = db.data[Site.hostname].lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) {
ThreadWatcher.fetchAllStatus(); ThreadWatcher.fetchAllStatus();
db.setLastChecked(); db.setLastChecked();
} }
@ -19984,7 +20061,7 @@ ThreadWatcher = (function() {
} }
}, },
fetchAllStatus: function() { fetchAllStatus: function() {
var db, dbs, i, len, n, results; var db, dbs, i, len1, n, results;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
@ -19993,13 +20070,13 @@ ThreadWatcher = (function() {
}); });
n = 0; n = 0;
results = []; results = [];
for (i = 0, len = dbs.length; i < len; i++) { for (i = 0, len1 = dbs.length; i < len1; i++) {
db = dbs[i]; db = dbs[i];
results.push(db.forceSync(function() { results.push(db.forceSync(function() {
var j, len1, thread, threads; var j, len2, thread, threads;
if ((++n) === dbs.length) { if ((++n) === dbs.length) {
threads = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (j = 0, len1 = threads.length; j < len1; j++) { for (j = 0, len2 = threads.length; j < len2; j++) {
thread = threads[j]; thread = threads[j];
ThreadWatcher.fetchStatus(thread); ThreadWatcher.fetchStatus(thread);
} }
@ -20009,11 +20086,11 @@ ThreadWatcher = (function() {
return results; return results;
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, req, threadID; var boardID, data, req, siteID, threadID;
if (Site.software !== 'yotsuba') { siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (!(Site.software === 'yotsuba' && siteID === Site.hostname)) {
return; return;
} }
boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
@ -20032,7 +20109,7 @@ ThreadWatcher = (function() {
return ThreadWatcher.requests.push(req); return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { parseStatus: function(arg) {
var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP; var boardID, data, i, isDead, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP;
boardID = arg.boardID, threadID = arg.threadID, data = arg.data; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
ThreadWatcher.fetched++; ThreadWatcher.fetched++;
if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
@ -20063,7 +20140,7 @@ ThreadWatcher = (function() {
postID: threadID postID: threadID
}) : void 0); }) : void 0);
ref1 = this.response.posts; ref1 = this.response.posts;
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len1 = ref1.length; i < len1; i++) {
postObj = ref1[i]; postObj = ref1[i];
if (!(postObj.no > lastReadPost)) { if (!(postObj.no > lastReadPost)) {
continue; continue;
@ -20131,29 +20208,35 @@ ThreadWatcher = (function() {
} }
}, },
getAll: function() { getAll: function() {
var all, boardID, data, ref, threadID, threads; var all, boardID, boards, data, ref, ref1, siteID, threadID, threads;
all = []; all = [];
ref = ThreadWatcher.db.data.boards; ref = ThreadWatcher.db.data;
for (boardID in ref) { for (siteID in ref) {
threads = ref[boardID]; boards = ref[siteID];
if (Conf['Current Board'] && boardID !== g.BOARD.ID) { ref1 = boards.boards;
continue; for (boardID in ref1) {
} threads = ref1[boardID];
for (threadID in threads) { if (Conf['Current Board'] && (siteID !== Site.hostname || boardID !== g.BOARD.ID)) {
data = threads[threadID]; continue;
if (data && typeof data === 'object') { }
all.push({ for (threadID in threads) {
boardID: boardID, data = threads[threadID];
threadID: threadID, if (data && typeof data === 'object') {
data: data all.push({
}); siteID: siteID,
boardID: boardID,
threadID: threadID,
data: data
});
}
} }
} }
} }
return all; return all;
}, },
makeLine: function(boardID, threadID, data) { makeLine: function(siteID, boardID, threadID, data) {
var count, div, excerpt, fullID, link, title, x; var count, div, excerpt, fullID, link, ref, ref1, software, title, x;
software = (ref = Conf['siteProperties'][siteID]) != null ? ref.software : void 0;
x = $.el('a', { x = $.el('a', {
className: 'fa fa-times', className: 'fa fa-times',
href: 'javascript:;' href: 'javascript:;'
@ -20161,15 +20244,19 @@ ThreadWatcher = (function() {
$.on(x, 'click', ThreadWatcher.cb.rm); $.on(x, 'click', ThreadWatcher.cb.rm);
excerpt = data.excerpt; excerpt = data.excerpt;
excerpt || (excerpt = "/" + boardID + "/ - No." + threadID); excerpt || (excerpt = "/" + boardID + "/ - No." + threadID);
if (Conf['Show Site Prefix']) {
excerpt = ThreadWatcher.prefixes[siteID] + excerpt;
}
link = $.el('a', { link = $.el('a', {
href: Site.urls.thread({ href: ((ref1 = SW[software]) != null ? ref1.urls.thread({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}), }) : void 0) || '',
title: excerpt, title: excerpt,
className: 'watcher-link' className: 'watcher-link'
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && (data.unread != null)) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba' && (data.unread != null)) {
count = $.el('span', { count = $.el('span', {
textContent: "(" + data.unread + ")", textContent: "(" + data.unread + ")",
className: 'watcher-unread' className: 'watcher-unread'
@ -20184,13 +20271,14 @@ ThreadWatcher = (function() {
div = $.el('div'); div = $.el('div');
fullID = boardID + "." + threadID; fullID = boardID + "." + threadID;
div.dataset.fullID = fullID; div.dataset.fullID = fullID;
div.dataset.siteID = siteID;
if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) { if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) {
$.addClass(div, 'current'); $.addClass(div, 'current');
} }
if (data.isDead) { if (data.isDead) {
$.addClass(div, 'dead-thread'); $.addClass(div, 'dead-thread');
} }
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba') {
if (data.unread === 0) { if (data.unread === 0) {
$.addClass(div, 'replies-read'); $.addClass(div, 'replies-read');
} }
@ -20204,13 +20292,43 @@ ThreadWatcher = (function() {
$.add(div, [x, $.tn(' '), link]); $.add(div, [x, $.tn(' '), link]);
return div; return div;
}, },
setPrefixes: function(threads) {
var conflicts, conflicts2, i, j, len, len1, len2, prefix, prefixes, siteID, siteID2;
prefixes = {};
for (i = 0, len1 = threads.length; i < len1; i++) {
siteID = threads[i].siteID;
if (siteID in prefixes) {
continue;
}
len = 0;
prefix = '';
conflicts = Object.keys(prefixes);
while (conflicts.length > 0) {
len++;
prefix = siteID.slice(0, len);
conflicts2 = [];
for (j = 0, len2 = conflicts.length; j < len2; j++) {
siteID2 = conflicts[j];
if (siteID2.slice(0, len) === prefix) {
conflicts2.push(siteID2);
} else if (prefixes[siteID2].length < len) {
prefixes[siteID2] = siteID2.slice(0, len);
}
}
conflicts = conflicts2;
}
prefixes[siteID] = prefix;
}
return ThreadWatcher.prefixes = prefixes;
},
build: function() { build: function() {
var boardID, data, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, thread, threadID; var boardID, data, i, j, len1, len2, list, nodes, ref, ref1, refresher, siteID, thread, threadID, threads;
nodes = []; nodes = [];
ref = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { ThreadWatcher.setPrefixes(threads);
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; for (i = 0, len1 = threads.length; i < len1; i++) {
if ((data.excerpt == null) && (thread = g.threads[boardID + "." + threadID])) { ref = threads[i], siteID = ref.siteID, boardID = ref.boardID, threadID = ref.threadID, data = ref.data;
if ((data.excerpt == null) && siteID === Site.hostname && (thread = g.threads[boardID + "." + threadID])) {
ThreadWatcher.db.extend({ ThreadWatcher.db.extend({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -20219,26 +20337,26 @@ ThreadWatcher = (function() {
} }
}); });
} }
nodes.push(ThreadWatcher.makeLine(boardID, threadID, data)); nodes.push(ThreadWatcher.makeLine(siteID, boardID, threadID, data));
} }
list = ThreadWatcher.list; list = ThreadWatcher.list;
$.rmAll(list); $.rmAll(list);
$.add(list, nodes); $.add(list, nodes);
ThreadWatcher.refreshIcon(); ThreadWatcher.refreshIcon();
ref2 = ThreadWatcher.menu.refreshers; ref1 = ThreadWatcher.menu.refreshers;
for (j = 0, len1 = ref2.length; j < len1; j++) { for (j = 0, len2 = ref1.length; j < len2; j++) {
refresher = ref2[j]; refresher = ref1[j];
refresher(); refresher();
} }
}, },
refresh: function() { refresh: function() {
ThreadWatcher.build(); ThreadWatcher.build();
g.threads.forEach(function(thread) { g.threads.forEach(function(thread) {
var i, isWatched, len, post, ref, toggler; var i, isWatched, len1, post, ref, toggler;
isWatched = ThreadWatcher.isWatched(thread); isWatched = ThreadWatcher.isWatched(thread);
if (thread.OP) { if (thread.OP) {
ref = [thread.OP].concat(slice.call(thread.OP.clones)); ref = [thread.OP].concat(slice.call(thread.OP.clones));
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
post = ref[i]; post = ref[i];
if ((toggler = $('.watch-thread-link', post.nodes.info))) { if ((toggler = $('.watch-thread-link', post.nodes.info))) {
ThreadWatcher.setToggler(toggler, isWatched); ThreadWatcher.setToggler(toggler, isWatched);
@ -20256,15 +20374,16 @@ ThreadWatcher = (function() {
} }
}, },
refreshIcon: function() { refreshIcon: function() {
var className, i, len, ref; var className, i, len1, ref;
ref = ['replies-unread', 'replies-quoting-you']; ref = ['replies-unread', 'replies-quoting-you'];
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
className = ref[i]; className = ref[i];
ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog));
} }
}, },
update: function(boardID, threadID, newData) { update: function(boardID, threadID, newData) {
var data, key, line, n, newLine, ref, val; var data, key, line, n, newLine, ref, siteID, val;
siteID = Site.hostname;
if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
@ -20300,8 +20419,8 @@ ThreadWatcher = (function() {
threadID: threadID, threadID: threadID,
val: newData val: newData
}); });
if (line = $("#watched-threads > [data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) { if (line = $("#watched-threads > [data-site-i-d='" + siteID + "'][data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) {
newLine = ThreadWatcher.makeLine(boardID, threadID, data); newLine = ThreadWatcher.makeLine(siteID, boardID, threadID, data);
$.replace(line, newLine); $.replace(line, newLine);
return ThreadWatcher.refreshIcon(); return ThreadWatcher.refreshIcon();
} else { } else {
@ -20336,21 +20455,23 @@ ThreadWatcher = (function() {
}, cb); }, cb);
}, },
toggle: function(thread) { toggle: function(thread) {
var boardID, threadID; var boardID, siteID, threadID;
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (ThreadWatcher.db.get({ if (ThreadWatcher.db.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
return ThreadWatcher.rm(boardID, threadID); return ThreadWatcher.rm(siteID, boardID, threadID);
} else { } else {
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
add: function(thread) { add: function(thread) {
var boardID, data, threadID; var boardID, data, siteID, threadID;
data = {}; data = {};
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (thread.isDead) { if (thread.isDead) {
@ -20358,7 +20479,7 @@ ThreadWatcher = (function() {
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
ThreadWatcher.rm(boardID, threadID); ThreadWatcher.rm(siteID, boardID, threadID);
return; return;
} }
data.isDead = true; data.isDead = true;
@ -20375,14 +20496,16 @@ ThreadWatcher = (function() {
ThreadWatcher.refresh(); ThreadWatcher.refresh();
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
return ThreadWatcher.fetchStatus({ return ThreadWatcher.fetchStatus({
siteID: Site.hostname,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
}, true); }, true);
} }
}, },
rm: function(boardID, threadID) { rm: function(siteID, boardID, threadID) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -20425,7 +20548,7 @@ ThreadWatcher = (function() {
}); });
}, },
addMenuEntries: function() { addMenuEntries: function() {
var cb, conf, entries, entry, i, len, name, ref, ref1, refresh, subEntries; var cb, conf, entries, entry, i, len1, name, ref, ref1, refresh, subEntries;
entries = []; entries = [];
entries.push({ entries.push({
cb: ThreadWatcher.cb.openAll, cb: ThreadWatcher.cb.openAll,
@ -20463,7 +20586,7 @@ ThreadWatcher = (function() {
subEntries: subEntries subEntries: subEntries
} }
}); });
for (i = 0, len = entries.length; i < len; i++) { for (i = 0, len1 = entries.length; i < len1; i++) {
ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh; ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh;
if (entry.el.nodeName === 'A') { if (entry.el.nodeName === 'A') {
entry.el.href = 'javascript:;'; entry.el.href = 'javascript:;';
@ -20491,7 +20614,7 @@ ThreadWatcher = (function() {
entry.el.title += '\n[Remember Last Read Post is disabled.]'; entry.el.title += '\n[Remember Last Read Post is disabled.]';
} }
$.on(input, 'change', $.cb.checked); $.on(input, 'change', $.cb.checked);
if (name === 'Current Board' || name === 'Show Unread Count') { if (name === 'Current Board' || name === 'Show Unread Count' || name === 'Show Site Prefix') {
$.on(input, 'change', ThreadWatcher.refresh); $.on(input, 'change', ThreadWatcher.refresh);
} }
if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') { if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') {
@ -24966,6 +25089,7 @@ Main = (function() {
for (i = k = 0; k < 2; i = ++k) { for (i = k = 0; k < 2; i = ++k) {
Conf["Last Long Reply Thresholds " + i] = {}; Conf["Last Long Reply Thresholds " + i] = {};
} }
Conf['siteProperties'] = {};
Conf['Except Archives from Encryption'] = false; Conf['Except Archives from Encryption'] = false;
Conf['JSON Navigation'] = true; Conf['JSON Navigation'] = true;
Conf['Oekaki Links'] = true; Conf['Oekaki Links'] = true;
@ -24973,6 +25097,7 @@ Main = (function() {
Conf['QR Shortcut'] = true; Conf['QR Shortcut'] = true;
Conf['Bottom QR Link'] = true; Conf['Bottom QR Link'] = true;
Conf['Toggleable Thread Watcher'] = true; Conf['Toggleable Thread Watcher'] = true;
Conf['siteSoftware'] = '';
if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) { if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) {
return /this\[/.test(s.textContent); return /this\[/.test(s.textContent);
}).length) { }).length) {
@ -25272,7 +25397,7 @@ Main = (function() {
ref = $$(s.thread, board); ref = $$(s.thread, board);
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
threadRoot = ref[j]; threadRoot = ref[j];
boardObj = (boardID = threadRoot.dataset.board) ? g.boards[boardID] || new Board(boardID) : g.BOARD; boardObj = (boardID = threadRoot.dataset.board) ? (boardID = encodeURIComponent(boardID), g.boards[boardID] || new Board(boardID)) : g.BOARD;
thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj); thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj);
thread.nodes.root = threadRoot; thread.nodes.root = threadRoot;
threads.push(thread); threads.push(thread);

Binary file not shown.

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.14.4.7 // @version 1.14.5.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -198,7 +198,7 @@ docSet = function() {
}; };
g = { g = {
VERSION: '1.14.4.7', VERSION: '1.14.5.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -411,6 +411,7 @@ Config = (function() {
'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'], 'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'],
'Auto Prune': [false, 'Automatically remove dead threads.'], 'Auto Prune': [false, 'Automatically remove dead threads.'],
'Show Unread Count': [true, 'Show number of unread posts in watched threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'],
'Show Site Prefix': [true, 'When multiple sites are shown in the thread watcher, add a prefix to board names to distinguish them.'],
'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.'] 'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.']
}, },
filter: { filter: {
@ -553,8 +554,7 @@ Config = (function() {
'updater.position': 'bottom: 0px; left: 0px;', 'updater.position': 'bottom: 0px; left: 0px;',
'thread-watcher.position': 'top: 50px; left: 0px;', 'thread-watcher.position': 'top: 50px; left: 0px;',
'qr.position': 'top: 50px; right: 0px;' 'qr.position': 'top: 50px; right: 0px;'
}, }
siteSoftware: "4chan.org yotsuba\n4channel.org yotsuba\n4cdn.org yotsuba"
}; };
return Config; return Config;
@ -5753,16 +5753,21 @@ DataBoard = (function() {
$.on(d, '4chanXInitFinished', init); $.on(d, '4chanXInitFinished', init);
} }
DataBoard.prototype.initData = function(allData) { DataBoard.prototype.initData = function(data1) {
var base, name; var base, boards, lastChecked, name, ref;
this.allData = allData; this.data = data1;
if (Site.hostname === '4chan.org' && this.allData.boards) { if (this.data.boards) {
return this.data = this.allData; ref = this.data, boards = ref.boards, lastChecked = ref.lastChecked;
} else { this.data['4chan.org'] = {
return this.data = ((base = this.allData)[name = Site.hostname] || (base[name] = { boards: boards,
boards: {} lastChecked: lastChecked
})); };
delete this.data.boards;
delete this.data.lastChecked;
} }
return (base = this.data)[name = Site.hostname] || (base[name] = {
boards: {}
});
}; };
DataBoard.prototype.changes = []; DataBoard.prototype.changes = [];
@ -5778,7 +5783,7 @@ DataBoard = (function() {
if (!_this.changes.length) { if (!_this.changes.length) {
return; return;
} }
needSync = (items[_this.key].version || 0) > (_this.allData.version || 0); needSync = (items[_this.key].version || 0) > (_this.data.version || 0);
if (needSync) { if (needSync) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
@ -5788,8 +5793,8 @@ DataBoard = (function() {
} }
} }
_this.changes = []; _this.changes = [];
_this.allData.version = (_this.allData.version || 0) + 1; _this.data.version = (_this.data.version || 0) + 1;
return $.set(_this.key, _this.allData, function() { return $.set(_this.key, _this.data, function() {
if (needSync) { if (needSync) {
if (typeof _this.sync === "function") { if (typeof _this.sync === "function") {
_this.sync(); _this.sync();
@ -5807,7 +5812,7 @@ DataBoard = (function() {
}, (function(_this) { }, (function(_this) {
return function(items) { return function(items) {
var change, i, len, ref; var change, i, len, ref;
if ((items[_this.key].version || 0) > (_this.allData.version || 0)) { if ((items[_this.key].version || 0) > (_this.data.version || 0)) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
@ -5824,47 +5829,51 @@ DataBoard = (function() {
}; };
DataBoard.prototype["delete"] = function(arg) { DataBoard.prototype["delete"] = function(arg) {
var boardID, postID, threadID; var boardID, postID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID;
siteID || (siteID = Site.hostname);
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var ref; var ref;
if (postID) { if (postID) {
if (!((ref = _this.data.boards[boardID]) != null ? ref[threadID] : void 0)) { if (!((ref = _this.data[siteID].boards[boardID]) != null ? ref[threadID] : void 0)) {
return; return;
} }
delete _this.data.boards[boardID][threadID][postID]; delete _this.data[siteID].boards[boardID][threadID][postID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else if (threadID) { } else if (threadID) {
if (!_this.data.boards[boardID]) { if (!_this.data[siteID].boards[boardID]) {
return; return;
} }
delete _this.data.boards[boardID][threadID]; delete _this.data[siteID].boards[boardID][threadID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} else { } else {
return delete _this.data.boards[boardID]; return delete _this.data[siteID].boards[boardID];
} }
}; };
})(this)); })(this));
}; };
DataBoard.prototype.deleteIfEmpty = function(arg) { DataBoard.prototype.deleteIfEmpty = function(arg) {
var boardID, threadID; var boardID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
if (threadID) { if (threadID) {
if (!Object.keys(this.data.boards[boardID][threadID]).length) { if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
delete this.data.boards[boardID][threadID]; delete this.data[siteID].boards[boardID][threadID];
return this.deleteIfEmpty({ return this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
} else if (!Object.keys(this.data.boards[boardID]).length) { } else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
return delete this.data.boards[boardID]; return delete this.data[siteID].boards[boardID];
} }
}; };
@ -5877,24 +5886,26 @@ DataBoard = (function() {
}; };
DataBoard.prototype.setUnsafe = function(arg) { DataBoard.prototype.setUnsafe = function(arg) {
var base, base1, base2, boardID, postID, threadID, val; var base, base1, base2, boardID, postID, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val;
siteID || (siteID = Site.hostname);
if (postID !== void 0) { if (postID !== void 0) {
return ((base = ((base1 = this.data.boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val; return ((base = ((base1 = this.data[siteID].boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val;
} else if (threadID !== void 0) { } else if (threadID !== void 0) {
return ((base2 = this.data.boards)[boardID] || (base2[boardID] = {}))[threadID] = val; return ((base2 = this.data[siteID].boards)[boardID] || (base2[boardID] = {}))[threadID] = val;
} else { } else {
return this.data.boards[boardID] = val; return this.data[siteID].boards[boardID] = val;
} }
}; };
DataBoard.prototype.extend = function(arg, cb) { DataBoard.prototype.extend = function(arg, cb) {
var boardID, postID, rm, threadID, val; var boardID, postID, rm, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm;
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var i, key, len, oldVal, ref; var i, key, len, oldVal, ref;
oldVal = _this.get({ oldVal = _this.get({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5907,6 +5918,7 @@ DataBoard = (function() {
} }
$.extend(oldVal, val); $.extend(oldVal, val);
return _this.setUnsafe({ return _this.setUnsafe({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5916,18 +5928,22 @@ DataBoard = (function() {
})(this), cb); })(this), cb);
}; };
DataBoard.prototype.setLastChecked = function() { DataBoard.prototype.setLastChecked = function(siteID) {
if (siteID == null) {
siteID = Site.hostname;
}
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
return _this.data.lastChecked = Date.now(); return _this.data[siteID].lastChecked = Date.now();
}; };
})(this)); })(this));
}; };
DataBoard.prototype.get = function(arg) { DataBoard.prototype.get = function(arg) {
var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; var ID, board, boardID, defaultValue, i, len, postID, siteID, thread, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue;
if (board = this.data.boards[boardID]) { siteID || (siteID = Site.hostname);
if (board = this.data[siteID].boards[boardID]) {
if (threadID == null) { if (threadID == null) {
if (postID != null) { if (postID != null) {
for (thread = i = 0, len = board.length; i < len; thread = ++i) { for (thread = i = 0, len = board.length; i < len; thread = ++i) {
@ -5948,21 +5964,23 @@ DataBoard = (function() {
}; };
DataBoard.prototype.clean = function() { DataBoard.prototype.clean = function() {
var boardID, now, ref, ref1, val; var boardID, now, ref, ref1, siteID, val;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
ref = this.data.boards; siteID = Site.hostname;
ref = this.data[siteID].boards;
for (boardID in ref) { for (boardID in ref) {
val = ref[boardID]; val = ref[boardID];
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
now = Date.now(); now = Date.now();
if (!((now - 2 * $.HOUR < (ref1 = this.data.lastChecked || 0) && ref1 <= now))) { if (!((now - 2 * $.HOUR < (ref1 = this.data[siteID].lastChecked || 0) && ref1 <= now))) {
this.data.lastChecked = now; this.data[siteID].lastChecked = now;
for (boardID in this.data.boards) { for (boardID in this.data[siteID].boards) {
this.ajaxClean(boardID); this.ajaxClean(boardID);
} }
} }
@ -5987,8 +6005,9 @@ DataBoard = (function() {
}; };
DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) {
var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; var ID, board, i, j, k, len, len1, len2, page, ref, siteID, thread, threads;
if (!(board = this.data.boards[boardID])) { siteID = Site.hostname;
if (!(board = this.data[siteID].boards[boardID])) {
return; return;
} }
threads = {}; threads = {};
@ -6013,15 +6032,16 @@ DataBoard = (function() {
} }
} }
} }
this.data.boards[boardID] = threads; this.data[siteID].boards[boardID] = threads;
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
return $.set(this.key, this.allData); return $.set(this.key, this.data);
}; };
DataBoard.prototype.onSync = function(data) { DataBoard.prototype.onSync = function(data) {
if (!((data.version || 0) > (this.allData.version || 0))) { if (!((data.version || 0) > (this.data.version || 0))) {
return; return;
} }
this.initData(data); this.initData(data);
@ -7262,21 +7282,30 @@ SW = {};
isOPContainerThread: true, isOPContainerThread: true,
disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'], disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'],
detect: function() { detect: function() {
var i, len, ref, script; var i, len, m, properties, ref, root, script;
ref = $$('script:not([src])', d.head); ref = $$('script:not([src])', d.head);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
script = ref[i]; script = ref[i];
if (/\bvar configRoot=".*?"/.test(script.textContent)) { if ((m = script.textContent.match(/\bvar configRoot=(".*?")/))) {
return true; properties = {};
try {
root = JSON.parse(m[1]);
if (root[0] === '/') {
properties.root = location.origin + root;
} else if (/^https?:/.test(root)) {
properties.root = root;
}
} catch (_error) {}
return properties;
} }
} }
return false; return false;
}, },
urls: { urls: {
thread: function(arg) { thread: function(arg) {
var boardID, threadID; var boardID, ref, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
return location.origin + "/" + boardID + "/res/" + threadID + ".html"; return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/res/" + threadID + ".html";
} }
}, },
selectors: { selectors: {
@ -7566,49 +7595,65 @@ Site = (function() {
var Site; var Site;
Site = { Site = {
init: function(cb) { defaultProperties: {
var hostname, i, len, line, ref, ref1, software, swDict; '4chan.org': {
swDict = {}; software: 'yotsuba'
ref = Conf['siteSoftware'].split('\n'); },
for (i = 0, len = ref.length; i < len; i++) { '4channel.org': {
line = ref[i]; software: 'yotsuba'
if (!(line[0] !== '#')) { },
continue; '4cdn.org': {
} software: 'yotsuba'
ref1 = line.split(' '), hostname = ref1[0], software = ref1[1];
if (software in SW) {
swDict[hostname] = software;
}
}
hostname = location.hostname;
while (hostname && !(hostname in swDict)) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname === '4channel.org') {
hostname = '4chan.org';
}
if (hostname) {
this.set(hostname, swDict[hostname]);
return cb();
} else {
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base;
for (software in SW) {
if (typeof (base = SW[software]).detect === "function" ? base.detect() : void 0) {
_this.set(location.hostname.replace(/^www\./, ''), software);
Conf['siteSoftware'] += "\n" + _this.hostname + " " + _this.software;
$.set('siteSoftware', Conf['siteSoftware']);
cb();
}
}
};
})(this));
} }
}, },
set: function(hostname1, software1) { init: function(cb) {
var hostname;
$.extend(Conf['siteProperties'], Site.defaultProperties);
hostname = location.hostname;
while (hostname && !(hostname in Conf['siteProperties'])) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname && Conf['siteProperties'][hostname].software in SW) {
this.set(hostname);
cb();
}
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base, base1, changed, changes, key, properties, software;
for (software in SW) {
if (!((changes = typeof (base = SW[software]).detect === "function" ? base.detect() : void 0))) {
continue;
}
changes.software = software;
hostname = location.hostname.replace(/^www\./, '');
properties = ((base1 = Conf['siteProperties'])[hostname] || (base1[hostname] = {}));
changed = 0;
for (key in changes) {
if (!(properties[key] !== changes[key])) {
continue;
}
properties[key] = changes[key];
changed++;
}
if (changed) {
$.set('siteProperties', Conf['siteProperties']);
}
if (!_this.hostname) {
_this.set(hostname);
cb();
}
return;
}
};
})(this));
},
set: function(hostname1) {
this.hostname = hostname1; this.hostname = hostname1;
this.software = software1; this.properties = Conf['siteProperties'][this.hostname];
this.software = this.properties.software;
if (this.software === 'yotsuba') {
this.hostname = '4chan.org';
}
return $.extend(this, SW[this.software]); return $.extend(this, SW[this.software]);
} }
}; };
@ -9368,7 +9413,7 @@ Get = (function() {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, ref, ref1; var OP, excerpt, ref, ref1;
OP = thread.OP; OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP)); excerpt = ("/" + (decodeURIComponent(thread.board.ID)) + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP));
if (excerpt.length > 73) { if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "..."; return excerpt.slice(0, 70) + "...";
} }
@ -11950,7 +11995,7 @@ Settings = (function() {
} }
}, },
upgrade: function(data, version) { upgrade: function(data, version) {
var addCSS, addSauces, boardID, changes, compareString, corrupted, j, k, key, len, len1, list, name, record, ref, ref1, ref2, ref3, ref4, ref5, ref6, rice, set, setD, type, uids, val, val2, value; var addCSS, addSauces, boardID, boards, changes, compareString, corrupted, db, hostname, j, k, key, l, lastChecked, len, len1, len2, len3, line, list, m, name, record, ref, ref1, ref10, ref11, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rice, set, setD, siteProperties, software, type, uids, val, val2, value;
changes = {}; changes = {};
set = function(key, value) { set = function(key, value) {
return data[key] = changes[key] = value; return data[key] = changes[key] = value;
@ -12198,6 +12243,34 @@ Settings = (function() {
set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba'); set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba');
} }
} }
if (compareString < '00001.00014.00005.00000') {
ref7 = DataBoard.keys;
for (l = 0, len2 = ref7.length; l < len2; l++) {
db = ref7[l];
if ((ref8 = data[db]) != null ? ref8.boards : void 0) {
ref9 = data[db], boards = ref9.boards, lastChecked = ref9.lastChecked;
data[db]['4chan.org'] = {
boards: boards,
lastChecked: lastChecked
};
delete data[db].boards;
delete data[db].lastChecked;
set(db, data[db]);
}
}
if ((data['siteSoftware'] != null) && (data['siteProperties'] == null)) {
siteProperties = {};
ref10 = data['siteSoftware'].split('\n');
for (m = 0, len3 = ref10.length; m < len3; m++) {
line = ref10[m];
ref11 = line.split(' '), hostname = ref11[0], software = ref11[1];
siteProperties[hostname] = {
software: software
};
}
set('siteProperties', siteProperties);
}
}
return changes; return changes;
}, },
loadSettings: function(data, cb) { loadSettings: function(data, cb) {
@ -19684,7 +19757,7 @@ ThreadWatcher = (function() {
this.refreshButton = $('.refresh', this.dialog); this.refreshButton = $('.refresh', this.dialog);
this.closeButton = $('.move > .close', this.dialog); this.closeButton = $('.move > .close', this.dialog);
this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts');
this.unreadEnabled = Conf['Remember Last Read Post'] && Site.software === 'yotsuba'; this.unreadEnabled = Conf['Remember Last Read Post'];
$.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.buttonFetchAll); $.on(this.refreshButton, 'click', this.buttonFetchAll);
@ -19837,27 +19910,28 @@ ThreadWatcher = (function() {
}, },
cb: { cb: {
openAll: function() { openAll: function() {
var a, i, len, ref; var a, i, len1, ref;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = $$('a[title]', ThreadWatcher.list); ref = $$('a[title]', ThreadWatcher.list);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
a = ref[i]; a = ref[i];
$.open(a.href); $.open(a.href);
} }
return $.event('CloseMenu'); return $.event('CloseMenu');
}, },
pruneDeads: function() { pruneDeads: function() {
var boardID, data, i, len, ref, ref1, threadID; var boardID, data, i, len1, ref, ref1, siteID, threadID;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = ThreadWatcher.getAll(); ref = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; ref1 = ref[i], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data;
if (data.isDead) { if (data.isDead) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -19872,9 +19946,10 @@ ThreadWatcher = (function() {
return ThreadWatcher.toggle(thread); return ThreadWatcher.toggle(thread);
}, },
rm: function() { rm: function() {
var boardID, ref, threadID; var boardID, ref, siteID, threadID;
siteID = this.parentNode.dataset.siteID;
ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1];
return ThreadWatcher.rm(boardID, +threadID); return ThreadWatcher.rm(siteID, boardID, +threadID);
}, },
post: function(e) { post: function(e) {
var boardID, postID, ref, threadID; var boardID, postID, ref, threadID;
@ -19888,11 +19963,12 @@ ThreadWatcher = (function() {
} }
}, },
onIndexUpdate: function(e) { onIndexUpdate: function(e) {
var boardID, data, db, nKilled, ref, ref1, threadID; var boardID, data, db, nKilled, ref, ref1, siteID, threadID;
db = ThreadWatcher.db; db = ThreadWatcher.db;
siteID = Site.hostname;
boardID = g.BOARD.ID; boardID = g.BOARD.ID;
nKilled = 0; nKilled = 0;
ref = db.data.boards[boardID]; ref = db.data[siteID].boards[boardID];
for (threadID in ref) { for (threadID in ref) {
data = ref[threadID]; data = ref[threadID];
if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) { if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) {
@ -19919,6 +19995,7 @@ ThreadWatcher = (function() {
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({ ThreadWatcher.fetchStatus({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
@ -19948,9 +20025,9 @@ ThreadWatcher = (function() {
return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
}, },
abort: function() { abort: function() {
var i, len, ref, req; var i, len1, ref, req;
ref = ThreadWatcher.requests; ref = ThreadWatcher.requests;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
req = ref[i]; req = ref[i];
if (req.readyState !== 4) { if (req.readyState !== 4) {
req.abort(); req.abort();
@ -19970,7 +20047,7 @@ ThreadWatcher = (function() {
db = ThreadWatcher.db; db = ThreadWatcher.db;
interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR; interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR;
now = Date.now(); now = Date.now();
if (!((now - interval < (ref = db.data.lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) { if (!((now - interval < (ref = db.data[Site.hostname].lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) {
ThreadWatcher.fetchAllStatus(); ThreadWatcher.fetchAllStatus();
db.setLastChecked(); db.setLastChecked();
} }
@ -19984,7 +20061,7 @@ ThreadWatcher = (function() {
} }
}, },
fetchAllStatus: function() { fetchAllStatus: function() {
var db, dbs, i, len, n, results; var db, dbs, i, len1, n, results;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
@ -19993,13 +20070,13 @@ ThreadWatcher = (function() {
}); });
n = 0; n = 0;
results = []; results = [];
for (i = 0, len = dbs.length; i < len; i++) { for (i = 0, len1 = dbs.length; i < len1; i++) {
db = dbs[i]; db = dbs[i];
results.push(db.forceSync(function() { results.push(db.forceSync(function() {
var j, len1, thread, threads; var j, len2, thread, threads;
if ((++n) === dbs.length) { if ((++n) === dbs.length) {
threads = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (j = 0, len1 = threads.length; j < len1; j++) { for (j = 0, len2 = threads.length; j < len2; j++) {
thread = threads[j]; thread = threads[j];
ThreadWatcher.fetchStatus(thread); ThreadWatcher.fetchStatus(thread);
} }
@ -20009,11 +20086,11 @@ ThreadWatcher = (function() {
return results; return results;
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, req, threadID; var boardID, data, req, siteID, threadID;
if (Site.software !== 'yotsuba') { siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (!(Site.software === 'yotsuba' && siteID === Site.hostname)) {
return; return;
} }
boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
@ -20032,7 +20109,7 @@ ThreadWatcher = (function() {
return ThreadWatcher.requests.push(req); return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { parseStatus: function(arg) {
var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP; var boardID, data, i, isDead, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP;
boardID = arg.boardID, threadID = arg.threadID, data = arg.data; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
ThreadWatcher.fetched++; ThreadWatcher.fetched++;
if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
@ -20063,7 +20140,7 @@ ThreadWatcher = (function() {
postID: threadID postID: threadID
}) : void 0); }) : void 0);
ref1 = this.response.posts; ref1 = this.response.posts;
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len1 = ref1.length; i < len1; i++) {
postObj = ref1[i]; postObj = ref1[i];
if (!(postObj.no > lastReadPost)) { if (!(postObj.no > lastReadPost)) {
continue; continue;
@ -20131,29 +20208,35 @@ ThreadWatcher = (function() {
} }
}, },
getAll: function() { getAll: function() {
var all, boardID, data, ref, threadID, threads; var all, boardID, boards, data, ref, ref1, siteID, threadID, threads;
all = []; all = [];
ref = ThreadWatcher.db.data.boards; ref = ThreadWatcher.db.data;
for (boardID in ref) { for (siteID in ref) {
threads = ref[boardID]; boards = ref[siteID];
if (Conf['Current Board'] && boardID !== g.BOARD.ID) { ref1 = boards.boards;
continue; for (boardID in ref1) {
} threads = ref1[boardID];
for (threadID in threads) { if (Conf['Current Board'] && (siteID !== Site.hostname || boardID !== g.BOARD.ID)) {
data = threads[threadID]; continue;
if (data && typeof data === 'object') { }
all.push({ for (threadID in threads) {
boardID: boardID, data = threads[threadID];
threadID: threadID, if (data && typeof data === 'object') {
data: data all.push({
}); siteID: siteID,
boardID: boardID,
threadID: threadID,
data: data
});
}
} }
} }
} }
return all; return all;
}, },
makeLine: function(boardID, threadID, data) { makeLine: function(siteID, boardID, threadID, data) {
var count, div, excerpt, fullID, link, title, x; var count, div, excerpt, fullID, link, ref, ref1, software, title, x;
software = (ref = Conf['siteProperties'][siteID]) != null ? ref.software : void 0;
x = $.el('a', { x = $.el('a', {
className: 'fa fa-times', className: 'fa fa-times',
href: 'javascript:;' href: 'javascript:;'
@ -20161,15 +20244,19 @@ ThreadWatcher = (function() {
$.on(x, 'click', ThreadWatcher.cb.rm); $.on(x, 'click', ThreadWatcher.cb.rm);
excerpt = data.excerpt; excerpt = data.excerpt;
excerpt || (excerpt = "/" + boardID + "/ - No." + threadID); excerpt || (excerpt = "/" + boardID + "/ - No." + threadID);
if (Conf['Show Site Prefix']) {
excerpt = ThreadWatcher.prefixes[siteID] + excerpt;
}
link = $.el('a', { link = $.el('a', {
href: Site.urls.thread({ href: ((ref1 = SW[software]) != null ? ref1.urls.thread({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}), }) : void 0) || '',
title: excerpt, title: excerpt,
className: 'watcher-link' className: 'watcher-link'
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && (data.unread != null)) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba' && (data.unread != null)) {
count = $.el('span', { count = $.el('span', {
textContent: "(" + data.unread + ")", textContent: "(" + data.unread + ")",
className: 'watcher-unread' className: 'watcher-unread'
@ -20184,13 +20271,14 @@ ThreadWatcher = (function() {
div = $.el('div'); div = $.el('div');
fullID = boardID + "." + threadID; fullID = boardID + "." + threadID;
div.dataset.fullID = fullID; div.dataset.fullID = fullID;
div.dataset.siteID = siteID;
if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) { if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) {
$.addClass(div, 'current'); $.addClass(div, 'current');
} }
if (data.isDead) { if (data.isDead) {
$.addClass(div, 'dead-thread'); $.addClass(div, 'dead-thread');
} }
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba') {
if (data.unread === 0) { if (data.unread === 0) {
$.addClass(div, 'replies-read'); $.addClass(div, 'replies-read');
} }
@ -20204,13 +20292,43 @@ ThreadWatcher = (function() {
$.add(div, [x, $.tn(' '), link]); $.add(div, [x, $.tn(' '), link]);
return div; return div;
}, },
setPrefixes: function(threads) {
var conflicts, conflicts2, i, j, len, len1, len2, prefix, prefixes, siteID, siteID2;
prefixes = {};
for (i = 0, len1 = threads.length; i < len1; i++) {
siteID = threads[i].siteID;
if (siteID in prefixes) {
continue;
}
len = 0;
prefix = '';
conflicts = Object.keys(prefixes);
while (conflicts.length > 0) {
len++;
prefix = siteID.slice(0, len);
conflicts2 = [];
for (j = 0, len2 = conflicts.length; j < len2; j++) {
siteID2 = conflicts[j];
if (siteID2.slice(0, len) === prefix) {
conflicts2.push(siteID2);
} else if (prefixes[siteID2].length < len) {
prefixes[siteID2] = siteID2.slice(0, len);
}
}
conflicts = conflicts2;
}
prefixes[siteID] = prefix;
}
return ThreadWatcher.prefixes = prefixes;
},
build: function() { build: function() {
var boardID, data, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, thread, threadID; var boardID, data, i, j, len1, len2, list, nodes, ref, ref1, refresher, siteID, thread, threadID, threads;
nodes = []; nodes = [];
ref = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { ThreadWatcher.setPrefixes(threads);
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; for (i = 0, len1 = threads.length; i < len1; i++) {
if ((data.excerpt == null) && (thread = g.threads[boardID + "." + threadID])) { ref = threads[i], siteID = ref.siteID, boardID = ref.boardID, threadID = ref.threadID, data = ref.data;
if ((data.excerpt == null) && siteID === Site.hostname && (thread = g.threads[boardID + "." + threadID])) {
ThreadWatcher.db.extend({ ThreadWatcher.db.extend({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -20219,26 +20337,26 @@ ThreadWatcher = (function() {
} }
}); });
} }
nodes.push(ThreadWatcher.makeLine(boardID, threadID, data)); nodes.push(ThreadWatcher.makeLine(siteID, boardID, threadID, data));
} }
list = ThreadWatcher.list; list = ThreadWatcher.list;
$.rmAll(list); $.rmAll(list);
$.add(list, nodes); $.add(list, nodes);
ThreadWatcher.refreshIcon(); ThreadWatcher.refreshIcon();
ref2 = ThreadWatcher.menu.refreshers; ref1 = ThreadWatcher.menu.refreshers;
for (j = 0, len1 = ref2.length; j < len1; j++) { for (j = 0, len2 = ref1.length; j < len2; j++) {
refresher = ref2[j]; refresher = ref1[j];
refresher(); refresher();
} }
}, },
refresh: function() { refresh: function() {
ThreadWatcher.build(); ThreadWatcher.build();
g.threads.forEach(function(thread) { g.threads.forEach(function(thread) {
var i, isWatched, len, post, ref, toggler; var i, isWatched, len1, post, ref, toggler;
isWatched = ThreadWatcher.isWatched(thread); isWatched = ThreadWatcher.isWatched(thread);
if (thread.OP) { if (thread.OP) {
ref = [thread.OP].concat(slice.call(thread.OP.clones)); ref = [thread.OP].concat(slice.call(thread.OP.clones));
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
post = ref[i]; post = ref[i];
if ((toggler = $('.watch-thread-link', post.nodes.info))) { if ((toggler = $('.watch-thread-link', post.nodes.info))) {
ThreadWatcher.setToggler(toggler, isWatched); ThreadWatcher.setToggler(toggler, isWatched);
@ -20256,15 +20374,16 @@ ThreadWatcher = (function() {
} }
}, },
refreshIcon: function() { refreshIcon: function() {
var className, i, len, ref; var className, i, len1, ref;
ref = ['replies-unread', 'replies-quoting-you']; ref = ['replies-unread', 'replies-quoting-you'];
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
className = ref[i]; className = ref[i];
ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog));
} }
}, },
update: function(boardID, threadID, newData) { update: function(boardID, threadID, newData) {
var data, key, line, n, newLine, ref, val; var data, key, line, n, newLine, ref, siteID, val;
siteID = Site.hostname;
if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
@ -20300,8 +20419,8 @@ ThreadWatcher = (function() {
threadID: threadID, threadID: threadID,
val: newData val: newData
}); });
if (line = $("#watched-threads > [data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) { if (line = $("#watched-threads > [data-site-i-d='" + siteID + "'][data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) {
newLine = ThreadWatcher.makeLine(boardID, threadID, data); newLine = ThreadWatcher.makeLine(siteID, boardID, threadID, data);
$.replace(line, newLine); $.replace(line, newLine);
return ThreadWatcher.refreshIcon(); return ThreadWatcher.refreshIcon();
} else { } else {
@ -20336,21 +20455,23 @@ ThreadWatcher = (function() {
}, cb); }, cb);
}, },
toggle: function(thread) { toggle: function(thread) {
var boardID, threadID; var boardID, siteID, threadID;
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (ThreadWatcher.db.get({ if (ThreadWatcher.db.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
return ThreadWatcher.rm(boardID, threadID); return ThreadWatcher.rm(siteID, boardID, threadID);
} else { } else {
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
add: function(thread) { add: function(thread) {
var boardID, data, threadID; var boardID, data, siteID, threadID;
data = {}; data = {};
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (thread.isDead) { if (thread.isDead) {
@ -20358,7 +20479,7 @@ ThreadWatcher = (function() {
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
ThreadWatcher.rm(boardID, threadID); ThreadWatcher.rm(siteID, boardID, threadID);
return; return;
} }
data.isDead = true; data.isDead = true;
@ -20375,14 +20496,16 @@ ThreadWatcher = (function() {
ThreadWatcher.refresh(); ThreadWatcher.refresh();
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
return ThreadWatcher.fetchStatus({ return ThreadWatcher.fetchStatus({
siteID: Site.hostname,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
}, true); }, true);
} }
}, },
rm: function(boardID, threadID) { rm: function(siteID, boardID, threadID) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -20425,7 +20548,7 @@ ThreadWatcher = (function() {
}); });
}, },
addMenuEntries: function() { addMenuEntries: function() {
var cb, conf, entries, entry, i, len, name, ref, ref1, refresh, subEntries; var cb, conf, entries, entry, i, len1, name, ref, ref1, refresh, subEntries;
entries = []; entries = [];
entries.push({ entries.push({
cb: ThreadWatcher.cb.openAll, cb: ThreadWatcher.cb.openAll,
@ -20463,7 +20586,7 @@ ThreadWatcher = (function() {
subEntries: subEntries subEntries: subEntries
} }
}); });
for (i = 0, len = entries.length; i < len; i++) { for (i = 0, len1 = entries.length; i < len1; i++) {
ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh; ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh;
if (entry.el.nodeName === 'A') { if (entry.el.nodeName === 'A') {
entry.el.href = 'javascript:;'; entry.el.href = 'javascript:;';
@ -20491,7 +20614,7 @@ ThreadWatcher = (function() {
entry.el.title += '\n[Remember Last Read Post is disabled.]'; entry.el.title += '\n[Remember Last Read Post is disabled.]';
} }
$.on(input, 'change', $.cb.checked); $.on(input, 'change', $.cb.checked);
if (name === 'Current Board' || name === 'Show Unread Count') { if (name === 'Current Board' || name === 'Show Unread Count' || name === 'Show Site Prefix') {
$.on(input, 'change', ThreadWatcher.refresh); $.on(input, 'change', ThreadWatcher.refresh);
} }
if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') { if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') {
@ -24966,6 +25089,7 @@ Main = (function() {
for (i = k = 0; k < 2; i = ++k) { for (i = k = 0; k < 2; i = ++k) {
Conf["Last Long Reply Thresholds " + i] = {}; Conf["Last Long Reply Thresholds " + i] = {};
} }
Conf['siteProperties'] = {};
Conf['Except Archives from Encryption'] = false; Conf['Except Archives from Encryption'] = false;
Conf['JSON Navigation'] = true; Conf['JSON Navigation'] = true;
Conf['Oekaki Links'] = true; Conf['Oekaki Links'] = true;
@ -24973,6 +25097,7 @@ Main = (function() {
Conf['QR Shortcut'] = true; Conf['QR Shortcut'] = true;
Conf['Bottom QR Link'] = true; Conf['Bottom QR Link'] = true;
Conf['Toggleable Thread Watcher'] = true; Conf['Toggleable Thread Watcher'] = true;
Conf['siteSoftware'] = '';
if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) { if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) {
return /this\[/.test(s.textContent); return /this\[/.test(s.textContent);
}).length) { }).length) {
@ -25272,7 +25397,7 @@ Main = (function() {
ref = $$(s.thread, board); ref = $$(s.thread, board);
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
threadRoot = ref[j]; threadRoot = ref[j];
boardObj = (boardID = threadRoot.dataset.board) ? g.boards[boardID] || new Board(boardID) : g.BOARD; boardObj = (boardID = threadRoot.dataset.board) ? (boardID = encodeURIComponent(boardID), g.boards[boardID] || new Board(boardID)) : g.BOARD;
thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj); thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj);
thread.nodes.root = threadRoot; thread.nodes.root = threadRoot;
threads.push(thread); threads.push(thread);

Binary file not shown.

View File

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

View File

@ -1,6 +1,6 @@
// ==UserScript== // ==UserScript==
// @name 4chan X // @name 4chan X
// @version 1.14.4.7 // @version 1.14.5.0
// @minGMVer 1.14 // @minGMVer 1.14
// @minFFVer 26 // @minFFVer 26
// @namespace 4chan-X // @namespace 4chan-X
@ -198,7 +198,7 @@ docSet = function() {
}; };
g = { g = {
VERSION: '1.14.4.7', VERSION: '1.14.5.0',
NAMESPACE: '4chan X.', NAMESPACE: '4chan X.',
boards: {} boards: {}
}; };
@ -411,6 +411,7 @@ Config = (function() {
'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'], 'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'],
'Auto Prune': [false, 'Automatically remove dead threads.'], 'Auto Prune': [false, 'Automatically remove dead threads.'],
'Show Unread Count': [true, 'Show number of unread posts in watched threads.'], 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'],
'Show Site Prefix': [true, 'When multiple sites are shown in the thread watcher, add a prefix to board names to distinguish them.'],
'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.'] 'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.']
}, },
filter: { filter: {
@ -553,8 +554,7 @@ Config = (function() {
'updater.position': 'bottom: 0px; left: 0px;', 'updater.position': 'bottom: 0px; left: 0px;',
'thread-watcher.position': 'top: 50px; left: 0px;', 'thread-watcher.position': 'top: 50px; left: 0px;',
'qr.position': 'top: 50px; right: 0px;' 'qr.position': 'top: 50px; right: 0px;'
}, }
siteSoftware: "4chan.org yotsuba\n4channel.org yotsuba\n4cdn.org yotsuba"
}; };
return Config; return Config;
@ -5753,16 +5753,21 @@ DataBoard = (function() {
$.on(d, '4chanXInitFinished', init); $.on(d, '4chanXInitFinished', init);
} }
DataBoard.prototype.initData = function(allData) { DataBoard.prototype.initData = function(data1) {
var base, name; var base, boards, lastChecked, name, ref;
this.allData = allData; this.data = data1;
if (Site.hostname === '4chan.org' && this.allData.boards) { if (this.data.boards) {
return this.data = this.allData; ref = this.data, boards = ref.boards, lastChecked = ref.lastChecked;
} else { this.data['4chan.org'] = {
return this.data = ((base = this.allData)[name = Site.hostname] || (base[name] = { boards: boards,
boards: {} lastChecked: lastChecked
})); };
delete this.data.boards;
delete this.data.lastChecked;
} }
return (base = this.data)[name = Site.hostname] || (base[name] = {
boards: {}
});
}; };
DataBoard.prototype.changes = []; DataBoard.prototype.changes = [];
@ -5778,7 +5783,7 @@ DataBoard = (function() {
if (!_this.changes.length) { if (!_this.changes.length) {
return; return;
} }
needSync = (items[_this.key].version || 0) > (_this.allData.version || 0); needSync = (items[_this.key].version || 0) > (_this.data.version || 0);
if (needSync) { if (needSync) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
@ -5788,8 +5793,8 @@ DataBoard = (function() {
} }
} }
_this.changes = []; _this.changes = [];
_this.allData.version = (_this.allData.version || 0) + 1; _this.data.version = (_this.data.version || 0) + 1;
return $.set(_this.key, _this.allData, function() { return $.set(_this.key, _this.data, function() {
if (needSync) { if (needSync) {
if (typeof _this.sync === "function") { if (typeof _this.sync === "function") {
_this.sync(); _this.sync();
@ -5807,7 +5812,7 @@ DataBoard = (function() {
}, (function(_this) { }, (function(_this) {
return function(items) { return function(items) {
var change, i, len, ref; var change, i, len, ref;
if ((items[_this.key].version || 0) > (_this.allData.version || 0)) { if ((items[_this.key].version || 0) > (_this.data.version || 0)) {
_this.initData(items[_this.key]); _this.initData(items[_this.key]);
ref = _this.changes; ref = _this.changes;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
@ -5824,47 +5829,51 @@ DataBoard = (function() {
}; };
DataBoard.prototype["delete"] = function(arg) { DataBoard.prototype["delete"] = function(arg) {
var boardID, postID, threadID; var boardID, postID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID;
siteID || (siteID = Site.hostname);
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var ref; var ref;
if (postID) { if (postID) {
if (!((ref = _this.data.boards[boardID]) != null ? ref[threadID] : void 0)) { if (!((ref = _this.data[siteID].boards[boardID]) != null ? ref[threadID] : void 0)) {
return; return;
} }
delete _this.data.boards[boardID][threadID][postID]; delete _this.data[siteID].boards[boardID][threadID][postID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
} else if (threadID) { } else if (threadID) {
if (!_this.data.boards[boardID]) { if (!_this.data[siteID].boards[boardID]) {
return; return;
} }
delete _this.data.boards[boardID][threadID]; delete _this.data[siteID].boards[boardID][threadID];
return _this.deleteIfEmpty({ return _this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} else { } else {
return delete _this.data.boards[boardID]; return delete _this.data[siteID].boards[boardID];
} }
}; };
})(this)); })(this));
}; };
DataBoard.prototype.deleteIfEmpty = function(arg) { DataBoard.prototype.deleteIfEmpty = function(arg) {
var boardID, threadID; var boardID, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
if (threadID) { if (threadID) {
if (!Object.keys(this.data.boards[boardID][threadID]).length) { if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) {
delete this.data.boards[boardID][threadID]; delete this.data[siteID].boards[boardID][threadID];
return this.deleteIfEmpty({ return this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
} else if (!Object.keys(this.data.boards[boardID]).length) { } else if (!Object.keys(this.data[siteID].boards[boardID]).length) {
return delete this.data.boards[boardID]; return delete this.data[siteID].boards[boardID];
} }
}; };
@ -5877,24 +5886,26 @@ DataBoard = (function() {
}; };
DataBoard.prototype.setUnsafe = function(arg) { DataBoard.prototype.setUnsafe = function(arg) {
var base, base1, base2, boardID, postID, threadID, val; var base, base1, base2, boardID, postID, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val;
siteID || (siteID = Site.hostname);
if (postID !== void 0) { if (postID !== void 0) {
return ((base = ((base1 = this.data.boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val; return ((base = ((base1 = this.data[siteID].boards)[boardID] || (base1[boardID] = {})))[threadID] || (base[threadID] = {}))[postID] = val;
} else if (threadID !== void 0) { } else if (threadID !== void 0) {
return ((base2 = this.data.boards)[boardID] || (base2[boardID] = {}))[threadID] = val; return ((base2 = this.data[siteID].boards)[boardID] || (base2[boardID] = {}))[threadID] = val;
} else { } else {
return this.data.boards[boardID] = val; return this.data[siteID].boards[boardID] = val;
} }
}; };
DataBoard.prototype.extend = function(arg, cb) { DataBoard.prototype.extend = function(arg, cb) {
var boardID, postID, rm, threadID, val; var boardID, postID, rm, siteID, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val, rm = arg.rm;
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
var i, key, len, oldVal, ref; var i, key, len, oldVal, ref;
oldVal = _this.get({ oldVal = _this.get({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5907,6 +5918,7 @@ DataBoard = (function() {
} }
$.extend(oldVal, val); $.extend(oldVal, val);
return _this.setUnsafe({ return _this.setUnsafe({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
postID: postID, postID: postID,
@ -5916,18 +5928,22 @@ DataBoard = (function() {
})(this), cb); })(this), cb);
}; };
DataBoard.prototype.setLastChecked = function() { DataBoard.prototype.setLastChecked = function(siteID) {
if (siteID == null) {
siteID = Site.hostname;
}
return this.save((function(_this) { return this.save((function(_this) {
return function() { return function() {
return _this.data.lastChecked = Date.now(); return _this.data[siteID].lastChecked = Date.now();
}; };
})(this)); })(this));
}; };
DataBoard.prototype.get = function(arg) { DataBoard.prototype.get = function(arg) {
var ID, board, boardID, defaultValue, i, len, postID, thread, threadID, val; var ID, board, boardID, defaultValue, i, len, postID, siteID, thread, threadID, val;
boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue;
if (board = this.data.boards[boardID]) { siteID || (siteID = Site.hostname);
if (board = this.data[siteID].boards[boardID]) {
if (threadID == null) { if (threadID == null) {
if (postID != null) { if (postID != null) {
for (thread = i = 0, len = board.length; i < len; thread = ++i) { for (thread = i = 0, len = board.length; i < len; thread = ++i) {
@ -5948,21 +5964,23 @@ DataBoard = (function() {
}; };
DataBoard.prototype.clean = function() { DataBoard.prototype.clean = function() {
var boardID, now, ref, ref1, val; var boardID, now, ref, ref1, siteID, val;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
ref = this.data.boards; siteID = Site.hostname;
ref = this.data[siteID].boards;
for (boardID in ref) { for (boardID in ref) {
val = ref[boardID]; val = ref[boardID];
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
} }
now = Date.now(); now = Date.now();
if (!((now - 2 * $.HOUR < (ref1 = this.data.lastChecked || 0) && ref1 <= now))) { if (!((now - 2 * $.HOUR < (ref1 = this.data[siteID].lastChecked || 0) && ref1 <= now))) {
this.data.lastChecked = now; this.data[siteID].lastChecked = now;
for (boardID in this.data.boards) { for (boardID in this.data[siteID].boards) {
this.ajaxClean(boardID); this.ajaxClean(boardID);
} }
} }
@ -5987,8 +6005,9 @@ DataBoard = (function() {
}; };
DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) {
var ID, board, i, j, k, len, len1, len2, page, ref, thread, threads; var ID, board, i, j, k, len, len1, len2, page, ref, siteID, thread, threads;
if (!(board = this.data.boards[boardID])) { siteID = Site.hostname;
if (!(board = this.data[siteID].boards[boardID])) {
return; return;
} }
threads = {}; threads = {};
@ -6013,15 +6032,16 @@ DataBoard = (function() {
} }
} }
} }
this.data.boards[boardID] = threads; this.data[siteID].boards[boardID] = threads;
this.deleteIfEmpty({ this.deleteIfEmpty({
siteID: siteID,
boardID: boardID boardID: boardID
}); });
return $.set(this.key, this.allData); return $.set(this.key, this.data);
}; };
DataBoard.prototype.onSync = function(data) { DataBoard.prototype.onSync = function(data) {
if (!((data.version || 0) > (this.allData.version || 0))) { if (!((data.version || 0) > (this.data.version || 0))) {
return; return;
} }
this.initData(data); this.initData(data);
@ -7262,21 +7282,30 @@ SW = {};
isOPContainerThread: true, isOPContainerThread: true,
disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'], disabledFeatures: ['Board Configuration', 'Normalize URL', 'Captcha Configuration', 'Image Host Rewriting', 'Index Generator', 'Announcement Hiding', 'Fourchan thingies', 'Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Pass Link', 'Index Generator (Menu)', 'Report Link', 'Delete Link', 'Edit Link', 'Archive Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Fappe Tyme', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Unread', 'Quote Threading', 'Thread Stats', 'Thread Updater', 'Mark New IPs', 'Banner', 'Flash Features', 'Reply Pruning'],
detect: function() { detect: function() {
var i, len, ref, script; var i, len, m, properties, ref, root, script;
ref = $$('script:not([src])', d.head); ref = $$('script:not([src])', d.head);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len = ref.length; i < len; i++) {
script = ref[i]; script = ref[i];
if (/\bvar configRoot=".*?"/.test(script.textContent)) { if ((m = script.textContent.match(/\bvar configRoot=(".*?")/))) {
return true; properties = {};
try {
root = JSON.parse(m[1]);
if (root[0] === '/') {
properties.root = location.origin + root;
} else if (/^https?:/.test(root)) {
properties.root = root;
}
} catch (_error) {}
return properties;
} }
} }
return false; return false;
}, },
urls: { urls: {
thread: function(arg) { thread: function(arg) {
var boardID, threadID; var boardID, ref, siteID, threadID;
boardID = arg.boardID, threadID = arg.threadID; siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID;
return location.origin + "/" + boardID + "/res/" + threadID + ".html"; return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/res/" + threadID + ".html";
} }
}, },
selectors: { selectors: {
@ -7566,49 +7595,65 @@ Site = (function() {
var Site; var Site;
Site = { Site = {
init: function(cb) { defaultProperties: {
var hostname, i, len, line, ref, ref1, software, swDict; '4chan.org': {
swDict = {}; software: 'yotsuba'
ref = Conf['siteSoftware'].split('\n'); },
for (i = 0, len = ref.length; i < len; i++) { '4channel.org': {
line = ref[i]; software: 'yotsuba'
if (!(line[0] !== '#')) { },
continue; '4cdn.org': {
} software: 'yotsuba'
ref1 = line.split(' '), hostname = ref1[0], software = ref1[1];
if (software in SW) {
swDict[hostname] = software;
}
}
hostname = location.hostname;
while (hostname && !(hostname in swDict)) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname === '4channel.org') {
hostname = '4chan.org';
}
if (hostname) {
this.set(hostname, swDict[hostname]);
return cb();
} else {
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base;
for (software in SW) {
if (typeof (base = SW[software]).detect === "function" ? base.detect() : void 0) {
_this.set(location.hostname.replace(/^www\./, ''), software);
Conf['siteSoftware'] += "\n" + _this.hostname + " " + _this.software;
$.set('siteSoftware', Conf['siteSoftware']);
cb();
}
}
};
})(this));
} }
}, },
set: function(hostname1, software1) { init: function(cb) {
var hostname;
$.extend(Conf['siteProperties'], Site.defaultProperties);
hostname = location.hostname;
while (hostname && !(hostname in Conf['siteProperties'])) {
hostname = hostname.replace(/^[^.]*\.?/, '');
}
if (hostname && Conf['siteProperties'][hostname].software in SW) {
this.set(hostname);
cb();
}
return $.onExists(doc, 'body', (function(_this) {
return function() {
var base, base1, changed, changes, key, properties, software;
for (software in SW) {
if (!((changes = typeof (base = SW[software]).detect === "function" ? base.detect() : void 0))) {
continue;
}
changes.software = software;
hostname = location.hostname.replace(/^www\./, '');
properties = ((base1 = Conf['siteProperties'])[hostname] || (base1[hostname] = {}));
changed = 0;
for (key in changes) {
if (!(properties[key] !== changes[key])) {
continue;
}
properties[key] = changes[key];
changed++;
}
if (changed) {
$.set('siteProperties', Conf['siteProperties']);
}
if (!_this.hostname) {
_this.set(hostname);
cb();
}
return;
}
};
})(this));
},
set: function(hostname1) {
this.hostname = hostname1; this.hostname = hostname1;
this.software = software1; this.properties = Conf['siteProperties'][this.hostname];
this.software = this.properties.software;
if (this.software === 'yotsuba') {
this.hostname = '4chan.org';
}
return $.extend(this, SW[this.software]); return $.extend(this, SW[this.software]);
} }
}; };
@ -9368,7 +9413,7 @@ Get = (function() {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, ref, ref1; var OP, excerpt, ref, ref1;
OP = thread.OP; OP = thread.OP;
excerpt = ("/" + thread.board + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP)); excerpt = ("/" + (decodeURIComponent(thread.board.ID)) + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP));
if (excerpt.length > 73) { if (excerpt.length > 73) {
return excerpt.slice(0, 70) + "..."; return excerpt.slice(0, 70) + "...";
} }
@ -11950,7 +11995,7 @@ Settings = (function() {
} }
}, },
upgrade: function(data, version) { upgrade: function(data, version) {
var addCSS, addSauces, boardID, changes, compareString, corrupted, j, k, key, len, len1, list, name, record, ref, ref1, ref2, ref3, ref4, ref5, ref6, rice, set, setD, type, uids, val, val2, value; var addCSS, addSauces, boardID, boards, changes, compareString, corrupted, db, hostname, j, k, key, l, lastChecked, len, len1, len2, len3, line, list, m, name, record, ref, ref1, ref10, ref11, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rice, set, setD, siteProperties, software, type, uids, val, val2, value;
changes = {}; changes = {};
set = function(key, value) { set = function(key, value) {
return data[key] = changes[key] = value; return data[key] = changes[key] = value;
@ -12198,6 +12243,34 @@ Settings = (function() {
set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba'); set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba');
} }
} }
if (compareString < '00001.00014.00005.00000') {
ref7 = DataBoard.keys;
for (l = 0, len2 = ref7.length; l < len2; l++) {
db = ref7[l];
if ((ref8 = data[db]) != null ? ref8.boards : void 0) {
ref9 = data[db], boards = ref9.boards, lastChecked = ref9.lastChecked;
data[db]['4chan.org'] = {
boards: boards,
lastChecked: lastChecked
};
delete data[db].boards;
delete data[db].lastChecked;
set(db, data[db]);
}
}
if ((data['siteSoftware'] != null) && (data['siteProperties'] == null)) {
siteProperties = {};
ref10 = data['siteSoftware'].split('\n');
for (m = 0, len3 = ref10.length; m < len3; m++) {
line = ref10[m];
ref11 = line.split(' '), hostname = ref11[0], software = ref11[1];
siteProperties[hostname] = {
software: software
};
}
set('siteProperties', siteProperties);
}
}
return changes; return changes;
}, },
loadSettings: function(data, cb) { loadSettings: function(data, cb) {
@ -19684,7 +19757,7 @@ ThreadWatcher = (function() {
this.refreshButton = $('.refresh', this.dialog); this.refreshButton = $('.refresh', this.dialog);
this.closeButton = $('.move > .close', this.dialog); this.closeButton = $('.move > .close', this.dialog);
this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts'); this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts');
this.unreadEnabled = Conf['Remember Last Read Post'] && Site.software === 'yotsuba'; this.unreadEnabled = Conf['Remember Last Read Post'];
$.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.buttonFetchAll); $.on(this.refreshButton, 'click', this.buttonFetchAll);
@ -19837,27 +19910,28 @@ ThreadWatcher = (function() {
}, },
cb: { cb: {
openAll: function() { openAll: function() {
var a, i, len, ref; var a, i, len1, ref;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = $$('a[title]', ThreadWatcher.list); ref = $$('a[title]', ThreadWatcher.list);
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
a = ref[i]; a = ref[i];
$.open(a.href); $.open(a.href);
} }
return $.event('CloseMenu'); return $.event('CloseMenu');
}, },
pruneDeads: function() { pruneDeads: function() {
var boardID, data, i, len, ref, ref1, threadID; var boardID, data, i, len1, ref, ref1, siteID, threadID;
if ($.hasClass(this, 'disabled')) { if ($.hasClass(this, 'disabled')) {
return; return;
} }
ref = ThreadWatcher.getAll(); ref = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; ref1 = ref[i], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data;
if (data.isDead) { if (data.isDead) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -19872,9 +19946,10 @@ ThreadWatcher = (function() {
return ThreadWatcher.toggle(thread); return ThreadWatcher.toggle(thread);
}, },
rm: function() { rm: function() {
var boardID, ref, threadID; var boardID, ref, siteID, threadID;
siteID = this.parentNode.dataset.siteID;
ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1];
return ThreadWatcher.rm(boardID, +threadID); return ThreadWatcher.rm(siteID, boardID, +threadID);
}, },
post: function(e) { post: function(e) {
var boardID, postID, ref, threadID; var boardID, postID, ref, threadID;
@ -19888,11 +19963,12 @@ ThreadWatcher = (function() {
} }
}, },
onIndexUpdate: function(e) { onIndexUpdate: function(e) {
var boardID, data, db, nKilled, ref, ref1, threadID; var boardID, data, db, nKilled, ref, ref1, siteID, threadID;
db = ThreadWatcher.db; db = ThreadWatcher.db;
siteID = Site.hostname;
boardID = g.BOARD.ID; boardID = g.BOARD.ID;
nKilled = 0; nKilled = 0;
ref = db.data.boards[boardID]; ref = db.data[siteID].boards[boardID];
for (threadID in ref) { for (threadID in ref) {
data = ref[threadID]; data = ref[threadID];
if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) { if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) {
@ -19919,6 +19995,7 @@ ThreadWatcher = (function() {
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
ThreadWatcher.fetchStatus({ ThreadWatcher.fetchStatus({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
@ -19948,9 +20025,9 @@ ThreadWatcher = (function() {
return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin');
}, },
abort: function() { abort: function() {
var i, len, ref, req; var i, len1, ref, req;
ref = ThreadWatcher.requests; ref = ThreadWatcher.requests;
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
req = ref[i]; req = ref[i];
if (req.readyState !== 4) { if (req.readyState !== 4) {
req.abort(); req.abort();
@ -19970,7 +20047,7 @@ ThreadWatcher = (function() {
db = ThreadWatcher.db; db = ThreadWatcher.db;
interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR; interval = ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] ? 5 * $.MINUTE : 2 * $.HOUR;
now = Date.now(); now = Date.now();
if (!((now - interval < (ref = db.data.lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) { if (!((now - interval < (ref = db.data[Site.hostname].lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) {
ThreadWatcher.fetchAllStatus(); ThreadWatcher.fetchAllStatus();
db.setLastChecked(); db.setLastChecked();
} }
@ -19984,7 +20061,7 @@ ThreadWatcher = (function() {
} }
}, },
fetchAllStatus: function() { fetchAllStatus: function() {
var db, dbs, i, len, n, results; var db, dbs, i, len1, n, results;
if (Site.software !== 'yotsuba') { if (Site.software !== 'yotsuba') {
return; return;
} }
@ -19993,13 +20070,13 @@ ThreadWatcher = (function() {
}); });
n = 0; n = 0;
results = []; results = [];
for (i = 0, len = dbs.length; i < len; i++) { for (i = 0, len1 = dbs.length; i < len1; i++) {
db = dbs[i]; db = dbs[i];
results.push(db.forceSync(function() { results.push(db.forceSync(function() {
var j, len1, thread, threads; var j, len2, thread, threads;
if ((++n) === dbs.length) { if ((++n) === dbs.length) {
threads = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (j = 0, len1 = threads.length; j < len1; j++) { for (j = 0, len2 = threads.length; j < len2; j++) {
thread = threads[j]; thread = threads[j];
ThreadWatcher.fetchStatus(thread); ThreadWatcher.fetchStatus(thread);
} }
@ -20009,11 +20086,11 @@ ThreadWatcher = (function() {
return results; return results;
}, },
fetchStatus: function(thread, force) { fetchStatus: function(thread, force) {
var boardID, data, req, threadID; var boardID, data, req, siteID, threadID;
if (Site.software !== 'yotsuba') { siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (!(Site.software === 'yotsuba' && siteID === Site.hostname)) {
return; return;
} }
boardID = thread.boardID, threadID = thread.threadID, data = thread.data;
if (data.isDead && !force) { if (data.isDead && !force) {
return; return;
} }
@ -20032,7 +20109,7 @@ ThreadWatcher = (function() {
return ThreadWatcher.requests.push(req); return ThreadWatcher.requests.push(req);
}, },
parseStatus: function(arg) { parseStatus: function(arg) {
var boardID, data, i, isDead, lastReadPost, len, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP; var boardID, data, i, isDead, lastReadPost, len1, match, postObj, quotesYou, quotingYou, ref, ref1, ref2, regexp, threadID, unread, youOP;
boardID = arg.boardID, threadID = arg.threadID, data = arg.data; boardID = arg.boardID, threadID = arg.threadID, data = arg.data;
ThreadWatcher.fetched++; ThreadWatcher.fetched++;
if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { if (ThreadWatcher.fetched === ThreadWatcher.requests.length) {
@ -20063,7 +20140,7 @@ ThreadWatcher = (function() {
postID: threadID postID: threadID
}) : void 0); }) : void 0);
ref1 = this.response.posts; ref1 = this.response.posts;
for (i = 0, len = ref1.length; i < len; i++) { for (i = 0, len1 = ref1.length; i < len1; i++) {
postObj = ref1[i]; postObj = ref1[i];
if (!(postObj.no > lastReadPost)) { if (!(postObj.no > lastReadPost)) {
continue; continue;
@ -20131,29 +20208,35 @@ ThreadWatcher = (function() {
} }
}, },
getAll: function() { getAll: function() {
var all, boardID, data, ref, threadID, threads; var all, boardID, boards, data, ref, ref1, siteID, threadID, threads;
all = []; all = [];
ref = ThreadWatcher.db.data.boards; ref = ThreadWatcher.db.data;
for (boardID in ref) { for (siteID in ref) {
threads = ref[boardID]; boards = ref[siteID];
if (Conf['Current Board'] && boardID !== g.BOARD.ID) { ref1 = boards.boards;
continue; for (boardID in ref1) {
} threads = ref1[boardID];
for (threadID in threads) { if (Conf['Current Board'] && (siteID !== Site.hostname || boardID !== g.BOARD.ID)) {
data = threads[threadID]; continue;
if (data && typeof data === 'object') { }
all.push({ for (threadID in threads) {
boardID: boardID, data = threads[threadID];
threadID: threadID, if (data && typeof data === 'object') {
data: data all.push({
}); siteID: siteID,
boardID: boardID,
threadID: threadID,
data: data
});
}
} }
} }
} }
return all; return all;
}, },
makeLine: function(boardID, threadID, data) { makeLine: function(siteID, boardID, threadID, data) {
var count, div, excerpt, fullID, link, title, x; var count, div, excerpt, fullID, link, ref, ref1, software, title, x;
software = (ref = Conf['siteProperties'][siteID]) != null ? ref.software : void 0;
x = $.el('a', { x = $.el('a', {
className: 'fa fa-times', className: 'fa fa-times',
href: 'javascript:;' href: 'javascript:;'
@ -20161,15 +20244,19 @@ ThreadWatcher = (function() {
$.on(x, 'click', ThreadWatcher.cb.rm); $.on(x, 'click', ThreadWatcher.cb.rm);
excerpt = data.excerpt; excerpt = data.excerpt;
excerpt || (excerpt = "/" + boardID + "/ - No." + threadID); excerpt || (excerpt = "/" + boardID + "/ - No." + threadID);
if (Conf['Show Site Prefix']) {
excerpt = ThreadWatcher.prefixes[siteID] + excerpt;
}
link = $.el('a', { link = $.el('a', {
href: Site.urls.thread({ href: ((ref1 = SW[software]) != null ? ref1.urls.thread({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}), }) : void 0) || '',
title: excerpt, title: excerpt,
className: 'watcher-link' className: 'watcher-link'
}); });
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && (data.unread != null)) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba' && (data.unread != null)) {
count = $.el('span', { count = $.el('span', {
textContent: "(" + data.unread + ")", textContent: "(" + data.unread + ")",
className: 'watcher-unread' className: 'watcher-unread'
@ -20184,13 +20271,14 @@ ThreadWatcher = (function() {
div = $.el('div'); div = $.el('div');
fullID = boardID + "." + threadID; fullID = boardID + "." + threadID;
div.dataset.fullID = fullID; div.dataset.fullID = fullID;
div.dataset.siteID = siteID;
if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) { if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) {
$.addClass(div, 'current'); $.addClass(div, 'current');
} }
if (data.isDead) { if (data.isDead) {
$.addClass(div, 'dead-thread'); $.addClass(div, 'dead-thread');
} }
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && software === 'yotsuba') {
if (data.unread === 0) { if (data.unread === 0) {
$.addClass(div, 'replies-read'); $.addClass(div, 'replies-read');
} }
@ -20204,13 +20292,43 @@ ThreadWatcher = (function() {
$.add(div, [x, $.tn(' '), link]); $.add(div, [x, $.tn(' '), link]);
return div; return div;
}, },
setPrefixes: function(threads) {
var conflicts, conflicts2, i, j, len, len1, len2, prefix, prefixes, siteID, siteID2;
prefixes = {};
for (i = 0, len1 = threads.length; i < len1; i++) {
siteID = threads[i].siteID;
if (siteID in prefixes) {
continue;
}
len = 0;
prefix = '';
conflicts = Object.keys(prefixes);
while (conflicts.length > 0) {
len++;
prefix = siteID.slice(0, len);
conflicts2 = [];
for (j = 0, len2 = conflicts.length; j < len2; j++) {
siteID2 = conflicts[j];
if (siteID2.slice(0, len) === prefix) {
conflicts2.push(siteID2);
} else if (prefixes[siteID2].length < len) {
prefixes[siteID2] = siteID2.slice(0, len);
}
}
conflicts = conflicts2;
}
prefixes[siteID] = prefix;
}
return ThreadWatcher.prefixes = prefixes;
},
build: function() { build: function() {
var boardID, data, i, j, len, len1, list, nodes, ref, ref1, ref2, refresher, thread, threadID; var boardID, data, i, j, len1, len2, list, nodes, ref, ref1, refresher, siteID, thread, threadID, threads;
nodes = []; nodes = [];
ref = ThreadWatcher.getAll(); threads = ThreadWatcher.getAll();
for (i = 0, len = ref.length; i < len; i++) { ThreadWatcher.setPrefixes(threads);
ref1 = ref[i], boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; for (i = 0, len1 = threads.length; i < len1; i++) {
if ((data.excerpt == null) && (thread = g.threads[boardID + "." + threadID])) { ref = threads[i], siteID = ref.siteID, boardID = ref.boardID, threadID = ref.threadID, data = ref.data;
if ((data.excerpt == null) && siteID === Site.hostname && (thread = g.threads[boardID + "." + threadID])) {
ThreadWatcher.db.extend({ ThreadWatcher.db.extend({
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
@ -20219,26 +20337,26 @@ ThreadWatcher = (function() {
} }
}); });
} }
nodes.push(ThreadWatcher.makeLine(boardID, threadID, data)); nodes.push(ThreadWatcher.makeLine(siteID, boardID, threadID, data));
} }
list = ThreadWatcher.list; list = ThreadWatcher.list;
$.rmAll(list); $.rmAll(list);
$.add(list, nodes); $.add(list, nodes);
ThreadWatcher.refreshIcon(); ThreadWatcher.refreshIcon();
ref2 = ThreadWatcher.menu.refreshers; ref1 = ThreadWatcher.menu.refreshers;
for (j = 0, len1 = ref2.length; j < len1; j++) { for (j = 0, len2 = ref1.length; j < len2; j++) {
refresher = ref2[j]; refresher = ref1[j];
refresher(); refresher();
} }
}, },
refresh: function() { refresh: function() {
ThreadWatcher.build(); ThreadWatcher.build();
g.threads.forEach(function(thread) { g.threads.forEach(function(thread) {
var i, isWatched, len, post, ref, toggler; var i, isWatched, len1, post, ref, toggler;
isWatched = ThreadWatcher.isWatched(thread); isWatched = ThreadWatcher.isWatched(thread);
if (thread.OP) { if (thread.OP) {
ref = [thread.OP].concat(slice.call(thread.OP.clones)); ref = [thread.OP].concat(slice.call(thread.OP.clones));
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
post = ref[i]; post = ref[i];
if ((toggler = $('.watch-thread-link', post.nodes.info))) { if ((toggler = $('.watch-thread-link', post.nodes.info))) {
ThreadWatcher.setToggler(toggler, isWatched); ThreadWatcher.setToggler(toggler, isWatched);
@ -20256,15 +20374,16 @@ ThreadWatcher = (function() {
} }
}, },
refreshIcon: function() { refreshIcon: function() {
var className, i, len, ref; var className, i, len1, ref;
ref = ['replies-unread', 'replies-quoting-you']; ref = ['replies-unread', 'replies-quoting-you'];
for (i = 0, len = ref.length; i < len; i++) { for (i = 0, len1 = ref.length; i < len1; i++) {
className = ref[i]; className = ref[i];
ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog));
} }
}, },
update: function(boardID, threadID, newData) { update: function(boardID, threadID, newData) {
var data, key, line, n, newLine, ref, val; var data, key, line, n, newLine, ref, siteID, val;
siteID = Site.hostname;
if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
@ -20300,8 +20419,8 @@ ThreadWatcher = (function() {
threadID: threadID, threadID: threadID,
val: newData val: newData
}); });
if (line = $("#watched-threads > [data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) { if (line = $("#watched-threads > [data-site-i-d='" + siteID + "'][data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog)) {
newLine = ThreadWatcher.makeLine(boardID, threadID, data); newLine = ThreadWatcher.makeLine(siteID, boardID, threadID, data);
$.replace(line, newLine); $.replace(line, newLine);
return ThreadWatcher.refreshIcon(); return ThreadWatcher.refreshIcon();
} else { } else {
@ -20336,21 +20455,23 @@ ThreadWatcher = (function() {
}, cb); }, cb);
}, },
toggle: function(thread) { toggle: function(thread) {
var boardID, threadID; var boardID, siteID, threadID;
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (ThreadWatcher.db.get({ if (ThreadWatcher.db.get({
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
return ThreadWatcher.rm(boardID, threadID); return ThreadWatcher.rm(siteID, boardID, threadID);
} else { } else {
return ThreadWatcher.add(thread); return ThreadWatcher.add(thread);
} }
}, },
add: function(thread) { add: function(thread) {
var boardID, data, threadID; var boardID, data, siteID, threadID;
data = {}; data = {};
siteID = Site.hostname;
boardID = thread.board.ID; boardID = thread.board.ID;
threadID = thread.ID; threadID = thread.ID;
if (thread.isDead) { if (thread.isDead) {
@ -20358,7 +20479,7 @@ ThreadWatcher = (function() {
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
})) { })) {
ThreadWatcher.rm(boardID, threadID); ThreadWatcher.rm(siteID, boardID, threadID);
return; return;
} }
data.isDead = true; data.isDead = true;
@ -20375,14 +20496,16 @@ ThreadWatcher = (function() {
ThreadWatcher.refresh(); ThreadWatcher.refresh();
if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) {
return ThreadWatcher.fetchStatus({ return ThreadWatcher.fetchStatus({
siteID: Site.hostname,
boardID: boardID, boardID: boardID,
threadID: threadID, threadID: threadID,
data: data data: data
}, true); }, true);
} }
}, },
rm: function(boardID, threadID) { rm: function(siteID, boardID, threadID) {
ThreadWatcher.db["delete"]({ ThreadWatcher.db["delete"]({
siteID: siteID,
boardID: boardID, boardID: boardID,
threadID: threadID threadID: threadID
}); });
@ -20425,7 +20548,7 @@ ThreadWatcher = (function() {
}); });
}, },
addMenuEntries: function() { addMenuEntries: function() {
var cb, conf, entries, entry, i, len, name, ref, ref1, refresh, subEntries; var cb, conf, entries, entry, i, len1, name, ref, ref1, refresh, subEntries;
entries = []; entries = [];
entries.push({ entries.push({
cb: ThreadWatcher.cb.openAll, cb: ThreadWatcher.cb.openAll,
@ -20463,7 +20586,7 @@ ThreadWatcher = (function() {
subEntries: subEntries subEntries: subEntries
} }
}); });
for (i = 0, len = entries.length; i < len; i++) { for (i = 0, len1 = entries.length; i < len1; i++) {
ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh; ref1 = entries[i], entry = ref1.entry, cb = ref1.cb, refresh = ref1.refresh;
if (entry.el.nodeName === 'A') { if (entry.el.nodeName === 'A') {
entry.el.href = 'javascript:;'; entry.el.href = 'javascript:;';
@ -20491,7 +20614,7 @@ ThreadWatcher = (function() {
entry.el.title += '\n[Remember Last Read Post is disabled.]'; entry.el.title += '\n[Remember Last Read Post is disabled.]';
} }
$.on(input, 'change', $.cb.checked); $.on(input, 'change', $.cb.checked);
if (name === 'Current Board' || name === 'Show Unread Count') { if (name === 'Current Board' || name === 'Show Unread Count' || name === 'Show Site Prefix') {
$.on(input, 'change', ThreadWatcher.refresh); $.on(input, 'change', ThreadWatcher.refresh);
} }
if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') { if (name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') {
@ -24966,6 +25089,7 @@ Main = (function() {
for (i = k = 0; k < 2; i = ++k) { for (i = k = 0; k < 2; i = ++k) {
Conf["Last Long Reply Thresholds " + i] = {}; Conf["Last Long Reply Thresholds " + i] = {};
} }
Conf['siteProperties'] = {};
Conf['Except Archives from Encryption'] = false; Conf['Except Archives from Encryption'] = false;
Conf['JSON Navigation'] = true; Conf['JSON Navigation'] = true;
Conf['Oekaki Links'] = true; Conf['Oekaki Links'] = true;
@ -24973,6 +25097,7 @@ Main = (function() {
Conf['QR Shortcut'] = true; Conf['QR Shortcut'] = true;
Conf['Bottom QR Link'] = true; Conf['Bottom QR Link'] = true;
Conf['Toggleable Thread Watcher'] = true; Conf['Toggleable Thread Watcher'] = true;
Conf['siteSoftware'] = '';
if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) { if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !$$('script:not([src])', d).filter(function(s) {
return /this\[/.test(s.textContent); return /this\[/.test(s.textContent);
}).length) { }).length) {
@ -25272,7 +25397,7 @@ Main = (function() {
ref = $$(s.thread, board); ref = $$(s.thread, board);
for (j = 0, len = ref.length; j < len; j++) { for (j = 0, len = ref.length; j < len; j++) {
threadRoot = ref[j]; threadRoot = ref[j];
boardObj = (boardID = threadRoot.dataset.board) ? g.boards[boardID] || new Board(boardID) : g.BOARD; boardObj = (boardID = threadRoot.dataset.board) ? (boardID = encodeURIComponent(boardID), g.boards[boardID] || new Board(boardID)) : g.BOARD;
thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj); thread = new Thread(+threadRoot.id.match(/\d*$/)[0], boardObj);
thread.nodes.root = threadRoot; thread.nodes.root = threadRoot;
threads.push(thread); threads.push(thread);

Binary file not shown.

View File

@ -3,7 +3,7 @@
"4chan-x@4chan-x.net": { "4chan-x@4chan-x.net": {
"updates": [ "updates": [
{ {
"version": "1.14.4.7", "version": "1.14.5.0",
"update_link": "https://www.4chan-x.net/builds/4chan-X-beta.crx" "update_link": "https://www.4chan-x.net/builds/4chan-X-beta.crx"
} }
] ]

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://www.4chan-x.net/builds/4chan-X-beta.crx' version='1.14.4.7' /> <updatecheck codebase='https://www.4chan-x.net/builds/4chan-X-beta.crx' version='1.14.5.0' />
</app> </app>
</gupdate> </gupdate>

View File

@ -3,7 +3,7 @@
"4chan-x@4chan-x.net": { "4chan-x@4chan-x.net": {
"updates": [ "updates": [
{ {
"version": "1.14.4.7", "version": "1.14.5.0",
"update_link": "https://www.4chan-x.net/builds/4chan-X.crx" "update_link": "https://www.4chan-x.net/builds/4chan-X.crx"
} }
] ]

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://www.4chan-x.net/builds/4chan-X.crx' version='1.14.4.7' /> <updatecheck codebase='https://www.4chan-x.net/builds/4chan-X.crx' version='1.14.5.0' />
</app> </app>
</gupdate> </gupdate>

View File

@ -1,4 +1,4 @@
{ {
"version": "1.14.4.7", "version": "1.14.5.0",
"date": "2018-12-04T00:46:24.294Z" "date": "2018-12-06T04:19:59.545Z"
} }