From 6574746e907e769a5de69e3cb2228581f161db74 Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Sat, 4 Jan 2014 13:38:09 -0700 Subject: [PATCH] Start working on putting in aeosynth's RandomAccessList For performance, obviously. --- LICENSE | 8 +- builds/4chan-X.user.js | 140 ++++++++++++++++++++----- builds/crx/script.js | 140 ++++++++++++++++++++----- src/General/lib/classes.coffee | 3 +- src/General/lib/randomaccesslist.class | 58 ++++++++++ src/Monitoring/Unread.coffee | 35 ++++--- src/Quotelinks/QuoteThreading.coffee | 5 +- 7 files changed, 311 insertions(+), 78 deletions(-) create mode 100644 src/General/lib/randomaccesslist.class diff --git a/LICENSE b/LICENSE index 38ffc24ad..5ea10f543 100755 --- a/LICENSE +++ b/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. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -8,11 +8,11 @@ * http://zixaphir.github.io/appchan-x/ * 4chan x Copyright © 2009-2011 James Campos * https://github.com/aeosynth/4chan-x -* 4chan x Copyright © 2012-2013 Nicolas Stepien +* 4chan x Copyright © 2012-2014 Nicolas Stepien * https://4chan-x.just-believe.in/ -* 4chan x Copyright © 2013-2013 Jordan Bates +* 4chan x Copyright © 2013-2014 Jordan Bates * http://seaweedchan.github.io/4chan-x/ -* 4chan x Copyright © 2012-2013 ihavenoface +* 4chan x Copyright © 2012-2014 ihavenoface * http://ihavenoface.github.io/4chan-x/ * 4chan SS Copyright © 2011-2013 Ahodesuka * https://github.com/ahodesuka/4chan-Style-Script/ diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 01a734513..4a33a03db 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -22,7 +22,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.2.44 - 2013-12-27 +* 4chan X - Version 1.2.44 - 2014-01-04 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -31,11 +31,11 @@ * http://zixaphir.github.io/appchan-x/ * 4chan x Copyright © 2009-2011 James Campos * https://github.com/aeosynth/4chan-x -* 4chan x Copyright © 2012-2013 Nicolas Stepien +* 4chan x Copyright © 2012-2014 Nicolas Stepien * https://4chan-x.just-believe.in/ -* 4chan x Copyright © 2013-2013 Jordan Bates +* 4chan x Copyright © 2013-2014 Jordan Bates * http://seaweedchan.github.io/4chan-x/ -* 4chan x Copyright © 2012-2013 ihavenoface +* 4chan x Copyright © 2012-2014 ihavenoface * http://ihavenoface.github.io/4chan-x/ * 4chan SS Copyright © 2011-2013 Ahodesuka * https://github.com/ahodesuka/4chan-Style-Script/ @@ -104,7 +104,7 @@ 'use strict'; (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; }, __slice = [].slice, __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 = { init: function() {}, notificationPermission: function() { @@ -4868,10 +4949,11 @@ return QuoteThreading.hasRun = true; }, 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) { return; } + replies = Unread.replies; quotes = this.quotes, ID = this.ID, fullID = this.fullID; posts = g.posts; if (!(post = posts[fullID]) || post.isHidden) { @@ -4907,7 +4989,7 @@ if (QuoteThreading.hasRun) { height = doc.clientHeight; _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; } } @@ -4926,6 +5008,7 @@ }, toggle: function() { var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; + Unread.replies = new RandomAccessList; thread = $('.thread'); replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); QuoteThreading.enabled = this.checked; @@ -9393,7 +9476,7 @@ this.hr = $.el('hr', { id: 'unread-line' }); - this.posts = []; + this.posts = new RandomAccessList; this.postsQuotingYou = []; return Thread.callbacks.push({ name: 'Unread', @@ -9437,7 +9520,7 @@ if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } - if (post = Unread.posts[0]) { + if (post = Unread.posts.first) { while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { if (!(post = Get.postFromRoot(root)).isHidden) { break; @@ -9458,7 +9541,7 @@ }); }, sync: function() { - var lastReadPost; + var lastReadPost, post; lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -9469,6 +9552,14 @@ } Unread.lastReadPost = lastReadPost; 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); if (Conf['Unread Line']) { Unread.setLine(); @@ -9546,12 +9637,13 @@ } }, readSinglePost: function(post) { - var i; - if ((i = Unread.posts.indexOf(post)) === -1) { + var ID, i; + ID = post.ID; + if (!Unread.posts[ID]) { return; } - Unread.posts.splice(i, 1); - if (i === 0) { + Unread.posts.splice(ID(post.next.ID)); + if (post === Unread.posts.first) { Unread.lastReadPost = post.ID; Unread.saveLastReadPost(); } @@ -9571,14 +9663,14 @@ return arr.splice(0, i); }, read: $.debounce(50, function(e) { - var ID, height, i, post, posts; + var ID, height, post, posts; if (d.hidden || !Unread.posts.length) { return; } height = doc.clientHeight; posts = Unread.posts; - i = 0; - while (post = posts[i]) { + post = posts.first; + while (post) { if (Header.getBottomOf(post.nodes.root) > -1) { ID = post.ID; if (Conf['Mark Quotes of You']) { @@ -9586,23 +9678,15 @@ QuoteYou.lastRead = post.nodes.root; } } - if (Conf['Quote Threading']) { - posts.splice(i, 1); - continue; - } + post = post.next; } else { - if (!Conf['Quote Threading']) { - break; - } + break; } - i++; - } - if (i && !Conf['Quote Threading']) { - posts.splice(0, i); } if (!ID) { return; } + posts.splice(0, ID); if (Unread.lastReadPost < ID || !Unread.lastReadPost) { Unread.lastReadPost = ID; } diff --git a/builds/crx/script.js b/builds/crx/script.js index dac844bf7..28c04d8ab 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // 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. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -9,11 +9,11 @@ * http://zixaphir.github.io/appchan-x/ * 4chan x Copyright © 2009-2011 James Campos * https://github.com/aeosynth/4chan-x -* 4chan x Copyright © 2012-2013 Nicolas Stepien +* 4chan x Copyright © 2012-2014 Nicolas Stepien * https://4chan-x.just-believe.in/ -* 4chan x Copyright © 2013-2013 Jordan Bates +* 4chan x Copyright © 2013-2014 Jordan Bates * http://seaweedchan.github.io/4chan-x/ -* 4chan x Copyright © 2012-2013 ihavenoface +* 4chan x Copyright © 2012-2014 ihavenoface * http://ihavenoface.github.io/4chan-x/ * 4chan SS Copyright © 2011-2013 Ahodesuka * https://github.com/ahodesuka/4chan-Style-Script/ @@ -82,7 +82,7 @@ 'use strict'; (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; }, __slice = [].slice, __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 = { init: function() { this.notificationPermission(); @@ -4886,10 +4967,11 @@ return QuoteThreading.hasRun = true; }, 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) { return; } + replies = Unread.replies; quotes = this.quotes, ID = this.ID, fullID = this.fullID; posts = g.posts; if (!(post = posts[fullID]) || post.isHidden) { @@ -4925,7 +5007,7 @@ if (QuoteThreading.hasRun) { height = doc.clientHeight; _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; } } @@ -4944,6 +5026,7 @@ }, toggle: function() { var container, containers, node, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; + Unread.replies = new RandomAccessList; thread = $('.thread'); replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); QuoteThreading.enabled = this.checked; @@ -9391,7 +9474,7 @@ this.hr = $.el('hr', { id: 'unread-line' }); - this.posts = []; + this.posts = new RandomAccessList; this.postsQuotingYou = []; return Thread.callbacks.push({ name: 'Unread', @@ -9435,7 +9518,7 @@ if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } - if (post = Unread.posts[0]) { + if (post = Unread.posts.first) { while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { if (!(post = Get.postFromRoot(root)).isHidden) { break; @@ -9456,7 +9539,7 @@ }); }, sync: function() { - var lastReadPost; + var lastReadPost, post; lastReadPost = Unread.db.get({ boardID: Unread.thread.board.ID, threadID: Unread.thread.ID, @@ -9467,6 +9550,14 @@ } Unread.lastReadPost = lastReadPost; 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); if (Conf['Unread Line']) { Unread.setLine(); @@ -9544,12 +9635,13 @@ } }, readSinglePost: function(post) { - var i; - if ((i = Unread.posts.indexOf(post)) === -1) { + var ID, i; + ID = post.ID; + if (!Unread.posts[ID]) { return; } - Unread.posts.splice(i, 1); - if (i === 0) { + Unread.posts.splice(ID(post.next.ID)); + if (post === Unread.posts.first) { Unread.lastReadPost = post.ID; Unread.saveLastReadPost(); } @@ -9569,14 +9661,14 @@ return arr.splice(0, i); }, read: $.debounce(50, function(e) { - var ID, height, i, post, posts; + var ID, height, post, posts; if (d.hidden || !Unread.posts.length) { return; } height = doc.clientHeight; posts = Unread.posts; - i = 0; - while (post = posts[i]) { + post = posts.first; + while (post) { if (Header.getBottomOf(post.nodes.root) > -1) { ID = post.ID; if (Conf['Mark Quotes of You']) { @@ -9584,23 +9676,15 @@ QuoteYou.lastRead = post.nodes.root; } } - if (Conf['Quote Threading']) { - posts.splice(i, 1); - continue; - } + post = post.next; } else { - if (!Conf['Quote Threading']) { - break; - } + break; } - i++; - } - if (i && !Conf['Quote Threading']) { - posts.splice(0, i); } if (!ID) { return; } + posts.splice(0, ID); if (Unread.lastReadPost < ID || !Unread.lastReadPost) { Unread.lastReadPost = ID; } diff --git a/src/General/lib/classes.coffee b/src/General/lib/classes.coffee index 74697eec3..63c33645e 100755 --- a/src/General/lib/classes.coffee +++ b/src/General/lib/classes.coffee @@ -3,4 +3,5 @@ <%= grunt.file.read('src/General/lib/post.class') %> <%= grunt.file.read('src/General/lib/clone.class') %> <%= grunt.file.read('src/General/lib/databoard.class') %> -<%= grunt.file.read('src/General/lib/notice.class') %> \ No newline at end of file +<%= grunt.file.read('src/General/lib/notice.class') %> +<%= grunt.file.read('src/General/lib/randomaccesslist.class') %> \ No newline at end of file diff --git a/src/General/lib/randomaccesslist.class b/src/General/lib/randomaccesslist.class new file mode 100644 index 000000000..c53a0c932 --- /dev/null +++ b/src/General/lib/randomaccesslist.class @@ -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 \ No newline at end of file diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 36d5f5213..e0d475ef1 100755 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -5,7 +5,7 @@ Unread = @db = new DataBoard 'lastReadPosts', @sync @hr = $.el 'hr', id: 'unread-line' - @posts = [] + @posts = new RandomAccessList @postsQuotingYou = [] Thread.callbacks.push @@ -36,7 +36,7 @@ Unread = return unless Conf['Scroll to Last Read Post'] # Let the header's onload callback handle it. 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. while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root break unless (post = Get.postFromRoot root).isHidden @@ -60,6 +60,13 @@ Unread = return unless Unread.lastReadPost < lastReadPost Unread.lastReadPost = lastReadPost 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.setLine() if Conf['Unread Line'] Unread.update() @@ -114,9 +121,10 @@ Unread = Unread.addPosts e.detail.newPosts readSinglePost: (post) -> - return if (i = Unread.posts.indexOf post) is -1 - Unread.posts.splice i, 1 - if i is 0 + {ID} = post + return unless Unread.posts[ID] + Unread.posts.splice ID post.next.ID + if post is Unread.posts.first Unread.lastReadPost = post.ID Unread.saveLastReadPost() if (i = Unread.postsQuotingYou.indexOf post) isnt -1 @@ -132,27 +140,22 @@ Unread = return if d.hidden or !Unread.posts.length height = doc.clientHeight {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 {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 + post = post.next else - unless Conf['Quote Threading'] - break - i++ - - if i and !Conf['Quote Threading'] - posts.splice 0, i + break return unless ID + posts.splice 0, ID Unread.lastReadPost = ID if Unread.lastReadPost < ID or !Unread.lastReadPost Unread.saveLastReadPost() Unread.readArray Unread.postsQuotingYou diff --git a/src/Quotelinks/QuoteThreading.coffee b/src/Quotelinks/QuoteThreading.coffee index 3287c9a4f..0bc8981f4 100755 --- a/src/Quotelinks/QuoteThreading.coffee +++ b/src/Quotelinks/QuoteThreading.coffee @@ -36,6 +36,8 @@ QuoteThreading = node: -> return if @isClone or not QuoteThreading.enabled or @thread.OP is @ + + {replies} = Unread {quotes, ID, fullID} = @ {posts} = g @@ -68,7 +70,7 @@ QuoteThreading = {bottom, top} = qpost.nodes.root.getBoundingClientRect() # 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 unless $.hasClass qroot, 'threadOP' @@ -83,6 +85,7 @@ QuoteThreading = return true toggle: -> + Unread.replies = new RandomAccessList thread = $ '.thread' replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread QuoteThreading.enabled = @checked