Adrià Vilanova MartÃnez | 0d92a0c | 2023-11-06 01:37:20 +0100 | [diff] [blame^] | 1 | import {createPlainTooltip} from '../../../../common/tooltip.js'; |
| 2 | import {kItemMetadataState, kItemMetadataStateI18n} from '../consts.js'; |
| 3 | |
| 4 | export default class ThreadExtraInfoService { |
| 5 | /** |
| 6 | * Get a |chipContentList| array with the chips related to the thread, and a |
| 7 | * |tooltips| array with the corresponding tooltips which should be |
| 8 | * initialized after the chips are added to the DOM. |
| 9 | */ |
| 10 | static getThreadChips(thread) { |
| 11 | let chips = []; |
| 12 | let tooltips = []; |
| 13 | |
| 14 | const [pendingStateInfo, pendingTooltip] = this.getPendingStateChip(thread); |
| 15 | if (pendingStateInfo) chips.push(pendingStateInfo); |
| 16 | if (pendingTooltip) tooltips.push(pendingTooltip); |
| 17 | |
| 18 | chips.push(...this.getTrendingChips(thread)); |
| 19 | chips.push(...this.getMetadataChips(thread)); |
| 20 | |
| 21 | const [liveReviewInfo, liveReviewTooltip] = |
| 22 | this.getLiveReviewStatusChip(thread); |
| 23 | if (liveReviewInfo) chips.push(liveReviewInfo); |
| 24 | if (liveReviewTooltip) tooltips.push(liveReviewTooltip); |
| 25 | |
| 26 | return [chips, tooltips]; |
| 27 | } |
| 28 | |
| 29 | static getPendingStateChip(thread) { |
| 30 | const endPendingStateTimestampMicros = thread?.['2']?.['39']; |
| 31 | const endPendingStateTimestamp = |
| 32 | Math.floor(endPendingStateTimestampMicros / 1e3); |
| 33 | const now = Date.now(); |
| 34 | if (!endPendingStateTimestampMicros || endPendingStateTimestamp < now) |
| 35 | return [null, null]; |
| 36 | |
| 37 | const span = document.createElement('span'); |
| 38 | span.textContent = |
| 39 | chrome.i18n.getMessage('inject_extrainfo_message_pendingstate'); |
| 40 | |
| 41 | const date = new Date(endPendingStateTimestamp).toLocaleString(); |
| 42 | const pendingTooltip = createPlainTooltip( |
| 43 | span, |
| 44 | chrome.i18n.getMessage( |
| 45 | 'inject_extrainfo_message_pendingstate_tooltip', [date]), |
| 46 | false); |
| 47 | return [span, pendingTooltip]; |
| 48 | } |
| 49 | |
| 50 | static getTrendingChips(thread) { |
| 51 | const chips = []; |
| 52 | |
| 53 | const isTrending = thread?.['2']?.['25']; |
| 54 | const isTrendingAutoMarked = thread?.['39']; |
| 55 | if (isTrendingAutoMarked) |
| 56 | chips.push(document.createTextNode( |
| 57 | chrome.i18n.getMessage('inject_extrainfo_thread_autotrending'))); |
| 58 | else if (isTrending) |
| 59 | chips.push(document.createTextNode( |
| 60 | chrome.i18n.getMessage('inject_extrainfo_thread_trending'))); |
| 61 | |
| 62 | return chips; |
| 63 | } |
| 64 | |
| 65 | static getMetadataChips(thread) { |
| 66 | const itemMetadata = thread?.['2']?.['12']; |
| 67 | |
| 68 | return [ |
| 69 | this.getStateChip(itemMetadata), |
| 70 | this.getShadowBlockChip(itemMetadata), |
| 71 | ].filter(chip => chip !== null); |
| 72 | } |
| 73 | |
| 74 | static getLiveReviewStatusChip(thread) { |
| 75 | const liveReviewStatus = thread?.['2']?.['38']; |
| 76 | const verdict = liveReviewStatus?.['1']; |
| 77 | if (!verdict) return [null, null]; |
| 78 | |
| 79 | const [label, labelClass] = this.getLiveReviewStatusLabel(verdict); |
| 80 | if (!label || !labelClass) return [null, null]; |
| 81 | |
| 82 | const reviewedBy = liveReviewStatus?.['2']; |
| 83 | const timestamp = liveReviewStatus?.['3']; |
| 84 | const date = (new Date(Math.floor(timestamp / 1e3))).toLocaleString(); |
| 85 | |
| 86 | let a = document.createElement('a'); |
| 87 | a.href = 'https://support.google.com/s/community/user/' + reviewedBy; |
| 88 | a.classList.add(labelClass); |
| 89 | a.textContent = chrome.i18n.getMessage( |
| 90 | 'inject_extrainfo_message_livereviewverdict', |
| 91 | [chrome.i18n.getMessage( |
| 92 | 'inject_extrainfo_message_livereviewverdict_' + label)]); |
| 93 | let liveReviewTooltip = createPlainTooltip(a, date, false); |
| 94 | return [a, liveReviewTooltip]; |
| 95 | } |
| 96 | |
| 97 | static getStateChip(itemMetadata) { |
| 98 | const state = itemMetadata?.['1']; |
| 99 | if (!state || state == 1) return null; |
| 100 | |
| 101 | const stateI18nKey = |
| 102 | 'inject_extrainfo_message_state_' + kItemMetadataStateI18n[state]; |
| 103 | const stateLocalized = chrome.i18n.getMessage(stateI18nKey) ?? state; |
| 104 | |
| 105 | const span = document.createElement('span'); |
| 106 | span.textContent = chrome.i18n.getMessage( |
| 107 | 'inject_extrainfo_message_state', [stateLocalized]); |
| 108 | span.title = kItemMetadataState[state] ?? state; |
| 109 | return span; |
| 110 | } |
| 111 | |
| 112 | static getLiveReviewStatusLabel(verdict) { |
| 113 | let label, labelClass; |
| 114 | switch (verdict) { |
| 115 | case 1: // LIVE_REVIEW_RELEVANT |
| 116 | label = 'relevant'; |
| 117 | labelClass = 'TWPT-extrainfo-good'; |
| 118 | break; |
| 119 | |
| 120 | case 2: // LIVE_REVIEW_OFF_TOPIC |
| 121 | label = 'offtopic'; |
| 122 | labelClass = 'TWPT-extrainfo-bad'; |
| 123 | break; |
| 124 | |
| 125 | case 3: // LIVE_REVIEW_ABUSE |
| 126 | label = 'abuse'; |
| 127 | labelClass = 'TWPT-extrainfo-bad'; |
| 128 | break; |
| 129 | |
| 130 | default: |
| 131 | return [null, null]; |
| 132 | } |
| 133 | return [label, labelClass]; |
| 134 | } |
| 135 | |
| 136 | static getShadowBlockChip(itemMetadata) { |
| 137 | const shadowBlockInfo = itemMetadata?.['10']; |
| 138 | const blockedTimestampMicros = shadowBlockInfo?.['2']; |
| 139 | if (!blockedTimestampMicros) return null; |
| 140 | |
| 141 | const isBlocked = shadowBlockInfo?.['1']; |
| 142 | let span = document.createElement('span'); |
| 143 | span.textContent = chrome.i18n.getMessage( |
| 144 | 'inject_extrainfo_message_shadowblock' + |
| 145 | (isBlocked ? 'active' : 'notactive')); |
| 146 | if (isBlocked) span.classList.add('TWPT-extrainfo-bad'); |
| 147 | return span; |
| 148 | } |
| 149 | |
| 150 | static getThreadFromThreadList(threadList, currentThreadInfo) { |
| 151 | return threadList?.find?.(thread => { |
| 152 | const threadInfo = thread?.['2']?.['1']; |
| 153 | const threadId = threadInfo?.['1']; |
| 154 | const forumId = threadInfo?.['3']; |
| 155 | return threadId == currentThreadInfo.thread && |
| 156 | forumId == currentThreadInfo.forum; |
| 157 | }); |
| 158 | } |
| 159 | } |