blob: 47d7e65ac30f7796bc4d75c762c67cdbf7804468 [file] [log] [blame]
Adrià Vilanova Martínez0d92a0c2023-11-06 01:37:20 +01001import {waitFor} from 'poll-until-promise';
2
3import {kViewForumRequest, kViewForumResponse} from '../consts.js';
4import ThreadExtraInfoService from '../services/thread.js';
5
6import BaseInfoHandler from './base.js';
7
8const kCheckIntervalInMs = 450;
9const kTimeoutInMs = 2 * 1000;
10
11export default class ThreadListInfoHandler extends BaseInfoHandler {
12 constructor() {
13 super();
14
15 this.setUpDefaultValues();
16 this.setUpEventHandlers();
17 }
18
19 setUpDefaultValues() {
20 this.threads = [];
21 this.isFirstBatch = null;
22 this.requestId = -1;
23 this.timestamp = 0;
24 }
25
26 setUpEventHandlers() {
27 window.addEventListener(kViewForumRequest, e => this.onThreadRequest(e));
28 window.addEventListener(kViewForumResponse, e => this.onThreadResponse(e));
29 }
30
31 onThreadRequest(e) {
32 // Ignore ViewForum requests made by the chat feature and the "Mark as
33 // duplicate" dialog.
34 //
35 // All those requests have |maxNum| set to 10 and 20 respectively, while
36 // the requests that we want to handle are the ones to initially load the
37 // thread list (which currently requests 100 threads) and the ones to load
38 // more threads (which request 50 threads).
39 const maxNum = e.detail.body?.['2']?.['1']?.['2'];
40 if (maxNum == 10 || maxNum == 20) return;
41
42 this.requestId = e.detail.id;
43 this.isFirstBatch =
44 !e.detail.body?.['2']?.['1']?.['3']?.['2']; // Pagination token
45 }
46
47 onThreadResponse(e) {
48 if (e.detail.id != this.requestId) return;
49
50 const threads = e.detail.body?.['1']?.['2'] ?? [];
51 if (this.isFirstBatch)
52 this.threads = threads;
53 else
54 this.threads = this.threads.concat(threads);
55
56 this.timestamp = Date.now();
57 }
58
59 async getCurrentInfo(injectionDetails) {
60 const currentThreadInfo = injectionDetails.threadInfo;
61 const checkRecentTimestamp = !injectionDetails.isExpanded;
62
63 return this.getCurrentThreads(currentThreadInfo, checkRecentTimestamp)
64 .catch(err => {
65 if (checkRecentTimestamp) {
66 return this.getCurrentThreads(
67 currentThreadInfo, /* checkRecentTimestamp = */ false);
68 } else {
69 throw err;
70 }
71 });
72 }
73
74 async getCurrentThreads(currentThreadInfo, checkRecentTimestamp) {
75 const options = {
76 interval: kCheckIntervalInMs,
77 timeout: kTimeoutInMs,
78 };
79 return waitFor(
80 () => this.attemptToGetCurrentThreads(
81 currentThreadInfo, checkRecentTimestamp),
82 options);
83 }
84
85 async attemptToGetCurrentThreads(currentThreadInfo, checkRecentTimestamp) {
86 if (!this.isThreadListCurrent(currentThreadInfo, checkRecentTimestamp))
87 throw new Error('Didn\'t receive current information');
88
89 return this.threads;
90 }
91
92 isThreadListCurrent(currentThreadInfo, checkRecentTimestamp) {
93 if (checkRecentTimestamp && Date.now() - this.timestamp > kTimeoutInMs)
94 return false;
95
96 const thread = ThreadExtraInfoService.getThreadFromThreadList(
97 this.threads, currentThreadInfo);
98 return thread !== undefined;
99 }
100}