From 80dd30def01b600d21b61af7d6fee446236aa82e Mon Sep 17 00:00:00 2001 From: Zixaphir Date: Tue, 7 Jan 2014 10:17:46 -0700 Subject: [PATCH] Optimizations to QuoteThreading (again) --- builds/4chan-X.user.js | 186 ++++++++++++------------- builds/crx/script.js | 186 ++++++++++++------------- src/General/Main.coffee | 29 ++-- src/General/lib/randomaccesslist.class | 11 +- src/Monitoring/Unread.coffee | 2 +- src/Quotelinks/QuoteThreading.coffee | 57 +++----- 6 files changed, 216 insertions(+), 255 deletions(-) diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 56eda2ff0..ffff9a1c3 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1534,19 +1534,6 @@ } }; - RandomAccessList.prototype.closest = function(ID) { - var item, prev; - item = this.first; - while (item) { - if (item.ID > ID) { - prev = item.prev; - break; - } - item = item.next; - } - return (prev ? prev.ID : -1); - }; - return RandomAccessList; })(); @@ -4951,16 +4938,18 @@ }); }, setup: function() { - var ID, post, _ref; $.off(d, '4chanXInitFinished', QuoteThreading.setup); + return QuoteThreading.force(); + }, + force: function() { + var ID, post, _ref; _ref = g.posts; for (ID in _ref) { post = _ref[ID]; if (post.cb) { - post.cb(); + post.cb(true); } } - return QuoteThreading.hasRun = true; }, node: function() { var keys, len, post, posts, quote, _i, _len, _ref; @@ -4989,82 +4978,85 @@ this.threaded = keys[0]; return this.cb = QuoteThreading.nodeinsert; }, - nodeinsert: function() { - var ID, bottom, height, post, posts, root, threadContainer, top, _ref; + nodeinsert: function(force) { + var bottom, height, post, posts, root, threadContainer, top, _ref; post = g.posts[this.threaded]; posts = Unread.posts; + root = post.nodes.root; if (this.thread.OP === post) { return false; } - if (QuoteThreading.hasRun) { + if (!force) { height = doc.clientHeight; - _ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top; - if (!((posts != null ? posts[post.ID] : void 0) || ((bottom < height) && (top > 0)))) { + _ref = root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top; + if (!((Conf['Unread Count'] && posts[post.ID]) || ((bottom < height) && (top > 0)))) { return false; } } - root = post.nodes.root; - if (!$.hasClass(root, 'threadOP')) { - $.addClass(root, 'threadOP'); + if ($.hasClass(root, 'threadOP')) { + threadContainer = root.nextElementSibling; + post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer)); + $.add(threadContainer, this.nodes.root); + } else { threadContainer = $.el('div', { className: 'threadContainer' }); + $.add(threadContainer, this.nodes.root); $.after(root, threadContainer); - } else { - threadContainer = root.nextSibling; - post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer)); + $.addClass(root, 'threadOP'); } - $.add(threadContainer, this.nodes.root); if (!Conf['Unread Count']) { return true; } if (posts[post.ID]) { posts.after(post, this); - return true; - } - if ((ID = posts.closest(post.ID)) !== -1) { - posts.after(posts[ID], this); } else { posts.prepend(this); } return true; }, toggle: function() { - var container, containers, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; - if (Conf['Unread Count']) { - Unread.posts = new RandomAccessList; - Unread.ready(); - } - thread = $('.thread'); - replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); + var ID, container, containers, post, posts, thread, _i, _j, _len, _len1, _ref, _results; if (QuoteThreading.enabled = this.checked) { - QuoteThreading.hasRun = false; - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; - post = Get.postFromRoot(reply); - if (post.cb) { - post.cb(); - } - } - QuoteThreading.hasRun = true; + return QuoteThreading.force(); } else { - replies.sort(function(a, b) { - return Number(a.id.slice(2)) - Number(b.id.slice(2)); + thread = $('.thread'); + posts = (function() { + var _ref, _results; + _ref = g.posts; + _results = []; + for (ID in _ref) { + post = _ref[ID]; + if (!(post === post.thread.OP || post.isClone)) { + _results.push(post); + } + } + return _results; + })(); + posts.sort(function(a, b) { + return a.ID - b.ID; }); - $.add(thread, replies); + $.add(thread, (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = posts.length; _i < _len; _i++) { + post = posts[_i]; + _results.push(post.nodes.root); + } + return _results; + })()); containers = $$('.threadContainer', thread); - for (_j = 0, _len1 = containers.length; _j < _len1; _j++) { - container = containers[_j]; + for (_i = 0, _len = containers.length; _i < _len; _i++) { + container = containers[_i]; $.rm(container); } _ref = $$('.threadOP'); - for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { - post = _ref[_k]; - $.rmClass(post, 'threadOP'); + _results = []; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + post = _ref[_j]; + _results.push($.rmClass(post, 'threadOP')); } - } - if (Conf['Unread Count']) { - return Unread.read(); + return _results; } }, kb: function() { @@ -9547,7 +9539,7 @@ } Unread.addPosts(posts); if (Conf['Quote Threading']) { - QuoteThreading.setup(); + QuoteThreading.force(); } if (Conf['Scroll to Last Read Post']) { return Unread.scroll(); @@ -12259,41 +12251,7 @@ Main = { init: function() { - var db, flatten, _i, _len, _ref; - flatten = function(parent, obj) { - var key, val; - if (obj instanceof Array) { - Conf[parent] = obj[0]; - } else if (typeof obj === 'object') { - for (key in obj) { - val = obj[key]; - flatten(key, val); - } - } else { - Conf[parent] = obj; - } - }; - flatten(null, Config); - _ref = DataBoard.keys; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - db = _ref[_i]; - Conf[db] = { - boards: {} - }; - } - Conf['selectedArchives'] = {}; - Conf['CachedTitles'] = []; - $.get(Conf, function(items) { - $.extend(Conf, items); - return Main.initFeatures(); - }); - $.on(d, '4chanMainInit', Main.initStyle); - return $.asap((function() { - return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; - }), Main.initStyle); - }, - initFeatures: function() { - var init, pathname, _ref; + var db, flatten, pathname, _i, _len, _ref, _ref1; pathname = location.pathname.split('/'); g.BOARD = new Board(pathname[1]); if ((_ref = g.BOARD.ID) === 'z' || _ref === 'fk') { @@ -12312,6 +12270,40 @@ if (g.VIEW === 'thread') { g.THREADID = +pathname[3]; } + flatten = function(parent, obj) { + var key, val; + if (obj instanceof Array) { + Conf[parent] = obj[0]; + } else if (typeof obj === 'object') { + for (key in obj) { + val = obj[key]; + flatten(key, val); + } + } else { + Conf[parent] = obj; + } + }; + flatten(null, Config); + _ref1 = DataBoard.keys; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + db = _ref1[_i]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + Conf['CachedTitles'] = []; + $.get(Conf, function(items) { + $.extend(Conf, items); + return Main.initFeatures(); + }); + $.on(d, '4chanMainInit', Main.initStyle); + return $.asap((function() { + return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; + }), Main.initStyle); + }, + initFeatures: function() { + var init; switch (location.hostname) { case 'a.4cdn.org': return; @@ -12320,8 +12312,8 @@ return; case 'i.4cdn.org': $.ready(function() { - var URL, _ref1; - if (Conf['404 Redirect'] && ((_ref1 = d.title) === '4chan - Temporarily Offline' || _ref1 === '4chan - 404 Not Found')) { + var URL, pathname, _ref; + if (Conf['404 Redirect'] && ((_ref = d.title) === '4chan - Temporarily Offline' || _ref === '4chan - 404 Not Found')) { Redirect.init(); pathname = location.pathname.split('/'); URL = Redirect.to('file', { diff --git a/builds/crx/script.js b/builds/crx/script.js index f864f3341..c793ecef5 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1540,19 +1540,6 @@ } }; - RandomAccessList.prototype.closest = function(ID) { - var item, prev; - item = this.first; - while (item) { - if (item.ID > ID) { - prev = item.prev; - break; - } - item = item.next; - } - return (prev ? prev.ID : -1); - }; - return RandomAccessList; })(); @@ -4954,16 +4941,18 @@ }); }, setup: function() { - var ID, post, _ref; $.off(d, '4chanXInitFinished', QuoteThreading.setup); + return QuoteThreading.force(); + }, + force: function() { + var ID, post, _ref; _ref = g.posts; for (ID in _ref) { post = _ref[ID]; if (post.cb) { - post.cb(); + post.cb(true); } } - return QuoteThreading.hasRun = true; }, node: function() { var keys, len, post, posts, quote, _i, _len, _ref; @@ -4992,82 +4981,85 @@ this.threaded = keys[0]; return this.cb = QuoteThreading.nodeinsert; }, - nodeinsert: function() { - var ID, bottom, height, post, posts, root, threadContainer, top, _ref; + nodeinsert: function(force) { + var bottom, height, post, posts, root, threadContainer, top, _ref; post = g.posts[this.threaded]; posts = Unread.posts; + root = post.nodes.root; if (this.thread.OP === post) { return false; } - if (QuoteThreading.hasRun) { + if (!force) { height = doc.clientHeight; - _ref = post.nodes.root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top; - if (!((posts != null ? posts[post.ID] : void 0) || ((bottom < height) && (top > 0)))) { + _ref = root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top; + if (!((Conf['Unread Count'] && posts[post.ID]) || ((bottom < height) && (top > 0)))) { return false; } } - root = post.nodes.root; - if (!$.hasClass(root, 'threadOP')) { - $.addClass(root, 'threadOP'); + if ($.hasClass(root, 'threadOP')) { + threadContainer = root.nextElementSibling; + post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer)); + $.add(threadContainer, this.nodes.root); + } else { threadContainer = $.el('div', { className: 'threadContainer' }); + $.add(threadContainer, this.nodes.root); $.after(root, threadContainer); - } else { - threadContainer = root.nextSibling; - post = Get.postFromRoot($.x('descendant::div[contains(@class,"postContainer")][last()]', threadContainer)); + $.addClass(root, 'threadOP'); } - $.add(threadContainer, this.nodes.root); if (!Conf['Unread Count']) { return true; } if (posts[post.ID]) { posts.after(post, this); - return true; - } - if ((ID = posts.closest(post.ID)) !== -1) { - posts.after(posts[ID], this); } else { posts.prepend(this); } return true; }, toggle: function() { - var container, containers, post, replies, reply, thread, _i, _j, _k, _len, _len1, _len2, _ref; - if (Conf['Unread Count']) { - Unread.posts = new RandomAccessList; - Unread.ready(); - } - thread = $('.thread'); - replies = $$('.thread > .replyContainer, .threadContainer > .replyContainer', thread); + var ID, container, containers, post, posts, thread, _i, _j, _len, _len1, _ref, _results; if (QuoteThreading.enabled = this.checked) { - QuoteThreading.hasRun = false; - for (_i = 0, _len = replies.length; _i < _len; _i++) { - reply = replies[_i]; - post = Get.postFromRoot(reply); - if (post.cb) { - post.cb(); - } - } - QuoteThreading.hasRun = true; + return QuoteThreading.force(); } else { - replies.sort(function(a, b) { - return Number(a.id.slice(2)) - Number(b.id.slice(2)); + thread = $('.thread'); + posts = (function() { + var _ref, _results; + _ref = g.posts; + _results = []; + for (ID in _ref) { + post = _ref[ID]; + if (!(post === post.thread.OP || post.isClone)) { + _results.push(post); + } + } + return _results; + })(); + posts.sort(function(a, b) { + return a.ID - b.ID; }); - $.add(thread, replies); + $.add(thread, (function() { + var _i, _len, _results; + _results = []; + for (_i = 0, _len = posts.length; _i < _len; _i++) { + post = posts[_i]; + _results.push(post.nodes.root); + } + return _results; + })()); containers = $$('.threadContainer', thread); - for (_j = 0, _len1 = containers.length; _j < _len1; _j++) { - container = containers[_j]; + for (_i = 0, _len = containers.length; _i < _len; _i++) { + container = containers[_i]; $.rm(container); } _ref = $$('.threadOP'); - for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) { - post = _ref[_k]; - $.rmClass(post, 'threadOP'); + _results = []; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + post = _ref[_j]; + _results.push($.rmClass(post, 'threadOP')); } - } - if (Conf['Unread Count']) { - return Unread.read(); + return _results; } }, kb: function() { @@ -9530,7 +9522,7 @@ } Unread.addPosts(posts); if (Conf['Quote Threading']) { - QuoteThreading.setup(); + QuoteThreading.force(); } if (Conf['Scroll to Last Read Post']) { return Unread.scroll(); @@ -12246,41 +12238,7 @@ Main = { init: function() { - var db, flatten, _i, _len, _ref; - flatten = function(parent, obj) { - var key, val; - if (obj instanceof Array) { - Conf[parent] = obj[0]; - } else if (typeof obj === 'object') { - for (key in obj) { - val = obj[key]; - flatten(key, val); - } - } else { - Conf[parent] = obj; - } - }; - flatten(null, Config); - _ref = DataBoard.keys; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - db = _ref[_i]; - Conf[db] = { - boards: {} - }; - } - Conf['selectedArchives'] = {}; - Conf['CachedTitles'] = []; - $.get(Conf, function(items) { - $.extend(Conf, items); - return Main.initFeatures(); - }); - $.on(d, '4chanMainInit', Main.initStyle); - return $.asap((function() { - return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; - }), Main.initStyle); - }, - initFeatures: function() { - var init, pathname, _ref; + var db, flatten, pathname, _i, _len, _ref, _ref1; pathname = location.pathname.split('/'); g.BOARD = new Board(pathname[1]); if ((_ref = g.BOARD.ID) === 'z' || _ref === 'fk') { @@ -12299,6 +12257,40 @@ if (g.VIEW === 'thread') { g.THREADID = +pathname[3]; } + flatten = function(parent, obj) { + var key, val; + if (obj instanceof Array) { + Conf[parent] = obj[0]; + } else if (typeof obj === 'object') { + for (key in obj) { + val = obj[key]; + flatten(key, val); + } + } else { + Conf[parent] = obj; + } + }; + flatten(null, Config); + _ref1 = DataBoard.keys; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + db = _ref1[_i]; + Conf[db] = { + boards: {} + }; + } + Conf['selectedArchives'] = {}; + Conf['CachedTitles'] = []; + $.get(Conf, function(items) { + $.extend(Conf, items); + return Main.initFeatures(); + }); + $.on(d, '4chanMainInit', Main.initStyle); + return $.asap((function() { + return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; + }), Main.initStyle); + }, + initFeatures: function() { + var init; switch (location.hostname) { case 'a.4cdn.org': return; @@ -12307,8 +12299,8 @@ return; case 'i.4cdn.org': $.ready(function() { - var URL, _ref1; - if (Conf['404 Redirect'] && ((_ref1 = d.title) === '4chan - Temporarily Offline' || _ref1 === '4chan - 404 Not Found')) { + var URL, pathname, _ref; + if (Conf['404 Redirect'] && ((_ref = d.title) === '4chan - Temporarily Offline' || _ref === '4chan - 404 Not Found')) { Redirect.init(); pathname = location.pathname.split('/'); URL = Redirect.to('file', { diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 61b083ecf..9d02d5f5d 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -1,5 +1,19 @@ Main = init: -> + pathname = location.pathname.split '/' + g.BOARD = new Board pathname[1] + return if g.BOARD.ID in ['z', 'fk'] + g.VIEW = + switch pathname[2] + when 'res' + 'thread' + when 'catalog' + 'catalog' + else + 'index' + if g.VIEW is 'thread' + g.THREADID = +pathname[3] + # flatten Config into Conf # and get saved or default values flatten = (parent, obj) -> @@ -25,21 +39,6 @@ Main = Main.initStyle initFeatures: -> - - pathname = location.pathname.split '/' - g.BOARD = new Board pathname[1] - return if g.BOARD.ID in ['z', 'fk'] - g.VIEW = - switch pathname[2] - when 'res' - 'thread' - when 'catalog' - 'catalog' - else - 'index' - if g.VIEW is 'thread' - g.THREADID = +pathname[3] - switch location.hostname when 'a.4cdn.org' return diff --git a/src/General/lib/randomaccesslist.class b/src/General/lib/randomaccesslist.class index 98c08a670..0cc754d60 100644 --- a/src/General/lib/randomaccesslist.class +++ b/src/General/lib/randomaccesslist.class @@ -55,13 +55,4 @@ class RandomAccessList if next next.prev = prev else - @last = prev - - closest: (ID) -> - item = @first - while item - if item.ID > ID - {prev} = item - break - item = item.next - return (if prev then prev.ID else -1) \ No newline at end of file + @last = prev \ No newline at end of file diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 02c50faf5..db4e061c6 100755 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -39,7 +39,7 @@ Unread = posts = [] posts.push post for ID, post of Unread.thread.posts when post.isReply Unread.addPosts posts - QuoteThreading.setup() if Conf['Quote Threading'] + QuoteThreading.force() if Conf['Quote Threading'] Unread.scroll() if Conf['Scroll to Last Read Post'] scroll: -> diff --git a/src/Quotelinks/QuoteThreading.coffee b/src/Quotelinks/QuoteThreading.coffee index ddc975dd0..b50cbe94c 100755 --- a/src/Quotelinks/QuoteThreading.coffee +++ b/src/Quotelinks/QuoteThreading.coffee @@ -26,9 +26,11 @@ QuoteThreading = setup: -> $.off d, '4chanXInitFinished', QuoteThreading.setup + QuoteThreading.force() - post.cb() for ID, post of g.posts when post.cb - QuoteThreading.hasRun = true + force: -> + post.cb true for ID, post of g.posts when post.cb + return node: -> {posts} = g @@ -46,69 +48,54 @@ QuoteThreading = @threaded = keys[0] @cb = QuoteThreading.nodeinsert - nodeinsert: -> + nodeinsert: (force) -> post = g.posts[@threaded] {posts} = Unread + {root} = post.nodes return false if @thread.OP is post - if QuoteThreading.hasRun + unless force height = doc.clientHeight - {bottom, top} = post.nodes.root.getBoundingClientRect() + {bottom, top} = root.getBoundingClientRect() # Post is unread or is fully visible. - return false unless posts?[post.ID] or ((bottom < height) and (top > 0)) + return false unless (Conf['Unread Count'] and posts[post.ID]) or ((bottom < height) and (top > 0)) - {root} = post.nodes - unless $.hasClass root, 'threadOP' - $.addClass root, 'threadOP' + if $.hasClass root, 'threadOP' + threadContainer = root.nextElementSibling + post = Get.postFromRoot $.x 'descendant::div[contains(@class,"postContainer")][last()]', threadContainer + $.add threadContainer, @nodes.root + + else threadContainer = $.el 'div', className: 'threadContainer' + $.add threadContainer, @nodes.root $.after root, threadContainer - else - threadContainer = root.nextSibling - post = Get.postFromRoot $.x 'descendant::div[contains(@class,"postContainer")][last()]', threadContainer - - $.add threadContainer, @nodes.root + $.addClass root, 'threadOP' return true unless Conf['Unread Count'] if posts[post.ID] posts.after post, @ - return true - if (ID = posts.closest post.ID) isnt -1 - posts.after posts[ID], @ else posts.prepend @ return true toggle: -> - if Conf['Unread Count'] - Unread.posts = new RandomAccessList - Unread.ready() - - thread = $ '.thread' - replies = $$ '.thread > .replyContainer, .threadContainer > .replyContainer', thread - if QuoteThreading.enabled = @checked - QuoteThreading.hasRun = false - for reply in replies - post = Get.postFromRoot reply - # QuoteThreading calculates whether or not posts should be threaded based on content - # and then threads them based on thread context, so regardless of whether or not it - # actually threads them all eligible posts WILL have a cb. Magic. - post.cb() if post.cb - QuoteThreading.hasRun = true + QuoteThreading.force() else - replies.sort (a, b) -> Number(a.id[2..]) - Number(b.id[2..]) - $.add thread, replies + thread = $('.thread') + posts = (post for ID, post of g.posts when not (post is post.thread.OP or post.isClone)) + posts.sort (a, b) -> a.ID - b.ID + $.add thread, (post.nodes.root for post in posts) containers = $$ '.threadContainer', thread $.rm container for container in containers $.rmClass post, 'threadOP' for post in $$ '.threadOP' - Unread.read() if Conf['Unread Count'] kb: -> control = $.id 'threadingControl'