Re-think the Quote Backlink implementation.

Before this rewrite, containers and backlinks were created even if the relevant
post did not exist in the page. If the post would never end up existing, it
resulted in a waste of resources. QuoteBacklink's cache also prevented these
containers and backlinks from being garbage collected.
We now only store a map of fullIDs. This feature should be faster since less
elements gets allocated, although the difference is probably negligible.
This commit is contained in:
Mayhem 2014-02-15 21:01:59 +01:00
parent f7d048de7b
commit 004c3f74ed

View File

@ -3,19 +3,19 @@ QuoteBacklink =
# - previous, same, and following posts. # - previous, same, and following posts.
# - existing and yet-to-exist posts. # - existing and yet-to-exist posts.
# - newly fetched posts. # - newly fetched posts.
# - in copies. # - clones.
# XXX what about order for fetched posts? # XXX what about order for fetched posts?
# #
# First callback creates backlinks and add them to relevant containers. # First callback creates a map of quoted -> [quoters],
# Second callback adds relevant containers into posts. # and append backlinks to posts that already have containers.
# This is is so that fetched posts can get their backlinks, # Second callback creates, fill and append containers.
# and that as much backlinks are appended in the background as possible.
init: -> init: ->
return if !Conf['Quote Backlinks'] return if !Conf['Quote Backlinks']
format = Conf['backlink'].replace /%id/g, "' + id + '" format = Conf['backlink'].replace /%id/g, "' + id + '"
@funk = Function 'id', "return '#{format}'" @funk = Function 'id', "return '#{format}'"
@containers = {} @frag = $.nodes [$.tn(' '), $.el 'a', className: 'backlink']
@map = {}
Post.callbacks.push Post.callbacks.push
name: 'Quote Backlinking Part 1' name: 'Quote Backlinking Part 1'
cb: @firstNode cb: @firstNode
@ -23,42 +23,39 @@ QuoteBacklink =
name: 'Quote Backlinking Part 2' name: 'Quote Backlinking Part 2'
cb: @secondNode cb: @secondNode
firstNode: -> firstNode: ->
return if @isClone or !@quotes.length return if @isClone
text = QuoteBacklink.funk @ID for quoteID in @quotes
a = $.el 'a', (QuoteBacklink.map[quoteID] or= []).push @fullID
href: "/#{@board}/res/#{@thread}#p#{@}" continue unless (post = g.posts[quoteID]) and container = post?.nodes.backlinkContainer
className: 'backlink' for container in [container].concat post.clones.map((clone) -> clone.nodes.backlinkContainer)
textContent: text $.add container, QuoteBacklink.buildBacklink @
if @isHidden
$.addClass a, 'filtered'
if @isDead
$.addClass a, 'deadlink'
if Conf['Quote Markers']
QuoteMarkers.parseQuotelink @board, @thread, @, a, false, text
for quote in @quotes
containers = [QuoteBacklink.getContainer quote]
if (post = g.posts[quote]) and post.nodes.backlinkContainer
# Don't add OP clones when OP Backlinks is disabled,
# as the clones won't have the backlink containers.
for clone in post.clones
containers.push clone.nodes.backlinkContainer
for container in containers
link = a.cloneNode true
if Conf['Quote Previewing']
$.on link, 'mouseover', QuotePreview.mouseover
if Conf['Quote Inlining']
$.on link, 'click', QuoteInline.toggle
$.add container, [$.tn(' '), link]
return return
secondNode: -> secondNode: ->
if @isClone and (@origin.isReply or Conf['OP Backlinks'])
@nodes.backlinkContainer = $ '.container', @nodes.info
return
# Don't backlink the OP. # Don't backlink the OP.
return unless @isReply or Conf['OP Backlinks'] return unless @isReply or Conf['OP Backlinks']
container = QuoteBacklink.getContainer @fullID if @isClone
@nodes.backlinkContainer = container @nodes.backlinkContainer = $ '.backlink-container', @nodes.info
return
@nodes.backlinkContainer = container = $.el 'span',
className: 'backlink-container'
if @fullID of QuoteBacklink.map
for quoteID in QuoteBacklink.map[@fullID]
if post = g.posts[quoteID] # Post hasn't been collected since.
$.add container, QuoteBacklink.buildBacklink post
$.add @nodes.info, container $.add @nodes.info, container
getContainer: (id) -> buildBacklink: (post) ->
@containers[id] or= frag = QuoteBacklink.frag.cloneNode true
$.el 'span', className: 'container' a = frag.lastElementChild
a.href = "/#{post.board}/res/#{post.thread}#p#{post}"
a.textContent = text = QuoteBacklink.funk post.ID
if post.isDead
$.addClass a, 'deadlink'
if post.isHidden
$.addClass a, 'filtered'
if Conf['Quote Markers']
QuoteMarkers.parseQuotelink post.board, post.thread, post, a, false, text
if Conf['Quote Previewing']
$.on a, 'mouseover', QuotePreview.mouseover
if Conf['Quote Inlining']
$.on a, 'click', QuoteInline.toggle
frag