Merge branch 'v3'
Conflicts: LICENSE builds/appchan-x.user.js builds/crx/script.js
This commit is contained in:
commit
bde16c1a64
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* appchan x - Version 2.7.5 - 2014-01-04
|
* appchan x - Version 2.7.5 - 2014-01-06
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* appchan x - Version 2.7.5 - 2014-01-04
|
* appchan x - Version 2.7.5 - 2014-01-06
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
@ -110,7 +110,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Color, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
|
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Color, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
|
||||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||||
__slice = [].slice,
|
__slice = [].slice,
|
||||||
__hasProp = {}.hasOwnProperty,
|
__hasProp = {}.hasOwnProperty,
|
||||||
@ -3825,6 +3825,99 @@
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
RandomAccessList = (function() {
|
||||||
|
function RandomAccessList() {
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomAccessList.prototype.push = function(item) {
|
||||||
|
var ID, last;
|
||||||
|
ID = item.ID;
|
||||||
|
if (this[ID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last = this.last;
|
||||||
|
item.prev = last;
|
||||||
|
this[ID] = item;
|
||||||
|
this.last = last ? last.next = item : this.first = item;
|
||||||
|
return this.length++;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.after = function(root, item) {
|
||||||
|
var next;
|
||||||
|
if (item.prev === root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rmi(item);
|
||||||
|
next = root.next;
|
||||||
|
root.next = item;
|
||||||
|
item.prev = root;
|
||||||
|
item.next = next;
|
||||||
|
return next.prev = item;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.prepend = function(item) {
|
||||||
|
var first;
|
||||||
|
first = this.first;
|
||||||
|
if (item === first || !this[item.ID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rmi(item);
|
||||||
|
item.next = first;
|
||||||
|
first.prev = item;
|
||||||
|
this.first = item;
|
||||||
|
return delete item.prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.shift = function() {
|
||||||
|
return this.rm(this.first.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.rm = function(ID) {
|
||||||
|
var item;
|
||||||
|
item = this[ID];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete this[ID];
|
||||||
|
this.length--;
|
||||||
|
this.rmi(item);
|
||||||
|
delete item.next;
|
||||||
|
return delete item.prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.rmi = function(item) {
|
||||||
|
var next, prev;
|
||||||
|
prev = item.prev, next = item.next;
|
||||||
|
if (prev) {
|
||||||
|
prev.next = next;
|
||||||
|
} else {
|
||||||
|
this.first = next;
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
return next.prev = prev;
|
||||||
|
} else {
|
||||||
|
return this.last = prev;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.closest = function(ID) {
|
||||||
|
var item, prev;
|
||||||
|
item = this.first;
|
||||||
|
while (item) {
|
||||||
|
if (item.ID > ID) {
|
||||||
|
prev = item.prev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
item = item.next;
|
||||||
|
}
|
||||||
|
return (prev ? prev.ID : -1);
|
||||||
|
};
|
||||||
|
|
||||||
|
return RandomAccessList;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
Polyfill = {
|
Polyfill = {
|
||||||
init: function() {},
|
init: function() {},
|
||||||
notificationPermission: function() {
|
notificationPermission: function() {
|
||||||
@ -7126,108 +7219,120 @@
|
|||||||
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
||||||
});
|
});
|
||||||
input = $('input', this.controls);
|
input = $('input', this.controls);
|
||||||
$.on(input, 'change', QuoteThreading.toggle);
|
$.on(input, 'change', this.toggle);
|
||||||
$.event('AddMenuEntry', {
|
$.event('AddMenuEntry', {
|
||||||
type: 'header',
|
type: 'header',
|
||||||
el: this.controls,
|
el: this.controls,
|
||||||
order: 98
|
order: 98
|
||||||
});
|
});
|
||||||
$.on(d, '4chanXInitFinished', this.setup);
|
if (!Conf['Unread Count']) {
|
||||||
|
$.on(d, '4chanXInitFinished', this.setup);
|
||||||
|
}
|
||||||
return Post.callbacks.push({
|
return Post.callbacks.push({
|
||||||
name: 'Quote Threading',
|
name: 'Quote Threading',
|
||||||
cb: this.node
|
cb: this.node
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setup: function() {
|
setup: function() {
|
||||||
var ID, post, posts;
|
var ID, post, _ref;
|
||||||
$.off(d, '4chanXInitFinished', QuoteThreading.setup);
|
$.off(d, '4chanXInitFinished', QuoteThreading.setup);
|
||||||
posts = g.posts;
|
_ref = g.posts;
|
||||||
for (ID in posts) {
|
for (ID in _ref) {
|
||||||
post = posts[ID];
|
post = _ref[ID];
|
||||||
if (post.cb) {
|
if (post.cb) {
|
||||||
post.cb.call(post);
|
post.cb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QuoteThreading.hasRun = true;
|
return QuoteThreading.hasRun = true;
|
||||||
},
|
},
|
||||||
node: function() {
|
node: function() {
|
||||||
var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len;
|
var keys, len, post, posts, quote, _i, _len, _ref;
|
||||||
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
|
||||||
posts = g.posts;
|
posts = g.posts;
|
||||||
if (!(post = posts[fullID]) || post.isHidden) {
|
if (this.isClone || !QuoteThreading.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uniq = {};
|
if (Conf['Unread Count']) {
|
||||||
len = ("" + g.BOARD).length + 1;
|
Unread.posts.push(this);
|
||||||
for (_i = 0, _len = quotes.length; _i < _len; _i++) {
|
}
|
||||||
quote = quotes[_i];
|
if (this.thread.OP === this || !(post = posts[this.fullID]) || post.isHidden) {
|
||||||
qid = quote;
|
return;
|
||||||
if (!(qid.slice(len) < ID)) {
|
}
|
||||||
continue;
|
keys = [];
|
||||||
}
|
len = g.BOARD.ID.length + 1;
|
||||||
if (qid in posts) {
|
_ref = this.quotes;
|
||||||
uniq[qid.slice(len)] = true;
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
quote = _ref[_i];
|
||||||
|
if ((quote.slice(len) < this.ID) && quote in posts) {
|
||||||
|
keys.push(quote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys = Object.keys(uniq);
|
|
||||||
if (keys.length !== 1) {
|
if (keys.length !== 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.threaded = "" + g.BOARD + "." + keys[0];
|
this.threaded = keys[0];
|
||||||
return this.cb = QuoteThreading.nodeinsert;
|
return this.cb = QuoteThreading.nodeinsert;
|
||||||
},
|
},
|
||||||
nodeinsert: function() {
|
nodeinsert: function() {
|
||||||
var bottom, height, qpost, qroot, threadContainer, top, _ref;
|
var ID, bottom, height, post, posts, root, threadContainer, top, _ref;
|
||||||
qpost = g.posts[this.threaded];
|
post = g.posts[this.threaded];
|
||||||
delete this.threaded;
|
posts = Unread.posts;
|
||||||
delete this.cb;
|
if (this.thread.OP === post) {
|
||||||
if (this.thread.OP === qpost) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (QuoteThreading.hasRun) {
|
if (QuoteThreading.hasRun) {
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
_ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
||||||
if (!(__indexOf.call(Unread.posts, qpost) >= 0 || ((bottom < height) && (top > 0)))) {
|
if (!((posts != null ? posts[post.ID] : void 0) || ((bottom < height) && (top > 0)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qroot = qpost.nodes.root;
|
root = post.nodes.root;
|
||||||
if (!$.hasClass(qroot, 'threadOP')) {
|
if (!$.hasClass(root, 'threadOP')) {
|
||||||
$.addClass(qroot, 'threadOP');
|
$.addClass(root, 'threadOP');
|
||||||
threadContainer = $.el('div', {
|
threadContainer = $.el('div', {
|
||||||
className: 'threadContainer'
|
className: 'threadContainer'
|
||||||
});
|
});
|
||||||
$.after(qroot, threadContainer);
|
$.after(root, threadContainer);
|
||||||
} else {
|
} else {
|
||||||
threadContainer = qroot.nextSibling;
|
threadContainer = root.nextSibling;
|
||||||
|
post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer));
|
||||||
}
|
}
|
||||||
$.add(threadContainer, this.nodes.root);
|
$.add(threadContainer, this.nodes.root);
|
||||||
|
if (!Conf['Unread Count']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (posts[post.ID]) {
|
||||||
|
posts.after(post, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((ID = posts.closest(post.ID)) !== -1) {
|
||||||
|
posts.after(posts[ID], this);
|
||||||
|
} else {
|
||||||
|
posts.prepend(this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
var container, containers, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||||
|
if (Conf['Unread Count']) {
|
||||||
|
Unread.posts = new RandomAccessList;
|
||||||
|
Unread.ready();
|
||||||
|
}
|
||||||
thread = $('.thread');
|
thread = $('.thread');
|
||||||
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
||||||
QuoteThreading.enabled = this.checked;
|
if (QuoteThreading.enabled = this.checked) {
|
||||||
if (this.checked) {
|
|
||||||
QuoteThreading.hasRun = false;
|
QuoteThreading.hasRun = false;
|
||||||
for (_i = 0, _len = replies.length; _i < _len; _i++) {
|
for (_i = 0, _len = replies.length; _i < _len; _i++) {
|
||||||
reply = replies[_i];
|
reply = replies[_i];
|
||||||
QuoteThreading.node.call(node = Get.postFromRoot(reply));
|
post = Get.postFromRoot(reply);
|
||||||
if (node.cb) {
|
if (post.cb) {
|
||||||
node.cb();
|
post.cb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QuoteThreading.hasRun = true;
|
QuoteThreading.hasRun = true;
|
||||||
} else {
|
} else {
|
||||||
replies.sort(function(a, b) {
|
replies.sort(function(a, b) {
|
||||||
var aID, bID;
|
return Number(a.id.slice(2)) - Number(b.id.slice(2));
|
||||||
aID = Number(a.id.slice(2));
|
|
||||||
bID = Number(b.id.slice(2));
|
|
||||||
return aID - bID;
|
|
||||||
});
|
});
|
||||||
$.add(thread, replies);
|
$.add(thread, replies);
|
||||||
containers = $$('.threadContainer', thread);
|
containers = $$('.threadContainer', thread);
|
||||||
@ -7241,12 +7346,15 @@
|
|||||||
$.rmClass(post, 'threadOP');
|
$.rmClass(post, 'threadOP');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Unread.update(true);
|
if (Conf['Unread Count']) {
|
||||||
|
return Unread.read();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
kb: function() {
|
kb: function() {
|
||||||
var control;
|
var control;
|
||||||
control = $.id('threadingControl');
|
control = $.id('threadingControl');
|
||||||
return control.click();
|
control.checked = !control.checked;
|
||||||
|
return QuoteThreading.toggle.call(control);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11168,7 +11276,7 @@
|
|||||||
}
|
}
|
||||||
root = post.nodes.root;
|
root = post.nodes.root;
|
||||||
if (post.cb) {
|
if (post.cb) {
|
||||||
if (!post.cb.call(post)) {
|
if (!post.cb()) {
|
||||||
$.add(ThreadUpdater.root, root);
|
$.add(ThreadUpdater.root, root);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -11698,8 +11806,19 @@
|
|||||||
this.hr = $.el('hr', {
|
this.hr = $.el('hr', {
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
});
|
});
|
||||||
this.posts = [];
|
this.posts = new RandomAccessList;
|
||||||
this.postsQuotingYou = [];
|
this.postsQuotingYou = [];
|
||||||
|
this.qr = QR.db ? function(post) {
|
||||||
|
var data;
|
||||||
|
data = {
|
||||||
|
boardID: post.board.ID,
|
||||||
|
threadID: post.thread.ID,
|
||||||
|
postID: post.ID
|
||||||
|
};
|
||||||
|
return (QR.db.get(data) ? true : false);
|
||||||
|
} : function() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
return Thread.callbacks.push({
|
return Thread.callbacks.push({
|
||||||
name: 'Unread',
|
name: 'Unread',
|
||||||
cb: this.node
|
cb: this.node
|
||||||
@ -11732,17 +11851,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unread.addPosts(posts);
|
Unread.addPosts(posts);
|
||||||
return Unread.scroll();
|
if (Conf['Quote Threading']) {
|
||||||
|
QuoteThreading.setup();
|
||||||
|
}
|
||||||
|
if (Conf['Scroll to Last Read Post']) {
|
||||||
|
return Unread.scroll();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var down, hash, post, posts, root;
|
var down, hash, post, posts, root;
|
||||||
if (!Conf['Scroll to Last Read Post']) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (post = Unread.posts[0]) {
|
if (post = Unread.posts.first) {
|
||||||
while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) {
|
while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) {
|
||||||
if (!(post = Get.postFromRoot(root)).isHidden) {
|
if (!(post = Get.postFromRoot(root)).isHidden) {
|
||||||
break;
|
break;
|
||||||
@ -11761,7 +11882,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var ID, lastReadPost, post;
|
||||||
lastReadPost = Unread.db.get({
|
lastReadPost = Unread.db.get({
|
||||||
boardID: Unread.thread.board.ID,
|
boardID: Unread.thread.board.ID,
|
||||||
threadID: Unread.thread.ID,
|
threadID: Unread.thread.ID,
|
||||||
@ -11771,7 +11892,14 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Unread.lastReadPost = lastReadPost;
|
Unread.lastReadPost = lastReadPost;
|
||||||
Unread.readArray(Unread.posts);
|
post = Unread.posts.first;
|
||||||
|
while (post) {
|
||||||
|
if ((ID = post.ID, post) > Unread.lastReadPost) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
post = post.next;
|
||||||
|
Unread.posts.rm(ID);
|
||||||
|
}
|
||||||
Unread.readArray(Unread.postsQuotingYou);
|
Unread.readArray(Unread.postsQuotingYou);
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine();
|
Unread.setLine();
|
||||||
@ -11779,28 +11907,20 @@
|
|||||||
return Unread.update();
|
return Unread.update();
|
||||||
},
|
},
|
||||||
addPosts: function(posts) {
|
addPosts: function(posts) {
|
||||||
var ID, data, post, _i, _len, _ref;
|
var ID, post, _i, _len, _ref;
|
||||||
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
||||||
post = posts[_i];
|
post = posts[_i];
|
||||||
ID = post.ID;
|
ID = post.ID;
|
||||||
if (ID <= Unread.lastReadPost || post.isHidden) {
|
if (ID <= Unread.lastReadPost || post.isHidden || Unread.qr(post)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (QR.db) {
|
if (!(post.prev || post.next)) {
|
||||||
data = {
|
Unread.posts.push(post);
|
||||||
boardID: post.board.ID,
|
|
||||||
threadID: post.thread.ID,
|
|
||||||
postID: post.ID
|
|
||||||
};
|
|
||||||
if (QR.db.get(data)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Unread.posts.push(post);
|
|
||||||
Unread.addPostQuotingYou(post);
|
Unread.addPostQuotingYou(post);
|
||||||
}
|
}
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine((_ref = Unread.posts[0], __indexOf.call(posts, _ref) >= 0));
|
Unread.setLine((_ref = Unread.posts.first, __indexOf.call(posts, _ref) >= 0));
|
||||||
}
|
}
|
||||||
Unread.read();
|
Unread.read();
|
||||||
return Unread.update();
|
return Unread.update();
|
||||||
@ -11849,15 +11969,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
readSinglePost: function(post) {
|
readSinglePost: function(post) {
|
||||||
var i;
|
var ID, i;
|
||||||
if ((i = Unread.posts.indexOf(post)) === -1) {
|
ID = post.ID;
|
||||||
|
if (!Unread.posts[ID]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Unread.posts.splice(i, 1);
|
if (post === Unread.posts.first) {
|
||||||
if (i === 0) {
|
Unread.lastReadPost = ID;
|
||||||
Unread.lastReadPost = post.ID;
|
|
||||||
Unread.saveLastReadPost();
|
Unread.saveLastReadPost();
|
||||||
}
|
}
|
||||||
|
Unread.posts.rm(ID);
|
||||||
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
||||||
Unread.postsQuotingYou.splice(i, 1);
|
Unread.postsQuotingYou.splice(i, 1);
|
||||||
}
|
}
|
||||||
@ -11873,35 +11994,22 @@
|
|||||||
}
|
}
|
||||||
return arr.splice(0, i);
|
return arr.splice(0, i);
|
||||||
},
|
},
|
||||||
read: $.debounce(50, function(e) {
|
read: $.debounce(100, function(e) {
|
||||||
var ID, height, i, post, posts;
|
var ID, height, post, posts;
|
||||||
if (d.hidden || !Unread.posts.length) {
|
if (d.hidden || !Unread.posts.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
posts = Unread.posts;
|
posts = Unread.posts;
|
||||||
i = 0;
|
while (post = posts.first) {
|
||||||
while (post = posts[i]) {
|
if (!(Header.getBottomOf(post.nodes.root) > -1)) {
|
||||||
if (Header.getBottomOf(post.nodes.root) > -1) {
|
break;
|
||||||
ID = post.ID;
|
}
|
||||||
if (Conf['Mark Quotes of You']) {
|
ID = post.ID;
|
||||||
if (post.info.yours) {
|
posts.rm(ID);
|
||||||
QuoteYou.lastRead = post.nodes.root;
|
if (Conf['Mark Quotes of You'] && post.info.yours) {
|
||||||
}
|
QuoteYou.lastRead = post.nodes.root;
|
||||||
}
|
|
||||||
if (Conf['Quote Threading']) {
|
|
||||||
posts.splice(i, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!Conf['Quote Threading']) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i && !Conf['Quote Threading']) {
|
|
||||||
posts.splice(0, i);
|
|
||||||
}
|
}
|
||||||
if (!ID) {
|
if (!ID) {
|
||||||
return;
|
return;
|
||||||
@ -11930,7 +12038,7 @@
|
|||||||
if (!(d.hidden || force === true)) {
|
if (!(d.hidden || force === true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(post = Unread.posts[0])) {
|
if (!(post = Unread.posts.first)) {
|
||||||
return $.rm(Unread.hr);
|
return $.rm(Unread.hr);
|
||||||
}
|
}
|
||||||
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root)) {
|
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root)) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Generated by CoffeeScript
|
// Generated by CoffeeScript
|
||||||
/*
|
/*
|
||||||
* appchan x - Version 2.7.5 - 2014-01-04
|
* appchan x - Version 2.7.5 - 2014-01-06
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
@ -88,7 +88,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Color, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
|
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Color, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, GlobalMessage, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, JSColor, Keybinds, Linkify, Main, MascotTools, Mascots, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Rice, Sauce, Settings, Style, ThemeTools, Themes, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, editMascot, editTheme, g, userNavigation,
|
||||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||||
__slice = [].slice,
|
__slice = [].slice,
|
||||||
__hasProp = {}.hasOwnProperty,
|
__hasProp = {}.hasOwnProperty,
|
||||||
@ -3832,6 +3832,99 @@
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
RandomAccessList = (function() {
|
||||||
|
function RandomAccessList() {
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomAccessList.prototype.push = function(item) {
|
||||||
|
var ID, last;
|
||||||
|
ID = item.ID;
|
||||||
|
if (this[ID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last = this.last;
|
||||||
|
item.prev = last;
|
||||||
|
this[ID] = item;
|
||||||
|
this.last = last ? last.next = item : this.first = item;
|
||||||
|
return this.length++;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.after = function(root, item) {
|
||||||
|
var next;
|
||||||
|
if (item.prev === root) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rmi(item);
|
||||||
|
next = root.next;
|
||||||
|
root.next = item;
|
||||||
|
item.prev = root;
|
||||||
|
item.next = next;
|
||||||
|
return next.prev = item;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.prepend = function(item) {
|
||||||
|
var first;
|
||||||
|
first = this.first;
|
||||||
|
if (item === first || !this[item.ID]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rmi(item);
|
||||||
|
item.next = first;
|
||||||
|
first.prev = item;
|
||||||
|
this.first = item;
|
||||||
|
return delete item.prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.shift = function() {
|
||||||
|
return this.rm(this.first.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.rm = function(ID) {
|
||||||
|
var item;
|
||||||
|
item = this[ID];
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete this[ID];
|
||||||
|
this.length--;
|
||||||
|
this.rmi(item);
|
||||||
|
delete item.next;
|
||||||
|
return delete item.prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.rmi = function(item) {
|
||||||
|
var next, prev;
|
||||||
|
prev = item.prev, next = item.next;
|
||||||
|
if (prev) {
|
||||||
|
prev.next = next;
|
||||||
|
} else {
|
||||||
|
this.first = next;
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
return next.prev = prev;
|
||||||
|
} else {
|
||||||
|
return this.last = prev;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.closest = function(ID) {
|
||||||
|
var item, prev;
|
||||||
|
item = this.first;
|
||||||
|
while (item) {
|
||||||
|
if (item.ID > ID) {
|
||||||
|
prev = item.prev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
item = item.next;
|
||||||
|
}
|
||||||
|
return (prev ? prev.ID : -1);
|
||||||
|
};
|
||||||
|
|
||||||
|
return RandomAccessList;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
Polyfill = {
|
Polyfill = {
|
||||||
init: function() {
|
init: function() {
|
||||||
this.notificationPermission();
|
this.notificationPermission();
|
||||||
@ -7130,108 +7223,120 @@
|
|||||||
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
||||||
});
|
});
|
||||||
input = $('input', this.controls);
|
input = $('input', this.controls);
|
||||||
$.on(input, 'change', QuoteThreading.toggle);
|
$.on(input, 'change', this.toggle);
|
||||||
$.event('AddMenuEntry', {
|
$.event('AddMenuEntry', {
|
||||||
type: 'header',
|
type: 'header',
|
||||||
el: this.controls,
|
el: this.controls,
|
||||||
order: 98
|
order: 98
|
||||||
});
|
});
|
||||||
$.on(d, '4chanXInitFinished', this.setup);
|
if (!Conf['Unread Count']) {
|
||||||
|
$.on(d, '4chanXInitFinished', this.setup);
|
||||||
|
}
|
||||||
return Post.callbacks.push({
|
return Post.callbacks.push({
|
||||||
name: 'Quote Threading',
|
name: 'Quote Threading',
|
||||||
cb: this.node
|
cb: this.node
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setup: function() {
|
setup: function() {
|
||||||
var ID, post, posts;
|
var ID, post, _ref;
|
||||||
$.off(d, '4chanXInitFinished', QuoteThreading.setup);
|
$.off(d, '4chanXInitFinished', QuoteThreading.setup);
|
||||||
posts = g.posts;
|
_ref = g.posts;
|
||||||
for (ID in posts) {
|
for (ID in _ref) {
|
||||||
post = posts[ID];
|
post = _ref[ID];
|
||||||
if (post.cb) {
|
if (post.cb) {
|
||||||
post.cb.call(post);
|
post.cb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QuoteThreading.hasRun = true;
|
return QuoteThreading.hasRun = true;
|
||||||
},
|
},
|
||||||
node: function() {
|
node: function() {
|
||||||
var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len;
|
var keys, len, post, posts, quote, _i, _len, _ref;
|
||||||
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
|
||||||
posts = g.posts;
|
posts = g.posts;
|
||||||
if (!(post = posts[fullID]) || post.isHidden) {
|
if (this.isClone || !QuoteThreading.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uniq = {};
|
if (Conf['Unread Count']) {
|
||||||
len = ("" + g.BOARD).length + 1;
|
Unread.posts.push(this);
|
||||||
for (_i = 0, _len = quotes.length; _i < _len; _i++) {
|
}
|
||||||
quote = quotes[_i];
|
if (this.thread.OP === this || !(post = posts[this.fullID]) || post.isHidden) {
|
||||||
qid = quote;
|
return;
|
||||||
if (!(qid.slice(len) < ID)) {
|
}
|
||||||
continue;
|
keys = [];
|
||||||
}
|
len = g.BOARD.ID.length + 1;
|
||||||
if (qid in posts) {
|
_ref = this.quotes;
|
||||||
uniq[qid.slice(len)] = true;
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
quote = _ref[_i];
|
||||||
|
if ((quote.slice(len) < this.ID) && quote in posts) {
|
||||||
|
keys.push(quote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys = Object.keys(uniq);
|
|
||||||
if (keys.length !== 1) {
|
if (keys.length !== 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.threaded = "" + g.BOARD + "." + keys[0];
|
this.threaded = keys[0];
|
||||||
return this.cb = QuoteThreading.nodeinsert;
|
return this.cb = QuoteThreading.nodeinsert;
|
||||||
},
|
},
|
||||||
nodeinsert: function() {
|
nodeinsert: function() {
|
||||||
var bottom, height, qpost, qroot, threadContainer, top, _ref;
|
var ID, bottom, height, post, posts, root, threadContainer, top, _ref;
|
||||||
qpost = g.posts[this.threaded];
|
post = g.posts[this.threaded];
|
||||||
delete this.threaded;
|
posts = Unread.posts;
|
||||||
delete this.cb;
|
if (this.thread.OP === post) {
|
||||||
if (this.thread.OP === qpost) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (QuoteThreading.hasRun) {
|
if (QuoteThreading.hasRun) {
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
_ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
||||||
if (!(__indexOf.call(Unread.posts, qpost) >= 0 || ((bottom < height) && (top > 0)))) {
|
if (!((posts != null ? posts[post.ID] : void 0) || ((bottom < height) && (top > 0)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qroot = qpost.nodes.root;
|
root = post.nodes.root;
|
||||||
if (!$.hasClass(qroot, 'threadOP')) {
|
if (!$.hasClass(root, 'threadOP')) {
|
||||||
$.addClass(qroot, 'threadOP');
|
$.addClass(root, 'threadOP');
|
||||||
threadContainer = $.el('div', {
|
threadContainer = $.el('div', {
|
||||||
className: 'threadContainer'
|
className: 'threadContainer'
|
||||||
});
|
});
|
||||||
$.after(qroot, threadContainer);
|
$.after(root, threadContainer);
|
||||||
} else {
|
} else {
|
||||||
threadContainer = qroot.nextSibling;
|
threadContainer = root.nextSibling;
|
||||||
|
post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer));
|
||||||
}
|
}
|
||||||
$.add(threadContainer, this.nodes.root);
|
$.add(threadContainer, this.nodes.root);
|
||||||
|
if (!Conf['Unread Count']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (posts[post.ID]) {
|
||||||
|
posts.after(post, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((ID = posts.closest(post.ID)) !== -1) {
|
||||||
|
posts.after(posts[ID], this);
|
||||||
|
} else {
|
||||||
|
posts.prepend(this);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
var container, containers, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||||
|
if (Conf['Unread Count']) {
|
||||||
|
Unread.posts = new RandomAccessList;
|
||||||
|
Unread.ready();
|
||||||
|
}
|
||||||
thread = $('.thread');
|
thread = $('.thread');
|
||||||
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
||||||
QuoteThreading.enabled = this.checked;
|
if (QuoteThreading.enabled = this.checked) {
|
||||||
if (this.checked) {
|
|
||||||
QuoteThreading.hasRun = false;
|
QuoteThreading.hasRun = false;
|
||||||
for (_i = 0, _len = replies.length; _i < _len; _i++) {
|
for (_i = 0, _len = replies.length; _i < _len; _i++) {
|
||||||
reply = replies[_i];
|
reply = replies[_i];
|
||||||
QuoteThreading.node.call(node = Get.postFromRoot(reply));
|
post = Get.postFromRoot(reply);
|
||||||
if (node.cb) {
|
if (post.cb) {
|
||||||
node.cb();
|
post.cb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QuoteThreading.hasRun = true;
|
QuoteThreading.hasRun = true;
|
||||||
} else {
|
} else {
|
||||||
replies.sort(function(a, b) {
|
replies.sort(function(a, b) {
|
||||||
var aID, bID;
|
return Number(a.id.slice(2)) - Number(b.id.slice(2));
|
||||||
aID = Number(a.id.slice(2));
|
|
||||||
bID = Number(b.id.slice(2));
|
|
||||||
return aID - bID;
|
|
||||||
});
|
});
|
||||||
$.add(thread, replies);
|
$.add(thread, replies);
|
||||||
containers = $$('.threadContainer', thread);
|
containers = $$('.threadContainer', thread);
|
||||||
@ -7245,12 +7350,15 @@
|
|||||||
$.rmClass(post, 'threadOP');
|
$.rmClass(post, 'threadOP');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Unread.update(true);
|
if (Conf['Unread Count']) {
|
||||||
|
return Unread.read();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
kb: function() {
|
kb: function() {
|
||||||
var control;
|
var control;
|
||||||
control = $.id('threadingControl');
|
control = $.id('threadingControl');
|
||||||
return control.click();
|
control.checked = !control.checked;
|
||||||
|
return QuoteThreading.toggle.call(control);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11152,7 +11260,7 @@
|
|||||||
}
|
}
|
||||||
root = post.nodes.root;
|
root = post.nodes.root;
|
||||||
if (post.cb) {
|
if (post.cb) {
|
||||||
if (!post.cb.call(post)) {
|
if (!post.cb()) {
|
||||||
$.add(ThreadUpdater.root, root);
|
$.add(ThreadUpdater.root, root);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -11682,8 +11790,19 @@
|
|||||||
this.hr = $.el('hr', {
|
this.hr = $.el('hr', {
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
});
|
});
|
||||||
this.posts = [];
|
this.posts = new RandomAccessList;
|
||||||
this.postsQuotingYou = [];
|
this.postsQuotingYou = [];
|
||||||
|
this.qr = QR.db ? function(post) {
|
||||||
|
var data;
|
||||||
|
data = {
|
||||||
|
boardID: post.board.ID,
|
||||||
|
threadID: post.thread.ID,
|
||||||
|
postID: post.ID
|
||||||
|
};
|
||||||
|
return (QR.db.get(data) ? true : false);
|
||||||
|
} : function() {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
return Thread.callbacks.push({
|
return Thread.callbacks.push({
|
||||||
name: 'Unread',
|
name: 'Unread',
|
||||||
cb: this.node
|
cb: this.node
|
||||||
@ -11716,17 +11835,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unread.addPosts(posts);
|
Unread.addPosts(posts);
|
||||||
return Unread.scroll();
|
if (Conf['Quote Threading']) {
|
||||||
|
QuoteThreading.setup();
|
||||||
|
}
|
||||||
|
if (Conf['Scroll to Last Read Post']) {
|
||||||
|
return Unread.scroll();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scroll: function() {
|
scroll: function() {
|
||||||
var down, hash, post, posts, root;
|
var down, hash, post, posts, root;
|
||||||
if (!Conf['Scroll to Last Read Post']) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (post = Unread.posts[0]) {
|
if (post = Unread.posts.first) {
|
||||||
while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) {
|
while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) {
|
||||||
if (!(post = Get.postFromRoot(root)).isHidden) {
|
if (!(post = Get.postFromRoot(root)).isHidden) {
|
||||||
break;
|
break;
|
||||||
@ -11745,7 +11866,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var ID, lastReadPost, post;
|
||||||
lastReadPost = Unread.db.get({
|
lastReadPost = Unread.db.get({
|
||||||
boardID: Unread.thread.board.ID,
|
boardID: Unread.thread.board.ID,
|
||||||
threadID: Unread.thread.ID,
|
threadID: Unread.thread.ID,
|
||||||
@ -11755,7 +11876,14 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Unread.lastReadPost = lastReadPost;
|
Unread.lastReadPost = lastReadPost;
|
||||||
Unread.readArray(Unread.posts);
|
post = Unread.posts.first;
|
||||||
|
while (post) {
|
||||||
|
if ((ID = post.ID, post) > Unread.lastReadPost) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
post = post.next;
|
||||||
|
Unread.posts.rm(ID);
|
||||||
|
}
|
||||||
Unread.readArray(Unread.postsQuotingYou);
|
Unread.readArray(Unread.postsQuotingYou);
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine();
|
Unread.setLine();
|
||||||
@ -11763,28 +11891,20 @@
|
|||||||
return Unread.update();
|
return Unread.update();
|
||||||
},
|
},
|
||||||
addPosts: function(posts) {
|
addPosts: function(posts) {
|
||||||
var ID, data, post, _i, _len, _ref;
|
var ID, post, _i, _len, _ref;
|
||||||
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
||||||
post = posts[_i];
|
post = posts[_i];
|
||||||
ID = post.ID;
|
ID = post.ID;
|
||||||
if (ID <= Unread.lastReadPost || post.isHidden) {
|
if (ID <= Unread.lastReadPost || post.isHidden || Unread.qr(post)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (QR.db) {
|
if (!(post.prev || post.next)) {
|
||||||
data = {
|
Unread.posts.push(post);
|
||||||
boardID: post.board.ID,
|
|
||||||
threadID: post.thread.ID,
|
|
||||||
postID: post.ID
|
|
||||||
};
|
|
||||||
if (QR.db.get(data)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Unread.posts.push(post);
|
|
||||||
Unread.addPostQuotingYou(post);
|
Unread.addPostQuotingYou(post);
|
||||||
}
|
}
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine((_ref = Unread.posts[0], __indexOf.call(posts, _ref) >= 0));
|
Unread.setLine((_ref = Unread.posts.first, __indexOf.call(posts, _ref) >= 0));
|
||||||
}
|
}
|
||||||
Unread.read();
|
Unread.read();
|
||||||
return Unread.update();
|
return Unread.update();
|
||||||
@ -11833,15 +11953,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
readSinglePost: function(post) {
|
readSinglePost: function(post) {
|
||||||
var i;
|
var ID, i;
|
||||||
if ((i = Unread.posts.indexOf(post)) === -1) {
|
ID = post.ID;
|
||||||
|
if (!Unread.posts[ID]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Unread.posts.splice(i, 1);
|
if (post === Unread.posts.first) {
|
||||||
if (i === 0) {
|
Unread.lastReadPost = ID;
|
||||||
Unread.lastReadPost = post.ID;
|
|
||||||
Unread.saveLastReadPost();
|
Unread.saveLastReadPost();
|
||||||
}
|
}
|
||||||
|
Unread.posts.rm(ID);
|
||||||
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
||||||
Unread.postsQuotingYou.splice(i, 1);
|
Unread.postsQuotingYou.splice(i, 1);
|
||||||
}
|
}
|
||||||
@ -11857,35 +11978,22 @@
|
|||||||
}
|
}
|
||||||
return arr.splice(0, i);
|
return arr.splice(0, i);
|
||||||
},
|
},
|
||||||
read: $.debounce(50, function(e) {
|
read: $.debounce(100, function(e) {
|
||||||
var ID, height, i, post, posts;
|
var ID, height, post, posts;
|
||||||
if (d.hidden || !Unread.posts.length) {
|
if (d.hidden || !Unread.posts.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
posts = Unread.posts;
|
posts = Unread.posts;
|
||||||
i = 0;
|
while (post = posts.first) {
|
||||||
while (post = posts[i]) {
|
if (!(Header.getBottomOf(post.nodes.root) > -1)) {
|
||||||
if (Header.getBottomOf(post.nodes.root) > -1) {
|
break;
|
||||||
ID = post.ID;
|
}
|
||||||
if (Conf['Mark Quotes of You']) {
|
ID = post.ID;
|
||||||
if (post.info.yours) {
|
posts.rm(ID);
|
||||||
QuoteYou.lastRead = post.nodes.root;
|
if (Conf['Mark Quotes of You'] && post.info.yours) {
|
||||||
}
|
QuoteYou.lastRead = post.nodes.root;
|
||||||
}
|
|
||||||
if (Conf['Quote Threading']) {
|
|
||||||
posts.splice(i, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!Conf['Quote Threading']) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i && !Conf['Quote Threading']) {
|
|
||||||
posts.splice(0, i);
|
|
||||||
}
|
}
|
||||||
if (!ID) {
|
if (!ID) {
|
||||||
return;
|
return;
|
||||||
@ -11914,7 +12022,7 @@
|
|||||||
if (!(d.hidden || force === true)) {
|
if (!(d.hidden || force === true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(post = Unread.posts[0])) {
|
if (!(post = Unread.posts.first)) {
|
||||||
return $.rm(Unread.hr);
|
return $.rm(Unread.hr);
|
||||||
}
|
}
|
||||||
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root)) {
|
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root)) {
|
||||||
|
|||||||
@ -4,3 +4,4 @@
|
|||||||
<%= grunt.file.read('src/General/lib/clone.class') %>
|
<%= grunt.file.read('src/General/lib/clone.class') %>
|
||||||
<%= grunt.file.read('src/General/lib/databoard.class') %>
|
<%= grunt.file.read('src/General/lib/databoard.class') %>
|
||||||
<%= grunt.file.read('src/General/lib/notice.class') %>
|
<%= grunt.file.read('src/General/lib/notice.class') %>
|
||||||
|
<%= grunt.file.read('src/General/lib/randomaccesslist.class') %>
|
||||||
67
src/General/lib/randomaccesslist.class
Normal file
67
src/General/lib/randomaccesslist.class
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
class RandomAccessList
|
||||||
|
constructor: ->
|
||||||
|
@length = 0
|
||||||
|
|
||||||
|
push: (item) ->
|
||||||
|
{ID} = item
|
||||||
|
return if @[ID]
|
||||||
|
{last} = @
|
||||||
|
item.prev = last
|
||||||
|
@[ID] = item
|
||||||
|
@last = if last
|
||||||
|
last.next = item
|
||||||
|
else
|
||||||
|
@first = item
|
||||||
|
@length++
|
||||||
|
|
||||||
|
after: (root, item) ->
|
||||||
|
return if item.prev is root
|
||||||
|
|
||||||
|
@rmi item
|
||||||
|
|
||||||
|
{next} = root
|
||||||
|
root.next = item
|
||||||
|
item.prev = root
|
||||||
|
item.next = next
|
||||||
|
next.prev = item
|
||||||
|
|
||||||
|
prepend: (item) ->
|
||||||
|
{first} = @
|
||||||
|
return if item is first or not @[item.ID]
|
||||||
|
@rmi item
|
||||||
|
item.next = first
|
||||||
|
first.prev = item
|
||||||
|
@first = item
|
||||||
|
delete item.prev
|
||||||
|
|
||||||
|
shift: ->
|
||||||
|
@rm @first.ID
|
||||||
|
|
||||||
|
rm: (ID) ->
|
||||||
|
item = @[ID]
|
||||||
|
return unless item
|
||||||
|
delete @[ID]
|
||||||
|
@length--
|
||||||
|
@rmi item
|
||||||
|
delete item.next
|
||||||
|
delete item.prev
|
||||||
|
|
||||||
|
rmi: (item) ->
|
||||||
|
{prev, next} = item
|
||||||
|
if prev
|
||||||
|
prev.next = next
|
||||||
|
else
|
||||||
|
@first = next
|
||||||
|
if next
|
||||||
|
next.prev = prev
|
||||||
|
else
|
||||||
|
@last = prev
|
||||||
|
|
||||||
|
closest: (ID) ->
|
||||||
|
item = @first
|
||||||
|
while item
|
||||||
|
if item.ID > ID
|
||||||
|
{prev} = item
|
||||||
|
break
|
||||||
|
item = item.next
|
||||||
|
return (if prev then prev.ID else -1)
|
||||||
@ -296,7 +296,7 @@ ThreadUpdater =
|
|||||||
continue unless posts.hasOwnProperty key
|
continue unless posts.hasOwnProperty key
|
||||||
root = post.nodes.root
|
root = post.nodes.root
|
||||||
if post.cb
|
if post.cb
|
||||||
unless post.cb.call post
|
unless post.cb()
|
||||||
$.add ThreadUpdater.root, root
|
$.add ThreadUpdater.root, root
|
||||||
else
|
else
|
||||||
$.add ThreadUpdater.root, root
|
$.add ThreadUpdater.root, root
|
||||||
|
|||||||
@ -5,9 +5,19 @@ Unread =
|
|||||||
@db = new DataBoard 'lastReadPosts', @sync
|
@db = new DataBoard 'lastReadPosts', @sync
|
||||||
@hr = $.el 'hr',
|
@hr = $.el 'hr',
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
@posts = []
|
@posts = new RandomAccessList
|
||||||
@postsQuotingYou = []
|
@postsQuotingYou = []
|
||||||
|
|
||||||
|
@qr = if QR.db
|
||||||
|
(post) ->
|
||||||
|
data =
|
||||||
|
boardID: post.board.ID
|
||||||
|
threadID: post.thread.ID
|
||||||
|
postID: post.ID
|
||||||
|
return (if QR.db.get data then true else false)
|
||||||
|
else ->
|
||||||
|
return false
|
||||||
|
|
||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
name: 'Unread'
|
name: 'Unread'
|
||||||
cb: @node
|
cb: @node
|
||||||
@ -27,16 +37,15 @@ Unread =
|
|||||||
ready: ->
|
ready: ->
|
||||||
$.off d, '4chanXInitFinished', Unread.ready
|
$.off d, '4chanXInitFinished', Unread.ready
|
||||||
posts = []
|
posts = []
|
||||||
for ID, post of Unread.thread.posts
|
posts.push post for ID, post of Unread.thread.posts when post.isReply
|
||||||
posts.push post if post.isReply
|
|
||||||
Unread.addPosts posts
|
Unread.addPosts posts
|
||||||
Unread.scroll()
|
QuoteThreading.setup() if Conf['Quote Threading']
|
||||||
|
Unread.scroll() if Conf['Scroll to Last Read Post']
|
||||||
|
|
||||||
scroll: ->
|
scroll: ->
|
||||||
return unless Conf['Scroll to Last Read Post']
|
|
||||||
# Let the header's onload callback handle it.
|
# Let the header's onload callback handle it.
|
||||||
return if (hash = location.hash.match /\d+/) and hash[0] of Unread.thread.posts
|
return if (hash = location.hash.match /\d+/) and hash[0] of Unread.thread.posts
|
||||||
if post = Unread.posts[0]
|
if post = Unread.posts.first
|
||||||
# Scroll to a non-hidden, non-OP post that's before the first unread post.
|
# Scroll to a non-hidden, non-OP post that's before the first unread post.
|
||||||
while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root
|
while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root
|
||||||
break unless (post = Get.postFromRoot root).isHidden
|
break unless (post = Get.postFromRoot root).isHidden
|
||||||
@ -57,7 +66,13 @@ Unread =
|
|||||||
defaultValue: 0
|
defaultValue: 0
|
||||||
return unless Unread.lastReadPost < lastReadPost
|
return unless Unread.lastReadPost < lastReadPost
|
||||||
Unread.lastReadPost = lastReadPost
|
Unread.lastReadPost = lastReadPost
|
||||||
Unread.readArray Unread.posts
|
|
||||||
|
post = Unread.posts.first
|
||||||
|
while post
|
||||||
|
break if ({ID} = post) > Unread.lastReadPost
|
||||||
|
post = post.next
|
||||||
|
Unread.posts.rm ID
|
||||||
|
|
||||||
Unread.readArray Unread.postsQuotingYou
|
Unread.readArray Unread.postsQuotingYou
|
||||||
Unread.setLine() if Conf['Unread Line']
|
Unread.setLine() if Conf['Unread Line']
|
||||||
Unread.update()
|
Unread.update()
|
||||||
@ -65,19 +80,12 @@ Unread =
|
|||||||
addPosts: (posts) ->
|
addPosts: (posts) ->
|
||||||
for post in posts
|
for post in posts
|
||||||
{ID} = post
|
{ID} = post
|
||||||
if ID <= Unread.lastReadPost or post.isHidden
|
continue if ID <= Unread.lastReadPost or post.isHidden or Unread.qr post
|
||||||
continue
|
Unread.posts.push post unless post.prev or post.next
|
||||||
if QR.db
|
|
||||||
data =
|
|
||||||
boardID: post.board.ID
|
|
||||||
threadID: post.thread.ID
|
|
||||||
postID: post.ID
|
|
||||||
continue if QR.db.get data
|
|
||||||
Unread.posts.push post
|
|
||||||
Unread.addPostQuotingYou post
|
Unread.addPostQuotingYou post
|
||||||
if Conf['Unread Line']
|
if Conf['Unread Line']
|
||||||
# Force line on visible threads if there were no unread posts previously.
|
# Force line on visible threads if there were no unread posts previously.
|
||||||
Unread.setLine Unread.posts[0] in posts
|
Unread.setLine Unread.posts.first in posts
|
||||||
Unread.read()
|
Unread.read()
|
||||||
Unread.update()
|
Unread.update()
|
||||||
|
|
||||||
@ -112,11 +120,12 @@ Unread =
|
|||||||
Unread.addPosts e.detail.newPosts
|
Unread.addPosts e.detail.newPosts
|
||||||
|
|
||||||
readSinglePost: (post) ->
|
readSinglePost: (post) ->
|
||||||
return if (i = Unread.posts.indexOf post) is -1
|
{ID} = post
|
||||||
Unread.posts.splice i, 1
|
return unless Unread.posts[ID]
|
||||||
if i is 0
|
if post is Unread.posts.first
|
||||||
Unread.lastReadPost = post.ID
|
Unread.lastReadPost = ID
|
||||||
Unread.saveLastReadPost()
|
Unread.saveLastReadPost()
|
||||||
|
Unread.posts.rm ID
|
||||||
if (i = Unread.postsQuotingYou.indexOf post) isnt -1
|
if (i = Unread.postsQuotingYou.indexOf post) isnt -1
|
||||||
Unread.postsQuotingYou.splice i, 1
|
Unread.postsQuotingYou.splice i, 1
|
||||||
Unread.update()
|
Unread.update()
|
||||||
@ -126,28 +135,18 @@ Unread =
|
|||||||
break if post.ID > Unread.lastReadPost
|
break if post.ID > Unread.lastReadPost
|
||||||
arr.splice 0, i
|
arr.splice 0, i
|
||||||
|
|
||||||
read: $.debounce 50, (e) ->
|
read: $.debounce 100, (e) ->
|
||||||
return if d.hidden or !Unread.posts.length
|
return if d.hidden or !Unread.posts.length
|
||||||
height = doc.clientHeight
|
height = doc.clientHeight
|
||||||
|
|
||||||
{posts} = Unread
|
{posts} = Unread
|
||||||
i = 0
|
while post = posts.first
|
||||||
|
break unless Header.getBottomOf(post.nodes.root) > -1 # post is not completely read
|
||||||
|
{ID} = post
|
||||||
|
posts.rm ID
|
||||||
|
|
||||||
while post = posts[i]
|
if Conf['Mark Quotes of You'] and post.info.yours
|
||||||
if Header.getBottomOf(post.nodes.root) > -1 # post is not completely read
|
QuoteYou.lastRead = post.nodes.root
|
||||||
{ID} = post
|
|
||||||
if Conf['Mark Quotes of You']
|
|
||||||
if post.info.yours
|
|
||||||
QuoteYou.lastRead = post.nodes.root
|
|
||||||
if Conf['Quote Threading']
|
|
||||||
posts.splice i, 1
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
unless Conf['Quote Threading']
|
|
||||||
break
|
|
||||||
i++
|
|
||||||
|
|
||||||
if i and !Conf['Quote Threading']
|
|
||||||
posts.splice 0, i
|
|
||||||
|
|
||||||
return unless ID
|
return unless ID
|
||||||
|
|
||||||
@ -159,13 +158,13 @@ Unread =
|
|||||||
saveLastReadPost: $.debounce 2 * $.SECOND, ->
|
saveLastReadPost: $.debounce 2 * $.SECOND, ->
|
||||||
return if Unread.thread.isDead
|
return if Unread.thread.isDead
|
||||||
Unread.db.set
|
Unread.db.set
|
||||||
boardID: Unread.thread.board.ID
|
boardID: Unread.thread.board.ID
|
||||||
threadID: Unread.thread.ID
|
threadID: Unread.thread.ID
|
||||||
val: Unread.lastReadPost
|
val: Unread.lastReadPost
|
||||||
|
|
||||||
setLine: (force) ->
|
setLine: (force) ->
|
||||||
return unless d.hidden or force is true
|
return unless d.hidden or force is true
|
||||||
return $.rm Unread.hr unless post = Unread.posts[0]
|
return $.rm Unread.hr unless post = Unread.posts.first
|
||||||
if $.x 'preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root # not the first reply
|
if $.x 'preceding-sibling::div[contains(@class,"replyContainer")]', post.nodes.root # not the first reply
|
||||||
$.before post.nodes.root, Unread.hr
|
$.before post.nodes.root, Unread.hr
|
||||||
|
|
||||||
|
|||||||
@ -11,14 +11,14 @@ QuoteThreading =
|
|||||||
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
innerHTML: '<label><input id=threadingControl type=checkbox checked> Threading</label>'
|
||||||
|
|
||||||
input = $ 'input', @controls
|
input = $ 'input', @controls
|
||||||
$.on input, 'change', QuoteThreading.toggle
|
$.on input, 'change', @toggle
|
||||||
|
|
||||||
$.event 'AddMenuEntry',
|
$.event 'AddMenuEntry',
|
||||||
type: 'header'
|
type: 'header'
|
||||||
el: @controls
|
el: @controls
|
||||||
order: 98
|
order: 98
|
||||||
|
|
||||||
$.on d, '4chanXInitFinished', @setup
|
$.on d, '4chanXInitFinished', @setup unless Conf['Unread Count']
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Quote Threading'
|
name: 'Quote Threading'
|
||||||
@ -26,83 +26,91 @@ QuoteThreading =
|
|||||||
|
|
||||||
setup: ->
|
setup: ->
|
||||||
$.off d, '4chanXInitFinished', QuoteThreading.setup
|
$.off d, '4chanXInitFinished', QuoteThreading.setup
|
||||||
{posts} = g
|
|
||||||
|
|
||||||
for ID, post of posts
|
|
||||||
if post.cb
|
|
||||||
post.cb.call post
|
|
||||||
|
|
||||||
|
post.cb() for ID, post of g.posts when post.cb
|
||||||
QuoteThreading.hasRun = true
|
QuoteThreading.hasRun = true
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @isClone or not QuoteThreading.enabled or @thread.OP is @
|
|
||||||
|
|
||||||
{quotes, ID, fullID} = @
|
|
||||||
{posts} = g
|
{posts} = g
|
||||||
return if !(post = posts[fullID]) or post.isHidden # Filtered
|
return if @isClone or not QuoteThreading.enabled
|
||||||
|
Unread.posts.push @ if Conf['Unread Count']
|
||||||
|
|
||||||
uniq = {}
|
return if @thread.OP is @ or !(post = posts[@fullID]) or post.isHidden # Filtered
|
||||||
len = "#{g.BOARD}".length + 1
|
|
||||||
for quote in quotes
|
keys = []
|
||||||
qid = quote
|
len = g.BOARD.ID.length + 1
|
||||||
continue unless qid[len..] < ID
|
keys.push quote for quote in @quotes when (quote[len..] < @ID) and quote of posts
|
||||||
if qid of posts
|
|
||||||
uniq[qid[len..]] = true
|
|
||||||
|
|
||||||
keys = Object.keys uniq
|
|
||||||
return unless keys.length is 1
|
return unless keys.length is 1
|
||||||
|
|
||||||
@threaded = "#{g.BOARD}.#{keys[0]}"
|
@threaded = keys[0]
|
||||||
@cb = QuoteThreading.nodeinsert
|
@cb = QuoteThreading.nodeinsert
|
||||||
|
|
||||||
nodeinsert: ->
|
nodeinsert: ->
|
||||||
qpost = g.posts[@threaded]
|
post = g.posts[@threaded]
|
||||||
|
{posts} = Unread
|
||||||
|
|
||||||
delete @threaded
|
return false if @thread.OP is post
|
||||||
delete @cb
|
|
||||||
|
|
||||||
return false if @thread.OP is qpost
|
|
||||||
|
|
||||||
if QuoteThreading.hasRun
|
if QuoteThreading.hasRun
|
||||||
height = doc.clientHeight
|
height = doc.clientHeight
|
||||||
{bottom, top} = qpost.nodes.root.getBoundingClientRect()
|
{bottom, top} = post.nodes.root.getBoundingClientRect()
|
||||||
|
|
||||||
# Post is unread or is fully visible.
|
# Post is unread or is fully visible.
|
||||||
return false unless qpost in Unread.posts or ((bottom < height) and (top > 0))
|
return false unless posts?[post.ID] or ((bottom < height) and (top > 0))
|
||||||
|
|
||||||
qroot = qpost.nodes.root
|
{root} = post.nodes
|
||||||
unless $.hasClass qroot, 'threadOP'
|
unless $.hasClass root, 'threadOP'
|
||||||
$.addClass qroot, 'threadOP'
|
$.addClass root, 'threadOP'
|
||||||
threadContainer = $.el 'div',
|
threadContainer = $.el 'div',
|
||||||
className: 'threadContainer'
|
className: 'threadContainer'
|
||||||
$.after qroot, threadContainer
|
$.after root, threadContainer
|
||||||
else
|
else
|
||||||
threadContainer = qroot.nextSibling
|
threadContainer = root.nextSibling
|
||||||
|
post = Get.postFromRoot $.x 'descendant::div[contains(@class,"postContainer")][last()]', threadContainer
|
||||||
|
|
||||||
$.add threadContainer, @nodes.root
|
$.add threadContainer, @nodes.root
|
||||||
|
|
||||||
|
return true unless Conf['Unread Count']
|
||||||
|
|
||||||
|
if posts[post.ID]
|
||||||
|
posts.after post, @
|
||||||
|
return true
|
||||||
|
|
||||||
|
if (ID = posts.closest post.ID) isnt -1
|
||||||
|
posts.after posts[ID], @
|
||||||
|
else
|
||||||
|
posts.prepend @
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
toggle: ->
|
toggle: ->
|
||||||
|
if Conf['Unread Count']
|
||||||
|
Unread.posts = new RandomAccessList
|
||||||
|
Unread.ready()
|
||||||
|
|
||||||
thread = $ '.thread'
|
thread = $ '.thread'
|
||||||
replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread
|
replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread
|
||||||
QuoteThreading.enabled = @checked
|
|
||||||
if @checked
|
if QuoteThreading.enabled = @checked
|
||||||
QuoteThreading.hasRun = false
|
QuoteThreading.hasRun = false
|
||||||
for reply in replies
|
for reply in replies
|
||||||
QuoteThreading.node.call node = Get.postFromRoot reply
|
post = Get.postFromRoot reply
|
||||||
node.cb() if node.cb
|
# QuoteThreading calculates whether or not posts should be threaded based on content
|
||||||
|
# and then threads them based on thread context, so regardless of whether or not it
|
||||||
|
# actually threads them all eligible posts WILL have a cb. Magic.
|
||||||
|
post.cb() if post.cb
|
||||||
QuoteThreading.hasRun = true
|
QuoteThreading.hasRun = true
|
||||||
|
|
||||||
else
|
else
|
||||||
replies.sort (a, b) ->
|
replies.sort (a, b) -> Number(a.id[2..]) - Number(b.id[2..])
|
||||||
aID = Number a.id[2..]
|
|
||||||
bID = Number b.id[2..]
|
|
||||||
aID - bID
|
|
||||||
$.add thread, replies
|
$.add thread, replies
|
||||||
containers = $$ '.threadContainer', thread
|
containers = $$ '.threadContainer', thread
|
||||||
$.rm container for container in containers
|
$.rm container for container in containers
|
||||||
$.rmClass post, 'threadOP' for post in $$ '.threadOP'
|
$.rmClass post, 'threadOP' for post in $$ '.threadOP'
|
||||||
Unread.update true
|
Unread.read() if Conf['Unread Count']
|
||||||
|
|
||||||
kb: ->
|
kb: ->
|
||||||
control = $.id 'threadingControl'
|
control = $.id 'threadingControl'
|
||||||
control.click()
|
control.checked = not control.checked
|
||||||
|
QuoteThreading.toggle.call control
|
||||||
Loading…
x
Reference in New Issue
Block a user