Start working on putting in aeosynth's RandomAccessList
For performance, obviously.
This commit is contained in:
parent
43751a00b8
commit
6574746e90
8
LICENSE
8
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.2.44 - 2013-12-27
|
* 4chan X - Version 1.2.44 - 2014-01-04
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
||||||
@ -8,11 +8,11 @@
|
|||||||
* http://zixaphir.github.io/appchan-x/
|
* http://zixaphir.github.io/appchan-x/
|
||||||
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
* https://github.com/aeosynth/4chan-x
|
* https://github.com/aeosynth/4chan-x
|
||||||
* 4chan x Copyright © 2012-2013 Nicolas Stepien <stepien.nicolas@gmail.com>
|
* 4chan x Copyright © 2012-2014 Nicolas Stepien <stepien.nicolas@gmail.com>
|
||||||
* https://4chan-x.just-believe.in/
|
* https://4chan-x.just-believe.in/
|
||||||
* 4chan x Copyright © 2013-2013 Jordan Bates <saudrapsmann@gmail.com>
|
* 4chan x Copyright © 2013-2014 Jordan Bates <saudrapsmann@gmail.com>
|
||||||
* http://seaweedchan.github.io/4chan-x/
|
* http://seaweedchan.github.io/4chan-x/
|
||||||
* 4chan x Copyright © 2012-2013 ihavenoface
|
* 4chan x Copyright © 2012-2014 ihavenoface
|
||||||
* http://ihavenoface.github.io/4chan-x/
|
* http://ihavenoface.github.io/4chan-x/
|
||||||
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
||||||
* https://github.com/ahodesuka/4chan-Style-Script/
|
* https://github.com/ahodesuka/4chan-Style-Script/
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.2.44 - 2013-12-27
|
* 4chan X - Version 1.2.44 - 2014-01-04
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
||||||
@ -31,11 +31,11 @@
|
|||||||
* http://zixaphir.github.io/appchan-x/
|
* http://zixaphir.github.io/appchan-x/
|
||||||
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
* https://github.com/aeosynth/4chan-x
|
* https://github.com/aeosynth/4chan-x
|
||||||
* 4chan x Copyright © 2012-2013 Nicolas Stepien <stepien.nicolas@gmail.com>
|
* 4chan x Copyright © 2012-2014 Nicolas Stepien <stepien.nicolas@gmail.com>
|
||||||
* https://4chan-x.just-believe.in/
|
* https://4chan-x.just-believe.in/
|
||||||
* 4chan x Copyright © 2013-2013 Jordan Bates <saudrapsmann@gmail.com>
|
* 4chan x Copyright © 2013-2014 Jordan Bates <saudrapsmann@gmail.com>
|
||||||
* http://seaweedchan.github.io/4chan-x/
|
* http://seaweedchan.github.io/4chan-x/
|
||||||
* 4chan x Copyright © 2012-2013 ihavenoface
|
* 4chan x Copyright © 2012-2014 ihavenoface
|
||||||
* http://ihavenoface.github.io/4chan-x/
|
* http://ihavenoface.github.io/4chan-x/
|
||||||
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
||||||
* https://github.com/ahodesuka/4chan-Style-Script/
|
* https://github.com/ahodesuka/4chan-Style-Script/
|
||||||
@ -104,7 +104,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
|
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, Keybinds, Linkify, Main, 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, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
|
||||||
__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,
|
||||||
@ -1458,6 +1458,87 @@
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
RandomAccessList = (function() {
|
||||||
|
function RandomAccessList() {
|
||||||
|
this.first = null;
|
||||||
|
this.last = null;
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomAccessList.prototype.push = function(item) {
|
||||||
|
var ID, last;
|
||||||
|
ID = item.ID;
|
||||||
|
last = this.last;
|
||||||
|
$.extend(item, {
|
||||||
|
prev: last,
|
||||||
|
next: null
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
next.prev = root.next = item;
|
||||||
|
item.prev = root;
|
||||||
|
return item.next = next;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.shift = function() {
|
||||||
|
return this.rm(this.first.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.splice = function(start, end) {
|
||||||
|
var cur, next;
|
||||||
|
if (!this[end]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur = start === 0 ? this.first : this[start];
|
||||||
|
while (cur !== this[end]) {
|
||||||
|
if (!(next = cur.next, cur)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rm(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
Polyfill = {
|
Polyfill = {
|
||||||
init: function() {},
|
init: function() {},
|
||||||
notificationPermission: function() {
|
notificationPermission: function() {
|
||||||
@ -4868,10 +4949,11 @@
|
|||||||
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 ID, fullID, keys, len, post, posts, qid, quote, quotes, replies, uniq, _i, _len;
|
||||||
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
replies = Unread.replies;
|
||||||
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
||||||
posts = g.posts;
|
posts = g.posts;
|
||||||
if (!(post = posts[fullID]) || post.isHidden) {
|
if (!(post = posts[fullID]) || post.isHidden) {
|
||||||
@ -4907,7 +4989,7 @@
|
|||||||
if (QuoteThreading.hasRun) {
|
if (QuoteThreading.hasRun) {
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
||||||
if (!(__indexOf.call(Unread.posts, qpost) >= 0 || ((bottom < height) && (top > 0)))) {
|
if (!(Unread.posts[qpost.ID] || ((bottom < height) && (top > 0)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4926,6 +5008,7 @@
|
|||||||
},
|
},
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||||
|
Unread.replies = new RandomAccessList;
|
||||||
thread = $('.thread');
|
thread = $('.thread');
|
||||||
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
||||||
QuoteThreading.enabled = this.checked;
|
QuoteThreading.enabled = this.checked;
|
||||||
@ -9393,7 +9476,7 @@
|
|||||||
this.hr = $.el('hr', {
|
this.hr = $.el('hr', {
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
});
|
});
|
||||||
this.posts = [];
|
this.posts = new RandomAccessList;
|
||||||
this.postsQuotingYou = [];
|
this.postsQuotingYou = [];
|
||||||
return Thread.callbacks.push({
|
return Thread.callbacks.push({
|
||||||
name: 'Unread',
|
name: 'Unread',
|
||||||
@ -9437,7 +9520,7 @@
|
|||||||
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;
|
||||||
@ -9458,7 +9541,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var 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,
|
||||||
@ -9469,6 +9552,14 @@
|
|||||||
}
|
}
|
||||||
Unread.lastReadPost = lastReadPost;
|
Unread.lastReadPost = lastReadPost;
|
||||||
Unread.readArray(Unread.posts);
|
Unread.readArray(Unread.posts);
|
||||||
|
post = Unread.posts.first;
|
||||||
|
while (post) {
|
||||||
|
if (post.ID > Unread.lastReadPost) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
post = post.next;
|
||||||
|
}
|
||||||
|
Unread.posts.splice(0, i);
|
||||||
Unread.readArray(Unread.postsQuotingYou);
|
Unread.readArray(Unread.postsQuotingYou);
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine();
|
Unread.setLine();
|
||||||
@ -9546,12 +9637,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
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);
|
Unread.posts.splice(ID(post.next.ID));
|
||||||
if (i === 0) {
|
if (post === Unread.posts.first) {
|
||||||
Unread.lastReadPost = post.ID;
|
Unread.lastReadPost = post.ID;
|
||||||
Unread.saveLastReadPost();
|
Unread.saveLastReadPost();
|
||||||
}
|
}
|
||||||
@ -9571,14 +9663,14 @@
|
|||||||
return arr.splice(0, i);
|
return arr.splice(0, i);
|
||||||
},
|
},
|
||||||
read: $.debounce(50, function(e) {
|
read: $.debounce(50, 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;
|
post = posts.first;
|
||||||
while (post = posts[i]) {
|
while (post) {
|
||||||
if (Header.getBottomOf(post.nodes.root) > -1) {
|
if (Header.getBottomOf(post.nodes.root) > -1) {
|
||||||
ID = post.ID;
|
ID = post.ID;
|
||||||
if (Conf['Mark Quotes of You']) {
|
if (Conf['Mark Quotes of You']) {
|
||||||
@ -9586,23 +9678,15 @@
|
|||||||
QuoteYou.lastRead = post.nodes.root;
|
QuoteYou.lastRead = post.nodes.root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Conf['Quote Threading']) {
|
post = post.next;
|
||||||
posts.splice(i, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!Conf['Quote Threading']) {
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i && !Conf['Quote Threading']) {
|
|
||||||
posts.splice(0, i);
|
|
||||||
}
|
}
|
||||||
if (!ID) {
|
if (!ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
posts.splice(0, ID);
|
||||||
if (Unread.lastReadPost < ID || !Unread.lastReadPost) {
|
if (Unread.lastReadPost < ID || !Unread.lastReadPost) {
|
||||||
Unread.lastReadPost = ID;
|
Unread.lastReadPost = ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// Generated by CoffeeScript
|
// Generated by CoffeeScript
|
||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.2.44 - 2013-12-27
|
* 4chan X - Version 1.2.44 - 2014-01-04
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
||||||
@ -9,11 +9,11 @@
|
|||||||
* http://zixaphir.github.io/appchan-x/
|
* http://zixaphir.github.io/appchan-x/
|
||||||
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
* 4chan x Copyright © 2009-2011 James Campos <james.r.campos@gmail.com>
|
||||||
* https://github.com/aeosynth/4chan-x
|
* https://github.com/aeosynth/4chan-x
|
||||||
* 4chan x Copyright © 2012-2013 Nicolas Stepien <stepien.nicolas@gmail.com>
|
* 4chan x Copyright © 2012-2014 Nicolas Stepien <stepien.nicolas@gmail.com>
|
||||||
* https://4chan-x.just-believe.in/
|
* https://4chan-x.just-believe.in/
|
||||||
* 4chan x Copyright © 2013-2013 Jordan Bates <saudrapsmann@gmail.com>
|
* 4chan x Copyright © 2013-2014 Jordan Bates <saudrapsmann@gmail.com>
|
||||||
* http://seaweedchan.github.io/4chan-x/
|
* http://seaweedchan.github.io/4chan-x/
|
||||||
* 4chan x Copyright © 2012-2013 ihavenoface
|
* 4chan x Copyright © 2012-2014 ihavenoface
|
||||||
* http://ihavenoface.github.io/4chan-x/
|
* http://ihavenoface.github.io/4chan-x/
|
||||||
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
* 4chan SS Copyright © 2011-2013 Ahodesuka
|
||||||
* https://github.com/ahodesuka/4chan-Style-Script/
|
* https://github.com/ahodesuka/4chan-Style-Script/
|
||||||
@ -82,7 +82,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
|
var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Index, InfiniScroll, Keybinds, Linkify, Main, 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, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g,
|
||||||
__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,
|
||||||
@ -1479,6 +1479,87 @@
|
|||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
RandomAccessList = (function() {
|
||||||
|
function RandomAccessList() {
|
||||||
|
this.first = null;
|
||||||
|
this.last = null;
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomAccessList.prototype.push = function(item) {
|
||||||
|
var ID, last;
|
||||||
|
ID = item.ID;
|
||||||
|
last = this.last;
|
||||||
|
$.extend(item, {
|
||||||
|
prev: last,
|
||||||
|
next: null
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
next.prev = root.next = item;
|
||||||
|
item.prev = root;
|
||||||
|
return item.next = next;
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.shift = function() {
|
||||||
|
return this.rm(this.first.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
RandomAccessList.prototype.splice = function(start, end) {
|
||||||
|
var cur, next;
|
||||||
|
if (!this[end]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur = start === 0 ? this.first : this[start];
|
||||||
|
while (cur !== this[end]) {
|
||||||
|
if (!(next = cur.next, cur)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.rm(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
Polyfill = {
|
Polyfill = {
|
||||||
init: function() {
|
init: function() {
|
||||||
this.notificationPermission();
|
this.notificationPermission();
|
||||||
@ -4886,10 +4967,11 @@
|
|||||||
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 ID, fullID, keys, len, post, posts, qid, quote, quotes, replies, uniq, _i, _len;
|
||||||
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
if (this.isClone || !QuoteThreading.enabled || this.thread.OP === this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
replies = Unread.replies;
|
||||||
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
quotes = this.quotes, ID = this.ID, fullID = this.fullID;
|
||||||
posts = g.posts;
|
posts = g.posts;
|
||||||
if (!(post = posts[fullID]) || post.isHidden) {
|
if (!(post = posts[fullID]) || post.isHidden) {
|
||||||
@ -4925,7 +5007,7 @@
|
|||||||
if (QuoteThreading.hasRun) {
|
if (QuoteThreading.hasRun) {
|
||||||
height = doc.clientHeight;
|
height = doc.clientHeight;
|
||||||
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
_ref = qpost.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
|
||||||
if (!(__indexOf.call(Unread.posts, qpost) >= 0 || ((bottom < height) && (top > 0)))) {
|
if (!(Unread.posts[qpost.ID] || ((bottom < height) && (top > 0)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4944,6 +5026,7 @@
|
|||||||
},
|
},
|
||||||
toggle: function() {
|
toggle: function() {
|
||||||
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||||
|
Unread.replies = new RandomAccessList;
|
||||||
thread = $('.thread');
|
thread = $('.thread');
|
||||||
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread);
|
||||||
QuoteThreading.enabled = this.checked;
|
QuoteThreading.enabled = this.checked;
|
||||||
@ -9391,7 +9474,7 @@
|
|||||||
this.hr = $.el('hr', {
|
this.hr = $.el('hr', {
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
});
|
});
|
||||||
this.posts = [];
|
this.posts = new RandomAccessList;
|
||||||
this.postsQuotingYou = [];
|
this.postsQuotingYou = [];
|
||||||
return Thread.callbacks.push({
|
return Thread.callbacks.push({
|
||||||
name: 'Unread',
|
name: 'Unread',
|
||||||
@ -9435,7 +9518,7 @@
|
|||||||
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;
|
||||||
@ -9456,7 +9539,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
sync: function() {
|
sync: function() {
|
||||||
var lastReadPost;
|
var 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,
|
||||||
@ -9467,6 +9550,14 @@
|
|||||||
}
|
}
|
||||||
Unread.lastReadPost = lastReadPost;
|
Unread.lastReadPost = lastReadPost;
|
||||||
Unread.readArray(Unread.posts);
|
Unread.readArray(Unread.posts);
|
||||||
|
post = Unread.posts.first;
|
||||||
|
while (post) {
|
||||||
|
if (post.ID > Unread.lastReadPost) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
post = post.next;
|
||||||
|
}
|
||||||
|
Unread.posts.splice(0, i);
|
||||||
Unread.readArray(Unread.postsQuotingYou);
|
Unread.readArray(Unread.postsQuotingYou);
|
||||||
if (Conf['Unread Line']) {
|
if (Conf['Unread Line']) {
|
||||||
Unread.setLine();
|
Unread.setLine();
|
||||||
@ -9544,12 +9635,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
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);
|
Unread.posts.splice(ID(post.next.ID));
|
||||||
if (i === 0) {
|
if (post === Unread.posts.first) {
|
||||||
Unread.lastReadPost = post.ID;
|
Unread.lastReadPost = post.ID;
|
||||||
Unread.saveLastReadPost();
|
Unread.saveLastReadPost();
|
||||||
}
|
}
|
||||||
@ -9569,14 +9661,14 @@
|
|||||||
return arr.splice(0, i);
|
return arr.splice(0, i);
|
||||||
},
|
},
|
||||||
read: $.debounce(50, function(e) {
|
read: $.debounce(50, 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;
|
post = posts.first;
|
||||||
while (post = posts[i]) {
|
while (post) {
|
||||||
if (Header.getBottomOf(post.nodes.root) > -1) {
|
if (Header.getBottomOf(post.nodes.root) > -1) {
|
||||||
ID = post.ID;
|
ID = post.ID;
|
||||||
if (Conf['Mark Quotes of You']) {
|
if (Conf['Mark Quotes of You']) {
|
||||||
@ -9584,23 +9676,15 @@
|
|||||||
QuoteYou.lastRead = post.nodes.root;
|
QuoteYou.lastRead = post.nodes.root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Conf['Quote Threading']) {
|
post = post.next;
|
||||||
posts.splice(i, 1);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!Conf['Quote Threading']) {
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i && !Conf['Quote Threading']) {
|
|
||||||
posts.splice(0, i);
|
|
||||||
}
|
}
|
||||||
if (!ID) {
|
if (!ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
posts.splice(0, ID);
|
||||||
if (Unread.lastReadPost < ID || !Unread.lastReadPost) {
|
if (Unread.lastReadPost < ID || !Unread.lastReadPost) {
|
||||||
Unread.lastReadPost = ID;
|
Unread.lastReadPost = ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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') %>
|
||||||
58
src/General/lib/randomaccesslist.class
Normal file
58
src/General/lib/randomaccesslist.class
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
class RandomAccessList
|
||||||
|
constructor: ->
|
||||||
|
@first = null
|
||||||
|
@last = null
|
||||||
|
@length = 0
|
||||||
|
|
||||||
|
push: (item) ->
|
||||||
|
{ID} = item
|
||||||
|
{last} = @
|
||||||
|
$.extend item,
|
||||||
|
prev: last
|
||||||
|
next: null
|
||||||
|
@[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
|
||||||
|
|
||||||
|
next.prev = root.next = item
|
||||||
|
item.prev = root
|
||||||
|
item.next = next
|
||||||
|
|
||||||
|
shift: ->
|
||||||
|
@rm @first.ID
|
||||||
|
|
||||||
|
splice: (start, end) ->
|
||||||
|
return unless @[end]
|
||||||
|
cur = if start is 0 then @first else @[start]
|
||||||
|
while cur isnt @[end]
|
||||||
|
return unless {next} = cur
|
||||||
|
@rm cur
|
||||||
|
cur = next
|
||||||
|
|
||||||
|
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
|
||||||
@ -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 = []
|
@posts = new RandomAccessList
|
||||||
@postsQuotingYou = []
|
@postsQuotingYou = []
|
||||||
|
|
||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
@ -36,7 +36,7 @@ Unread =
|
|||||||
return unless Conf['Scroll to Last Read Post']
|
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
|
||||||
@ -60,6 +60,13 @@ Unread =
|
|||||||
return unless Unread.lastReadPost < lastReadPost
|
return unless Unread.lastReadPost < lastReadPost
|
||||||
Unread.lastReadPost = lastReadPost
|
Unread.lastReadPost = lastReadPost
|
||||||
Unread.readArray Unread.posts
|
Unread.readArray Unread.posts
|
||||||
|
|
||||||
|
post = Unread.posts.first
|
||||||
|
while post
|
||||||
|
break if post.ID > Unread.lastReadPost
|
||||||
|
post = post.next
|
||||||
|
Unread.posts.splice 0, i
|
||||||
|
|
||||||
Unread.readArray Unread.postsQuotingYou
|
Unread.readArray Unread.postsQuotingYou
|
||||||
Unread.setLine() if Conf['Unread Line']
|
Unread.setLine() if Conf['Unread Line']
|
||||||
Unread.update()
|
Unread.update()
|
||||||
@ -114,9 +121,10 @@ 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
|
Unread.posts.splice ID post.next.ID
|
||||||
|
if post is Unread.posts.first
|
||||||
Unread.lastReadPost = post.ID
|
Unread.lastReadPost = post.ID
|
||||||
Unread.saveLastReadPost()
|
Unread.saveLastReadPost()
|
||||||
if (i = Unread.postsQuotingYou.indexOf post) isnt -1
|
if (i = Unread.postsQuotingYou.indexOf post) isnt -1
|
||||||
@ -132,27 +140,22 @@ Unread =
|
|||||||
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[i]
|
post = posts.first
|
||||||
|
|
||||||
|
while post
|
||||||
if Header.getBottomOf(post.nodes.root) > -1 # post is not completely read
|
if Header.getBottomOf(post.nodes.root) > -1 # post is not completely read
|
||||||
{ID} = post
|
{ID} = post
|
||||||
if Conf['Mark Quotes of You']
|
if Conf['Mark Quotes of You']
|
||||||
if post.info.yours
|
if post.info.yours
|
||||||
QuoteYou.lastRead = post.nodes.root
|
QuoteYou.lastRead = post.nodes.root
|
||||||
if Conf['Quote Threading']
|
post = post.next
|
||||||
posts.splice i, 1
|
|
||||||
continue
|
|
||||||
else
|
else
|
||||||
unless Conf['Quote Threading']
|
break
|
||||||
break
|
|
||||||
i++
|
|
||||||
|
|
||||||
if i and !Conf['Quote Threading']
|
|
||||||
posts.splice 0, i
|
|
||||||
|
|
||||||
return unless ID
|
return unless ID
|
||||||
|
|
||||||
|
posts.splice 0, ID
|
||||||
Unread.lastReadPost = ID if Unread.lastReadPost < ID or !Unread.lastReadPost
|
Unread.lastReadPost = ID if Unread.lastReadPost < ID or !Unread.lastReadPost
|
||||||
Unread.saveLastReadPost()
|
Unread.saveLastReadPost()
|
||||||
Unread.readArray Unread.postsQuotingYou
|
Unread.readArray Unread.postsQuotingYou
|
||||||
|
|||||||
@ -37,6 +37,8 @@ QuoteThreading =
|
|||||||
node: ->
|
node: ->
|
||||||
return if @isClone or not QuoteThreading.enabled or @thread.OP is @
|
return if @isClone or not QuoteThreading.enabled or @thread.OP is @
|
||||||
|
|
||||||
|
{replies} = Unread
|
||||||
|
|
||||||
{quotes, ID, fullID} = @
|
{quotes, ID, fullID} = @
|
||||||
{posts} = g
|
{posts} = g
|
||||||
return if !(post = posts[fullID]) or post.isHidden # Filtered
|
return if !(post = posts[fullID]) or post.isHidden # Filtered
|
||||||
@ -68,7 +70,7 @@ QuoteThreading =
|
|||||||
{bottom, top} = qpost.nodes.root.getBoundingClientRect()
|
{bottom, top} = qpost.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 Unread.posts[qpost.ID] or ((bottom < height) and (top > 0))
|
||||||
|
|
||||||
qroot = qpost.nodes.root
|
qroot = qpost.nodes.root
|
||||||
unless $.hasClass qroot, 'threadOP'
|
unless $.hasClass qroot, 'threadOP'
|
||||||
@ -83,6 +85,7 @@ QuoteThreading =
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
toggle: ->
|
toggle: ->
|
||||||
|
Unread.replies = new RandomAccessList
|
||||||
thread = $ '.thread'
|
thread = $ '.thread'
|
||||||
replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread
|
replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread
|
||||||
QuoteThreading.enabled = @checked
|
QuoteThreading.enabled = @checked
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user