mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2025-10-07 07:22:37 +02:00
103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
import Callbacks from "../classes/Callbacks"
|
|
import { Conf, doc,g } from "../globals/globals"
|
|
import $ from "../platform/$"
|
|
import { dict } from "../platform/helpers"
|
|
import QuoteInline from "./QuoteInline"
|
|
import QuotePreview from "./QuotePreview"
|
|
import QuoteYou from "./QuoteYou"
|
|
|
|
/*
|
|
* decaffeinate suggestions:
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
*/
|
|
var QuoteBacklink = {
|
|
// Backlinks appending need to work for:
|
|
// - previous, same, and following posts.
|
|
// - existing and yet-to-exist posts.
|
|
// - newly fetched posts.
|
|
// - in copies.
|
|
// XXX what about order for fetched posts?
|
|
//
|
|
// First callback creates backlinks and add them to relevant containers.
|
|
// Second callback adds relevant containers into posts.
|
|
// This is is so that fetched posts can get their backlinks,
|
|
// and that as much backlinks are appended in the background as possible.
|
|
containers: dict(),
|
|
init() {
|
|
if (!['index', 'thread'].includes(g.VIEW) || !Conf['Quote Backlinks']) { return }
|
|
|
|
// Add a class to differentiate when backlinks are at
|
|
// the top (default) or bottom of a post
|
|
if (this.bottomBacklinks = Conf['Bottom Backlinks']) {
|
|
$.addClass(doc, 'bottom-backlinks')
|
|
}
|
|
|
|
Callbacks.Post.push({
|
|
name: 'Quote Backlinking Part 1',
|
|
cb: this.firstNode
|
|
})
|
|
return Callbacks.Post.push({
|
|
name: 'Quote Backlinking Part 2',
|
|
cb: this.secondNode
|
|
})
|
|
},
|
|
firstNode() {
|
|
if (this.isClone || !this.quotes.length || this.isRebuilt) { return }
|
|
const markYours = Conf['Mark Quotes of You'] && QuoteYou.isYou(this)
|
|
const a = $.el('a', {
|
|
href: g.SITE.Build.postURL(this.board.ID, this.thread.ID, this.ID),
|
|
className: this.isHidden ? 'filtered backlink' : 'backlink',
|
|
textContent: Conf['backlink'].replace(/%(?:id|%)/g, x => ({'%id': this.ID, '%%': '%'})[x])
|
|
}
|
|
)
|
|
if (markYours) { $.add(a, QuoteYou.mark.cloneNode(true)) }
|
|
for (const quote of this.quotes) {
|
|
var post
|
|
const containers = [QuoteBacklink.getContainer(quote)]
|
|
if ((post = g.posts.get(quote)) && post.nodes.backlinkContainer) {
|
|
// Don't add OP clones when OP Backlinks is disabled,
|
|
// as the clones won't have the backlink containers.
|
|
for (const clone of post.clones) {
|
|
containers.push(clone.nodes.backlinkContainer)
|
|
}
|
|
}
|
|
for (const container of containers) {
|
|
const link = a.cloneNode(true)
|
|
const nodes = container.firstChild ? [$.tn(' '), link] : [link]
|
|
if (Conf['Quote Previewing']) {
|
|
$.on(link, 'mouseover', QuotePreview.mouseover)
|
|
}
|
|
if (Conf['Quote Inlining']) {
|
|
$.on(link, 'click', QuoteInline.toggle)
|
|
if (Conf['Quote Hash Navigation']) {
|
|
const hash = QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))
|
|
nodes.push(hash)
|
|
}
|
|
}
|
|
$.add(container, nodes)
|
|
}
|
|
}
|
|
},
|
|
secondNode() {
|
|
if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) {
|
|
this.nodes.backlinkContainer = $('.container', this.nodes.post)
|
|
return
|
|
}
|
|
// Don't backlink the OP.
|
|
if (!this.isReply && !Conf['OP Backlinks']) { return }
|
|
const container = QuoteBacklink.getContainer(this.fullID)
|
|
this.nodes.backlinkContainer = container
|
|
if (QuoteBacklink.bottomBacklinks) {
|
|
return $.add(this.nodes.post, container)
|
|
} else {
|
|
return $.add(this.nodes.info, container)
|
|
}
|
|
},
|
|
getContainer(id) {
|
|
return this.containers[id] ||
|
|
(this.containers[id] = $.el('span', {className: 'container'}))
|
|
}
|
|
}
|
|
export default QuoteBacklink
|