Completely remove Unread functionality from Quote Threading

And make Unread Quote Threading aware.

Also kill Random Access List
This commit is contained in:
Zixaphir 2013-04-18 23:16:48 -07:00
parent 7f59f65202
commit 23bed0ede7
7 changed files with 162 additions and 643 deletions

View File

@ -43,7 +43,7 @@
*/ */
(function() { (function() {
var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
__slice = [].slice, __slice = [].slice,
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -1446,79 +1446,6 @@
})(); })();
RandomAccessList = (function() {
function RandomAccessList() {
this.first = null;
this.last = null;
this.length = 0;
}
RandomAccessList.prototype.push = function(id, post) {
var item, last;
last = this.last;
this[id] = item = post;
item.prev = last;
item.next = null;
this.last = item;
if (last) {
last.next = item;
} else {
this.first = item;
}
return this.length++;
};
RandomAccessList.prototype.shift = function() {
return this.rm(this.first.ID);
};
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.rm = function(id) {
var item;
item = this[id];
if (!item) {
return;
}
delete this[id];
this.length--;
return this.rmi(item);
};
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;
}
};
return RandomAccessList;
})();
Get = { Get = {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, _ref; var OP, excerpt, _ref;
@ -6377,7 +6304,7 @@
this.hr = $.el('hr', { this.hr = $.el('hr', {
id: 'unread-line' id: 'unread-line'
}); });
this.posts = new RandomAccessList; this.posts = [];
this.postsQuotingYou = []; this.postsQuotingYou = [];
return Thread.prototype.callbacks.push({ return Thread.prototype.callbacks.push({
name: 'Unread', name: 'Unread',
@ -6461,16 +6388,14 @@
continue; continue;
} }
} }
Unread.posts.push(ID, post); Unread.posts.push(post);
Unread.addPostQuotingYou(post); Unread.addPostQuotingYou(post);
} }
if (Conf['Unread Line']) { if (Conf['Unread Line']) {
Unread.setLine(newPosts.contains(Unread.posts.first)); Unread.setLine(newPosts.contains(Unread.posts[0]));
}
if (!Conf['Quote Threading']) {
Unread.read();
return Unread.update();
} }
Unread.read();
return Unread.update();
}, },
addPostQuotingYou: function(post) { addPostQuotingYou: function(post) {
var quotelink, _i, _len, _ref; var quotelink, _i, _len, _ref;
@ -6494,15 +6419,14 @@
} }
}, },
readSinglePost: function(post) { readSinglePost: function(post) {
var ID, i; var i;
ID = post.ID; if ((i = Unread.posts.indexOf(post)) === -1) {
if (!Unread.posts[ID]) {
return; return;
} }
Unread.posts.rm(ID); Unread.posts.splice(i, 1);
if (!Unread.posts.first) { if (i === 0) {
Unread.lastReadPost = ID; Unread.lastReadPost = post.ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
} }
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) { if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
@ -6510,20 +6434,6 @@
} }
return Unread.update(); return Unread.update();
}, },
readRAL: function(ral) {
var item, items, post, _i, _len, _results;
items = [];
for (post in ral) {
items.push(post.ID > Unread.lastReadPost);
}
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
_results.push(ral.rm(item));
}
return _results;
},
readArray: function(arr) { readArray: function(arr) {
var i, post, _i, _len; var i, post, _i, _len;
@ -6536,28 +6446,26 @@
return arr.splice(0, i); return arr.splice(0, i);
}, },
read: function(e) { read: function(e) {
var bottom, height, key, post, posts; var bottom, height, i, post, posts, read, top, _ref;
if (d.hidden || !Unread.posts.length) { if (d.hidden || !Unread.posts.length) {
return; return;
} }
posts = Unread.posts;
height = doc.clientHeight; height = doc.clientHeight;
for (key in posts) { posts = Unread.posts;
post = posts[key]; read = [];
if (!posts.hasOwnProperty(key)) { i = posts.length;
continue; while (post = posts[--i]) {
_ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
if ((bottom < height) && (top > 0)) {
read.push(post);
posts.remove(post);
} }
bottom = post.nodes.root.getBoundingClientRect().bottom;
if (bottom > height) {
break;
}
Unread.posts.rm(post);
} }
if (!post) { if (!read.length) {
return; return;
} }
Unread.lastReadPost = post.ID; Unread.lastReadPost = read[read.length - 1].ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
Unread.readArray(Unread.postsQuotingYou); Unread.readArray(Unread.postsQuotingYou);
if (e) { if (e) {
@ -8278,79 +8186,51 @@
$.off(d, '4chanXInitFinished', QuoteThreading.setup); $.off(d, '4chanXInitFinished', QuoteThreading.setup);
posts = g.posts; posts = g.posts;
Unread.read();
Unread.update();
for (ID in posts) { for (ID in posts) {
post = posts[ID]; post = posts[ID];
if (post.cb) { if (post.cb) {
post.cb.call(post); post.cb.call(post);
} }
} }
return;
return QuoteThreading.hasRun = true; return QuoteThreading.hasRun = true;
}, },
node: function() { node: function() {
var ID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _j, _len, _len1; var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len;
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
return; return;
} }
quotes = this.quotes, ID = this.ID; quotes = this.quotes, ID = this.ID, fullID = this.fullID;
if (QuoteThreading.hasRun) { posts = g.posts;
posts = Unread.posts; if (!(post = posts[fullID]) || post.isHidden) {
if (!(post = posts[ID]) || post.isHidden) { return;
return;
}
} else {
posts = g.posts;
if (!(post = posts["" + g.BOARD + "." + ID]) || post.isHidden) {
return;
}
} }
uniq = {}; uniq = {};
if (QuoteThreading.hasRun) { len = ("" + g.BOARD).length + 1;
for (_i = 0, _len = quotes.length; _i < _len; _i++) { for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i]; quote = quotes[_i];
qid = quote.slice(2); qid = quote;
if (!(qid < ID)) { if (!(qid.slice(len) < ID)) {
continue; continue;
}
if (qid in posts) {
uniq[qid] = true;
}
} }
} else { if (qid in posts) {
len = ("" + g.BOARD).length + 1; uniq[qid.slice(len)] = true;
for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) {
quote = quotes[_j];
qid = quote;
if (!(qid.slice(len) < ID)) {
continue;
}
if (qid in posts) {
uniq[qid.slice(len)] = true;
}
} }
} }
keys = Object.keys(uniq); keys = Object.keys(uniq);
if (keys.length !== 1) { if (keys.length !== 1) {
return; return;
} }
this.threaded = keys[0]; this.threaded = "" + g.BOARD + "." + keys[0];
return this.cb = QuoteThreading.nodeinsert; return this.cb = QuoteThreading.nodeinsert;
}, },
nodeinsert: function() { nodeinsert: function() {
var pEl, pid, post, posts, ppost, qid, qpost, qroot, threadContainer, unread; var posts, qpost, qroot, threadContainer;
qid = this.threaded; posts = g.posts;
if (QuoteThreading.hasRun) { qpost = posts[this.threaded];
posts = Unread.posts; delete this.threaded;
qpost = posts[qid]; delete this.cb;
} else {
posts = g.posts;
unread = Unread.posts;
qpost = posts["" + g.BOARD + "." + qid];
}
if (this.thread.OP === qpost) { if (this.thread.OP === qpost) {
return; return;
} }
@ -8362,18 +8242,7 @@
}); });
$.after(qroot, threadContainer); $.after(qroot, threadContainer);
} }
$.add(threadContainer, this.nodes.root); return $.add(threadContainer, this.nodes.root);
pEl = $.x('preceding::div[contains(@class,"post reply")][1]/parent::div', this.nodes.root);
pid = pEl.id.slice(2);
if (QuoteThreading.hasRun) {
ppost = posts[pid];
} else {
ppost = posts[pid];
if (!((post = unread["" + g.BOARD + "." + this.id]) && (ppost = unread["" + g.BOARD + "." + pid]))) {
return;
}
}
return posts.after(ppost, this);
}, },
toggle: function() { toggle: function() {
var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results; var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results;

View File

@ -43,7 +43,7 @@
*/ */
(function() { (function() {
var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
__slice = [].slice, __slice = [].slice,
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -1437,79 +1437,6 @@
})(); })();
RandomAccessList = (function() {
function RandomAccessList() {
this.first = null;
this.last = null;
this.length = 0;
}
RandomAccessList.prototype.push = function(id, post) {
var item, last;
last = this.last;
this[id] = item = post;
item.prev = last;
item.next = null;
this.last = item;
if (last) {
last.next = item;
} else {
this.first = item;
}
return this.length++;
};
RandomAccessList.prototype.shift = function() {
return this.rm(this.first.ID);
};
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.rm = function(id) {
var item;
item = this[id];
if (!item) {
return;
}
delete this[id];
this.length--;
return this.rmi(item);
};
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;
}
};
return RandomAccessList;
})();
Get = { Get = {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, _ref; var OP, excerpt, _ref;
@ -6369,7 +6296,7 @@
this.hr = $.el('hr', { this.hr = $.el('hr', {
id: 'unread-line' id: 'unread-line'
}); });
this.posts = new RandomAccessList; this.posts = [];
this.postsQuotingYou = []; this.postsQuotingYou = [];
return Thread.prototype.callbacks.push({ return Thread.prototype.callbacks.push({
name: 'Unread', name: 'Unread',
@ -6453,16 +6380,14 @@
continue; continue;
} }
} }
Unread.posts.push(ID, post); Unread.posts.push(post);
Unread.addPostQuotingYou(post); Unread.addPostQuotingYou(post);
} }
if (Conf['Unread Line']) { if (Conf['Unread Line']) {
Unread.setLine(newPosts.contains(Unread.posts.first)); Unread.setLine(newPosts.contains(Unread.posts[0]));
}
if (!Conf['Quote Threading']) {
Unread.read();
return Unread.update();
} }
Unread.read();
return Unread.update();
}, },
addPostQuotingYou: function(post) { addPostQuotingYou: function(post) {
var quotelink, _i, _len, _ref; var quotelink, _i, _len, _ref;
@ -6486,15 +6411,14 @@
} }
}, },
readSinglePost: function(post) { readSinglePost: function(post) {
var ID, i; var i;
ID = post.ID; if ((i = Unread.posts.indexOf(post)) === -1) {
if (!Unread.posts[ID]) {
return; return;
} }
Unread.posts.rm(ID); Unread.posts.splice(i, 1);
if (!Unread.posts.first) { if (i === 0) {
Unread.lastReadPost = ID; Unread.lastReadPost = post.ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
} }
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) { if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
@ -6502,20 +6426,6 @@
} }
return Unread.update(); return Unread.update();
}, },
readRAL: function(ral) {
var item, items, post, _i, _len, _results;
items = [];
for (post in ral) {
items.push(post.ID > Unread.lastReadPost);
}
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
_results.push(ral.rm(item));
}
return _results;
},
readArray: function(arr) { readArray: function(arr) {
var i, post, _i, _len; var i, post, _i, _len;
@ -6528,28 +6438,26 @@
return arr.splice(0, i); return arr.splice(0, i);
}, },
read: function(e) { read: function(e) {
var bottom, height, key, post, posts; var bottom, height, i, post, posts, read, top, _ref;
if (d.hidden || !Unread.posts.length) { if (d.hidden || !Unread.posts.length) {
return; return;
} }
posts = Unread.posts;
height = doc.clientHeight; height = doc.clientHeight;
for (key in posts) { posts = Unread.posts;
post = posts[key]; read = [];
if (!posts.hasOwnProperty(key)) { i = posts.length;
continue; while (post = posts[--i]) {
_ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
if ((bottom < height) && (top > 0)) {
read.push(post);
posts.remove(post);
} }
bottom = post.nodes.root.getBoundingClientRect().bottom;
if (bottom > height) {
break;
}
Unread.posts.rm(post);
} }
if (!post) { if (!read.length) {
return; return;
} }
Unread.lastReadPost = post.ID; Unread.lastReadPost = read[read.length - 1].ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
Unread.readArray(Unread.postsQuotingYou); Unread.readArray(Unread.postsQuotingYou);
if (e) { if (e) {
@ -8295,79 +8203,51 @@
$.off(d, '4chanXInitFinished', QuoteThreading.setup); $.off(d, '4chanXInitFinished', QuoteThreading.setup);
posts = g.posts; posts = g.posts;
Unread.read();
Unread.update();
for (ID in posts) { for (ID in posts) {
post = posts[ID]; post = posts[ID];
if (post.cb) { if (post.cb) {
post.cb.call(post); post.cb.call(post);
} }
} }
return;
return QuoteThreading.hasRun = true; return QuoteThreading.hasRun = true;
}, },
node: function() { node: function() {
var ID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _j, _len, _len1; var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len;
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
return; return;
} }
quotes = this.quotes, ID = this.ID; quotes = this.quotes, ID = this.ID, fullID = this.fullID;
if (QuoteThreading.hasRun) { posts = g.posts;
posts = Unread.posts; if (!(post = posts[fullID]) || post.isHidden) {
if (!(post = posts[ID]) || post.isHidden) { return;
return;
}
} else {
posts = g.posts;
if (!(post = posts["" + g.BOARD + "." + ID]) || post.isHidden) {
return;
}
} }
uniq = {}; uniq = {};
if (QuoteThreading.hasRun) { len = ("" + g.BOARD).length + 1;
for (_i = 0, _len = quotes.length; _i < _len; _i++) { for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i]; quote = quotes[_i];
qid = quote.slice(2); qid = quote;
if (!(qid < ID)) { if (!(qid.slice(len) < ID)) {
continue; continue;
}
if (qid in posts) {
uniq[qid] = true;
}
} }
} else { if (qid in posts) {
len = ("" + g.BOARD).length + 1; uniq[qid.slice(len)] = true;
for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) {
quote = quotes[_j];
qid = quote;
if (!(qid.slice(len) < ID)) {
continue;
}
if (qid in posts) {
uniq[qid.slice(len)] = true;
}
} }
} }
keys = Object.keys(uniq); keys = Object.keys(uniq);
if (keys.length !== 1) { if (keys.length !== 1) {
return; return;
} }
this.threaded = keys[0]; this.threaded = "" + g.BOARD + "." + keys[0];
return this.cb = QuoteThreading.nodeinsert; return this.cb = QuoteThreading.nodeinsert;
}, },
nodeinsert: function() { nodeinsert: function() {
var pEl, pid, post, posts, ppost, qid, qpost, qroot, threadContainer, unread; var posts, qpost, qroot, threadContainer;
qid = this.threaded; posts = g.posts;
if (QuoteThreading.hasRun) { qpost = posts[this.threaded];
posts = Unread.posts; delete this.threaded;
qpost = posts[qid]; delete this.cb;
} else {
posts = g.posts;
unread = Unread.posts;
qpost = posts["" + g.BOARD + "." + qid];
}
if (this.thread.OP === qpost) { if (this.thread.OP === qpost) {
return; return;
} }
@ -8379,18 +8259,7 @@
}); });
$.after(qroot, threadContainer); $.after(qroot, threadContainer);
} }
$.add(threadContainer, this.nodes.root); return $.add(threadContainer, this.nodes.root);
pEl = $.x('preceding::div[contains(@class,"post reply")][1]/parent::div', this.nodes.root);
pid = pEl.id.slice(2);
if (QuoteThreading.hasRun) {
ppost = posts[pid];
} else {
ppost = posts[pid];
if (!((post = unread["" + g.BOARD + "." + this.id]) && (ppost = unread["" + g.BOARD + "." + pid]))) {
return;
}
}
return posts.after(ppost, this);
}, },
toggle: function() { toggle: function() {
var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results; var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results;

View File

@ -1,5 +1,5 @@
(function() { (function() {
var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, var $, $$, Anonymize, ArchiveLink, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DataBoards, DeleteLink, DownloadLink, ExpandComment, ExpandThread, Favicon, FileInfo, Filter, Fourchan, Get, Header, ImageExpand, ImageHover, ImageReplace, Keybinds, Linkify, Main, Menu, Nav, Notification, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
__slice = [].slice, __slice = [].slice,
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@ -1359,79 +1359,6 @@
})(); })();
RandomAccessList = (function() {
function RandomAccessList() {
this.first = null;
this.last = null;
this.length = 0;
}
RandomAccessList.prototype.push = function(id, post) {
var item, last;
last = this.last;
this[id] = item = post;
item.prev = last;
item.next = null;
this.last = item;
if (last) {
last.next = item;
} else {
this.first = item;
}
return this.length++;
};
RandomAccessList.prototype.shift = function() {
return this.rm(this.first.ID);
};
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.rm = function(id) {
var item;
item = this[id];
if (!item) {
return;
}
delete this[id];
this.length--;
return this.rmi(item);
};
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;
}
};
return RandomAccessList;
})();
Get = { Get = {
threadExcerpt: function(thread) { threadExcerpt: function(thread) {
var OP, excerpt, _ref; var OP, excerpt, _ref;
@ -6290,7 +6217,7 @@
this.hr = $.el('hr', { this.hr = $.el('hr', {
id: 'unread-line' id: 'unread-line'
}); });
this.posts = new RandomAccessList; this.posts = [];
this.postsQuotingYou = []; this.postsQuotingYou = [];
return Thread.prototype.callbacks.push({ return Thread.prototype.callbacks.push({
name: 'Unread', name: 'Unread',
@ -6374,16 +6301,14 @@
continue; continue;
} }
} }
Unread.posts.push(ID, post); Unread.posts.push(post);
Unread.addPostQuotingYou(post); Unread.addPostQuotingYou(post);
} }
if (Conf['Unread Line']) { if (Conf['Unread Line']) {
Unread.setLine(newPosts.contains(Unread.posts.first)); Unread.setLine(newPosts.contains(Unread.posts[0]));
}
if (!Conf['Quote Threading']) {
Unread.read();
return Unread.update();
} }
Unread.read();
return Unread.update();
}, },
addPostQuotingYou: function(post) { addPostQuotingYou: function(post) {
var quotelink, _i, _len, _ref; var quotelink, _i, _len, _ref;
@ -6407,15 +6332,14 @@
} }
}, },
readSinglePost: function(post) { readSinglePost: function(post) {
var ID, i; var i;
ID = post.ID; if ((i = Unread.posts.indexOf(post)) === -1) {
if (!Unread.posts[ID]) {
return; return;
} }
Unread.posts.rm(ID); Unread.posts.splice(i, 1);
if (!Unread.posts.first) { if (i === 0) {
Unread.lastReadPost = ID; Unread.lastReadPost = post.ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
} }
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) { if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
@ -6423,20 +6347,6 @@
} }
return Unread.update(); return Unread.update();
}, },
readRAL: function(ral) {
var item, items, post, _i, _len, _results;
items = [];
for (post in ral) {
items.push(post.ID > Unread.lastReadPost);
}
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
_results.push(ral.rm(item));
}
return _results;
},
readArray: function(arr) { readArray: function(arr) {
var i, post, _i, _len; var i, post, _i, _len;
@ -6449,28 +6359,26 @@
return arr.splice(0, i); return arr.splice(0, i);
}, },
read: function(e) { read: function(e) {
var bottom, height, key, post, posts; var bottom, height, i, post, posts, read, top, _ref;
if (d.hidden || !Unread.posts.length) { if (d.hidden || !Unread.posts.length) {
return; return;
} }
posts = Unread.posts;
height = doc.clientHeight; height = doc.clientHeight;
for (key in posts) { posts = Unread.posts;
post = posts[key]; read = [];
if (!posts.hasOwnProperty(key)) { i = posts.length;
continue; while (post = posts[--i]) {
_ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
if ((bottom < height) && (top > 0)) {
read.push(post);
posts.remove(post);
} }
bottom = post.nodes.root.getBoundingClientRect().bottom;
if (bottom > height) {
break;
}
Unread.posts.rm(post);
} }
if (!post) { if (!read.length) {
return; return;
} }
Unread.lastReadPost = post.ID; Unread.lastReadPost = read[read.length - 1].ID;
Unread.saveLastReadPost(); Unread.saveLastReadPost();
Unread.readArray(Unread.postsQuotingYou); Unread.readArray(Unread.postsQuotingYou);
if (e) { if (e) {
@ -8197,79 +8105,51 @@
$.off(d, '4chanXInitFinished', QuoteThreading.setup); $.off(d, '4chanXInitFinished', QuoteThreading.setup);
posts = g.posts; posts = g.posts;
Unread.read();
Unread.update();
for (ID in posts) { for (ID in posts) {
post = posts[ID]; post = posts[ID];
if (post.cb) { if (post.cb) {
post.cb.call(post); post.cb.call(post);
} }
} }
return;
return QuoteThreading.hasRun = true; return QuoteThreading.hasRun = true;
}, },
node: function() { node: function() {
var ID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _j, _len, _len1; var ID, fullID, keys, len, post, posts, qid, quote, quotes, uniq, _i, _len;
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) { if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
return; return;
} }
quotes = this.quotes, ID = this.ID; quotes = this.quotes, ID = this.ID, fullID = this.fullID;
if (QuoteThreading.hasRun) { posts = g.posts;
posts = Unread.posts; if (!(post = posts[fullID]) || post.isHidden) {
if (!(post = posts[ID]) || post.isHidden) { return;
return;
}
} else {
posts = g.posts;
if (!(post = posts["" + g.BOARD + "." + ID]) || post.isHidden) {
return;
}
} }
uniq = {}; uniq = {};
if (QuoteThreading.hasRun) { len = ("" + g.BOARD).length + 1;
for (_i = 0, _len = quotes.length; _i < _len; _i++) { for (_i = 0, _len = quotes.length; _i < _len; _i++) {
quote = quotes[_i]; quote = quotes[_i];
qid = quote.slice(2); qid = quote;
if (!(qid < ID)) { if (!(qid.slice(len) < ID)) {
continue; continue;
}
if (qid in posts) {
uniq[qid] = true;
}
} }
} else { if (qid in posts) {
len = ("" + g.BOARD).length + 1; uniq[qid.slice(len)] = true;
for (_j = 0, _len1 = quotes.length; _j < _len1; _j++) {
quote = quotes[_j];
qid = quote;
if (!(qid.slice(len) < ID)) {
continue;
}
if (qid in posts) {
uniq[qid.slice(len)] = true;
}
} }
} }
keys = Object.keys(uniq); keys = Object.keys(uniq);
if (keys.length !== 1) { if (keys.length !== 1) {
return; return;
} }
this.threaded = keys[0]; this.threaded = "" + g.BOARD + "." + keys[0];
return this.cb = QuoteThreading.nodeinsert; return this.cb = QuoteThreading.nodeinsert;
}, },
nodeinsert: function() { nodeinsert: function() {
var pEl, pid, post, posts, ppost, qid, qpost, qroot, threadContainer, unread; var posts, qpost, qroot, threadContainer;
qid = this.threaded; posts = g.posts;
if (QuoteThreading.hasRun) { qpost = posts[this.threaded];
posts = Unread.posts; delete this.threaded;
qpost = posts[qid]; delete this.cb;
} else {
posts = g.posts;
unread = Unread.posts;
qpost = posts["" + g.BOARD + "." + qid];
}
if (this.thread.OP === qpost) { if (this.thread.OP === qpost) {
return; return;
} }
@ -8281,18 +8161,7 @@
}); });
$.after(qroot, threadContainer); $.after(qroot, threadContainer);
} }
$.add(threadContainer, this.nodes.root); return $.add(threadContainer, this.nodes.root);
pEl = $.x('preceding::div[contains(@class,"post reply")][1]/parent::div', this.nodes.root);
pid = pEl.id.slice(2);
if (QuoteThreading.hasRun) {
ppost = posts[pid];
} else {
ppost = posts[pid];
if (!((post = unread["" + g.BOARD + "." + this.id]) && (ppost = unread["" + g.BOARD + "." + pid]))) {
return;
}
}
return posts.after(ppost, this);
}, },
toggle: function() { toggle: function() {
var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results; var container, containers, node, nodes, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _results;

View File

@ -5,7 +5,7 @@ Unread =
@db = new DataBoard 'lastReadPosts', @sync @db = new DataBoard 'lastReadPosts', @sync
@hr = $.el 'hr', @hr = $.el 'hr',
id: 'unread-line' id: 'unread-line'
@posts = new RandomAccessList @posts = []
@postsQuotingYou = [] @postsQuotingYou = []
Thread::callbacks.push Thread::callbacks.push
@ -19,7 +19,7 @@ Unread =
for ID, post of @posts for ID, post of @posts
posts.push post if post.isReply posts.push post if post.isReply
Unread.lastReadPost = Unread.db.get Unread.lastReadPost = Unread.db.get
boardID: @board.ID boardID: @board.ID
threadID: @ID threadID: @ID
defaultValue: 0 defaultValue: 0
Unread.addPosts posts Unread.addPosts posts
@ -62,14 +62,13 @@ Unread =
threadID: post.thread.ID threadID: post.thread.ID
postID: post.ID postID: post.ID
continue if QR.db.get data continue if QR.db.get data
Unread.posts.push ID, post 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 newPosts.contains Unread.posts.first Unread.setLine newPosts.contains Unread.posts[0]
unless Conf['Quote Threading'] Unread.read()
Unread.read() Unread.update()
Unread.update()
addPostQuotingYou: (post) -> addPostQuotingYou: (post) ->
return unless QR.db return unless QR.db
@ -85,22 +84,14 @@ Unread =
Unread.addPosts e.detail.newPosts Unread.addPosts e.detail.newPosts
readSinglePost: (post) -> readSinglePost: (post) ->
{ID} = post return if (i = Unread.posts.indexOf post) is -1
return unless Unread.posts[ID] Unread.posts.splice i, 1
Unread.posts.rm ID if i is 0
unless Unread.posts.first Unread.lastReadPost = post.ID
Unread.lastReadPost = ID
Unread.saveLastReadPost() Unread.saveLastReadPost()
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()
readRAL: (ral) ->
items = []
for post of ral
items.push post.ID > Unread.lastReadPost
for item in items
ral.rm item
readArray: (arr) -> readArray: (arr) ->
for post, i in arr for post, i in arr
@ -109,16 +100,19 @@ Unread =
read: (e) -> read: (e) ->
return if d.hidden or !Unread.posts.length return if d.hidden or !Unread.posts.length
height = doc.clientHeight
{posts} = Unread {posts} = Unread
height = doc.clientHeight read = []
for key, post of posts i = posts.length
continue unless posts.hasOwnProperty key
{bottom} = post.nodes.root.getBoundingClientRect()
break if bottom > height # post is not completely read
Unread.posts.rm post
return unless post
Unread.lastReadPost = post.ID while post = posts[--i]
{bottom, top} = post.nodes.root.getBoundingClientRect()
if (bottom < height) and (top > 0) # post is completely read
read.push post
posts.remove post
return unless read.length
Unread.lastReadPost = read[read.length - 1].ID
Unread.saveLastReadPost() Unread.saveLastReadPost()
Unread.readArray Unread.postsQuotingYou Unread.readArray Unread.postsQuotingYou
Unread.update() if e Unread.update() if e

View File

@ -28,13 +28,9 @@ QuoteThreading =
$.off d, '4chanXInitFinished', QuoteThreading.setup $.off d, '4chanXInitFinished', QuoteThreading.setup
{posts} = g {posts} = g
Unread.read()
Unread.update()
for ID, post of posts for ID, post of posts
if post.cb if post.cb
post.cb.call post post.cb.call post
return
QuoteThreading.hasRun = true QuoteThreading.hasRun = true
@ -48,46 +44,30 @@ QuoteThreading =
# Of course, implementing your own data structure can be awkward. # Of course, implementing your own data structure can be awkward.
return if @isClone or not QuoteThreading.enabled or @thread.OP is @ return if @isClone or not QuoteThreading.enabled or @thread.OP is @
{quotes, ID} = @ {quotes, ID, fullID} = @
if QuoteThreading.hasRun {posts} = g
{posts} = Unread return if !(post = posts[fullID]) or post.isHidden # Filtered
return if !(post = posts[ID]) or post.isHidden # Filtered
else
{posts} = g
return if !(post = posts["#{g.BOARD}.#{ID}"]) or post.isHidden # Filtered
uniq = {} uniq = {}
if QuoteThreading.hasRun len = "#{g.BOARD}".length + 1
for quote in quotes for quote in quotes
qid = quote[2..] qid = quote
continue unless qid < ID continue unless qid[len..] < ID
if qid of posts if qid of posts
uniq[qid] = true uniq[qid[len..]] = true
else
len = "#{g.BOARD}".length + 1
for quote in quotes
qid = quote
continue unless qid[len..] < ID
if qid of posts
uniq[qid[len..]] = true
keys = Object.keys uniq keys = Object.keys uniq
return unless keys.length is 1 return unless keys.length is 1
@threaded = keys[0] @threaded = "#{g.BOARD}.#{keys[0]}"
@cb = QuoteThreading.nodeinsert @cb = QuoteThreading.nodeinsert
nodeinsert: -> nodeinsert: ->
qid = @threaded {posts} = g
qpost = posts[@threaded]
if QuoteThreading.hasRun delete @threaded
{posts} = Unread delete @cb
qpost = posts[qid]
else
{posts} = g
unread = Unread.posts
qpost = posts["#{g.BOARD}.#{qid}"]
return if @thread.OP is qpost return if @thread.OP is qpost
@ -100,17 +80,6 @@ QuoteThreading =
$.add threadContainer, @nodes.root $.add threadContainer, @nodes.root
pEl = $.x 'preceding::div[contains(@class,"post reply")][1]/parent::div', @nodes.root
pid = pEl.id[2..]
if QuoteThreading.hasRun
ppost = posts[pid]
else
ppost = posts[pid]
return unless (post = unread["#{g.BOARD}.#{@id}"]) and (ppost = unread["#{g.BOARD}.#{pid}"])
posts.after ppost, @
toggle: -> toggle: ->
thread = $ '.thread' thread = $ '.thread'
replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread

View File

@ -3,5 +3,4 @@
<%= grunt.file.read('src/lib/post.class') %> <%= grunt.file.read('src/lib/post.class') %>
<%= grunt.file.read('src/lib/clone.class') %> <%= grunt.file.read('src/lib/clone.class') %>
<%= grunt.file.read('src/lib/databoard.class') %> <%= grunt.file.read('src/lib/databoard.class') %>
<%= grunt.file.read('src/lib/notification.class') %> <%= grunt.file.read('src/lib/notification.class') %>
<%= grunt.file.read('src/lib/randomaccesslist.class') %>

View File

@ -1,50 +0,0 @@
class RandomAccessList
constructor: ->
@first = null
@last = null
@length = 0
push: (id, post) ->
{last} = @
@[id] = item = post
item.prev = last
item.next = null
@last = item
if last
last.next = item
else
@first = item
@length++
shift: ->
@rm @first.ID
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
rm: (id) ->
item = @[id]
return unless item
delete @[id]
@length--
@rmi item
rmi: (item) ->
{prev, next} = item
if prev
prev.next = next
else
@first = next
if next
next.prev = prev
else
@last = prev