blob: 6fc3eacfc82e9a8b402012fe1c4e90e6434c5b6f [file] [log] [blame]
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +01001export const kAdditionalInfoPrefix = '__TWPT_FLATTENTHREADS_ADDITIONALINFO__';
2export const kAdditionalInfoRegex =
3 /^__TWPT_FLATTENTHREADS_ADDITIONALINFO__(.*)/;
4
5export const kReplyPayloadSelector =
6 '.scTailwindThreadMessageMessagecardcontent:not(.scTailwindThreadMessageMessagecardpromoted) .scTailwindThreadPostcontentroot html-blob';
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +01007export const kReplyActionButtonsSelector =
8 '.scTailwindThreadMessageMessagecardcontent:not(.scTailwindThreadMessageMessagecardpromoted) sc-tailwind-thread-message-message-actions';
9export const kMatchingSelectors = [
10 kReplyPayloadSelector,
11 kReplyActionButtonsSelector,
12];
13
14export function getExtraInfoNodes(node) {
15 const confirmedNodes = [];
16 const possibleExtraInfoNodes =
17 node.querySelectorAll('span[style*=\'display\'][style*=\'none\']');
18 for (const candidate of possibleExtraInfoNodes) {
19 const content = candidate.textContent;
20 const matches = content.match(kAdditionalInfoRegex);
21 if (matches) confirmedNodes.push(candidate);
22 }
23 return confirmedNodes;
24}
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +010025
26export default class FlattenThreads {
27 construct() {}
28
29 getExtraInfo(node) {
30 let rawExtraInfo = null;
31 const possibleExtraInfoNodes =
32 node.querySelectorAll('span[style*=\'display\'][style*=\'none\']');
33 for (const candidate of possibleExtraInfoNodes) {
34 const content = candidate.textContent;
35 const matches = content.match(kAdditionalInfoRegex);
36 if (matches) {
37 rawExtraInfo = matches?.[1] ?? null;
38 break;
39 }
40 }
41 if (!rawExtraInfo) return null;
42 return JSON.parse(rawExtraInfo);
43 }
44
45 injectId(node, extraInfo) {
46 const root = node.closest('.scTailwindThreadMessageMessagecardcontent');
47 if (!root) return false;
48 root.setAttribute('data-twpt-message-id', extraInfo.id);
49 return true;
50 }
51
52 injectQuote(node, extraInfo) {
53 const content = node.closest('.scTailwindThreadPostcontentroot');
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010054 const quote = document.createElement('twpt-flatten-thread-quote');
55 quote.setAttribute('prevMessage', JSON.stringify(extraInfo.prevMessage));
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +010056 content.prepend(quote);
57 }
58
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010059 injectReplyBtn(node, extraInfo) {
60 const btn = document.createElement('twpt-flatten-thread-reply-button');
61 btn.setAttribute('extraInfo', JSON.stringify(extraInfo));
62 node.prepend(btn);
63 }
64
65 injectQuoteIfApplicable(node) {
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +010066 // If we injected the additional information, it means the flatten threads
67 // feature is enabled and in actual use, so we should inject the quote.
68 const extraInfo = this.getExtraInfo(node);
69 if (!extraInfo) return;
70
71 this.injectId(node, extraInfo);
72 if (extraInfo.isComment) this.injectQuote(node, extraInfo);
73 }
74
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010075 shouldInjectQuote(node) {
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +010076 return node.matches(kReplyPayloadSelector);
77 }
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010078
79 injectReplyBtnIfApplicable(node) {
80 // If we injected the additional information, it means the flatten threads
81 // feature is enabled and in actual use, so we should inject the reply
82 // button.
83 const root =
84 node.closest('.scTailwindThreadMessageMessagecardcontent')
85 .querySelector('.scTailwindThreadMessageMessagecardbody html-blob');
86 const extraInfo = this.getExtraInfo(root);
87 if (!extraInfo) return;
88
89 this.injectReplyBtn(node, extraInfo);
90 }
91
92 shouldInjectReplyBtn(node) {
93 return node.matches(kReplyActionButtonsSelector);
94 }
Adrià Vilanova Martínez412b7582022-12-30 01:35:30 +010095}