blob: 5dc7d59361e5d44360d8b483b7e11773ee3e7d4a [file] [log] [blame]
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +01001import '@material/web/button/outlined-button.js';
2
Adrià Vilanova Martíneza03d03a2023-03-11 23:30:07 +01003import {msg} from '@lit/localize';
4import {css, html} from 'lit';
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +01005import {waitFor} from 'poll-until-promise';
6
Adrià Vilanova Martíneza03d03a2023-03-11 23:30:07 +01007import {I18nLitElement} from '../../../../common/litI18nUtils.js';
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +01008import {SHARED_MD3_STYLES} from '../../../../common/styles/md3.js';
9import {getExtraInfoNodes} from '../flattenThreads.js';
10
Adrià Vilanova Martíneza03d03a2023-03-11 23:30:07 +010011export default class TwptFlattenThreadReplyButton extends I18nLitElement {
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010012 static properties = {
13 extraInfo: {type: Object},
14 };
15
16 static styles = [
17 SHARED_MD3_STYLES,
18 css`
19 md-outlined-button {
20 --md-outlined-button-container-shape: 0.25rem;
21 --md-outlined-button-container-height: 38px;
22 }
23 `,
24 ];
25
26 constructor() {
27 super();
28 this.extraInfo = {};
29 }
30
31 render() {
32 return html`
33 <md-outlined-button
Adrià Vilanova Martíneza03d03a2023-03-11 23:30:07 +010034 label="${msg('Reply', {
35 desc: 'Button which is used to open the reply box.',
36 })}"
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +010037 @click=${this.openReplyEditor}>
38 </md-outlined-button>
39 `;
40 }
41
42 #defaultReply(messagePayload) {
43 const quoteHeader = document.createElement('div');
44 const italics = document.createElement('i');
45 italics.textContent = this.extraInfo?.authorName + ' said:';
46 quoteHeader.append(italics);
47
48 const quote = document.createElement('blockquote');
49 quote.innerHTML = messagePayload;
50 getExtraInfoNodes(quote)?.forEach?.(node => {
51 node.parentNode.removeChild(node);
52 });
53
54 const br1 = document.createElement('br');
55 const br2 = document.createElement('br');
56
57 return [quoteHeader, quote, br1, br2];
58 }
59
60 openReplyEditor() {
61 const messageId = this.extraInfo?.id;
62 const messagePayload = document.querySelector(
63 '[data-twpt-message-id="' + messageId +
64 '"] .scTailwindThreadPostcontentroot html-blob');
65 if (!messagePayload) {
66 console.error('[flattenThreads] Payload not found.');
67 return;
68 }
69
70 const parentId = this.extraInfo?.parentId ?? this.extraInfo?.id;
71 const parentNodeReply =
72 document.querySelector('[data-twpt-message-id="' + parentId + '"]')
73 ?.closest?.('sc-tailwind-thread-message-message-card');
74 const parentNodeReplyButton = parentNodeReply?.querySelector?.(
75 '.scTailwindThreadMessageMessagecardadd-comment button');
76 if (!parentNodeReplyButton) {
77 // This is not critical: the reply button might already have been clicked
78 // (so it no longer exists), or the thread might be locked so replying is
79 // disabled and the button does'nt exist.
80 console.debug('[flattenThreads] Reply button not found.');
81 return;
82 }
83
84 // Click the reply button.
85 parentNodeReplyButton.click();
86
87 // Fill in the default reply text (it includes a quote of the message the
88 // user wishes to reply to).
89 waitFor(() => {
90 const editor =
91 parentNodeReply?.querySelector('sc-tailwind-thread-reply-editor');
92 if (editor) return Promise.resolve(editor);
93 return Promise.reject(new Error('Editor not found.'));
94 }, {interval: 75, timeout: 10 * 1000}).then(editor => {
95 const payload =
96 editor?.querySelector('.scTailwindSharedRichtexteditoreditor');
97
98 payload.prepend(...this.#defaultReply(messagePayload.innerHTML));
Adrià Vilanova Martínezdb38d7f2023-01-10 22:40:58 +010099 payload.scrollTop = payload.scrollHeight;
Adrià Vilanova Martínez115e3d82023-01-10 21:50:06 +0100100 });
101 }
102}
103window.customElements.define(
104 'twpt-flatten-thread-reply-button', TwptFlattenThreadReplyButton);