extraInfo, perProfileStats: improve error handling
Fixed: twpowertools:94
Change-Id: I0c6d5af8bcf0cd6b37ba3fece87d13bdf6db9a66
diff --git a/src/contentScripts/communityConsole/extraInfo.js b/src/contentScripts/communityConsole/extraInfo.js
index 35c13b6..b78b2d0 100644
--- a/src/contentScripts/communityConsole/extraInfo.js
+++ b/src/contentScripts/communityConsole/extraInfo.js
@@ -235,7 +235,7 @@
// Add a pretty component which contains |info| to |node|.
addExtraInfoElement(info, node) {
- // Don't create
+ // Don't create if there's nothing to show
if (info.length == 0) return;
let container = document.createElement('div');
@@ -343,52 +343,66 @@
// Inject usage stats in the |tags| component of a CR
injectAtCR(tags, isExpanded) {
- waitFor(() => {
- if (this.lastCRsList.id != -1) return Promise.resolve(this.lastCRsList);
- return Promise.reject(new Error('Didn\'t receive canned responses list'));
- }, {
- interval: 500,
- timeout: 15 * 1000,
- }).then(crs => {
- let name = this.getCRName(tags, isExpanded);
+ waitFor(
+ () => {
+ if (this.lastCRsList.id != -1)
+ return Promise.resolve(this.lastCRsList);
+ return Promise.reject(
+ new Error('Didn\'t receive canned responses list'));
+ },
+ {
+ interval: 500,
+ timeout: 15 * 1000,
+ })
+ .then(crs => {
+ let name = this.getCRName(tags, isExpanded);
- // If another CR has the same name, there's no easy way to distinguish
- // them, so don't show the usage stats.
- if (crs.duplicateNames.has(name)) return;
-
- for (const cr of (crs.body?.['1'] ?? [])) {
- if (cr['7'] == name) {
- let tag = document.createElement('material-chip');
- tag.classList.add('TWPT-tag');
-
- let container = document.createElement('div');
- container.classList.add('TWPT-chip-content-container');
-
- let content = document.createElement('div');
- content.classList.add('TWPT-content');
-
- const [badge, badgeTooltip] = createExtBadge();
-
- let label = document.createElement('span');
- label.textContent = 'Used ' + (cr['8'] ?? '0') + ' times';
-
- content.append(badge, label);
- container.append(content);
- tag.append(container);
- tags.append(tag);
-
- new MDCTooltip(badgeTooltip);
-
- if (cr['9']) {
- const lastUsedTime = Math.floor(parseInt(cr['9']) / 1e3);
- let date = (new Date(lastUsedTime)).toLocaleString();
- createPlainTooltip(label, 'Last used: ' + date);
+ // If another CR has the same name, there's no easy way to distinguish
+ // them, so don't show the usage stats.
+ if (crs.duplicateNames.has(name)) {
+ console.info(
+ 'CR "' + name +
+ '" is duplicate, so skipping the injection of usage stats.');
+ return;
}
- break;
- }
- }
- });
+ for (const cr of (crs.body?.['1'] ?? [])) {
+ if (cr['7'] == name) {
+ let tag = document.createElement('material-chip');
+ tag.classList.add('TWPT-tag');
+
+ let container = document.createElement('div');
+ container.classList.add('TWPT-chip-content-container');
+
+ let content = document.createElement('div');
+ content.classList.add('TWPT-content');
+
+ const [badge, badgeTooltip] = createExtBadge();
+
+ let label = document.createElement('span');
+ label.textContent = 'Used ' + (cr['8'] ?? '0') + ' times';
+
+ content.append(badge, label);
+ container.append(content);
+ tag.append(container);
+ tags.append(tag);
+
+ new MDCTooltip(badgeTooltip);
+
+ if (cr['9']) {
+ const lastUsedTime = Math.floor(parseInt(cr['9']) / 1e3);
+ let date = (new Date(lastUsedTime)).toLocaleString();
+ createPlainTooltip(label, 'Last used: ' + date);
+ }
+
+ break;
+ }
+ }
+ })
+ .catch(err => {
+ console.error(
+ 'extraInfo: error while injecting profile extra info: ', err);
+ });
}
injectAtCRIfEnabled(tags, isExpanded) {
@@ -481,47 +495,55 @@
let content = question.querySelector('ec-question > .content');
if (!content) return;
- waitFor(() => {
- let now = Date.now();
- let threadInfo = this.lastThread.body['1']?.['2']?.['1'];
- if (now - this.lastThread.timestamp < 30 * 1000 &&
- threadInfo?.['1'] == currentPage.thread &&
- threadInfo?.['3'] == currentPage.forum)
- return Promise.resolve(this.lastThread);
- return Promise.reject(new Error('Didn\'t receive thread information'));
- }, {
- interval: 500,
- timeout: 30 * 1000,
- }).then(thread => {
- let info = [];
+ waitFor(
+ () => {
+ let now = Date.now();
+ let threadInfo = this.lastThread.body['1']?.['2']?.['1'];
+ if (now - this.lastThread.timestamp < 30 * 1000 &&
+ threadInfo?.['1'] == currentPage.thread &&
+ threadInfo?.['3'] == currentPage.forum)
+ return Promise.resolve(this.lastThread);
+ return Promise.reject(
+ new Error('Didn\'t receive thread information'));
+ },
+ {
+ interval: 500,
+ timeout: 30 * 1000,
+ })
+ .then(thread => {
+ let info = [];
- const endPendingStateTimestampMicros = thread.body['1']?.['2']?.['39'];
- const [pendingStateInfo, pendingTooltip] =
- this.getPendingStateInfo(endPendingStateTimestampMicros);
- if (pendingStateInfo) info.push(pendingStateInfo);
+ const endPendingStateTimestampMicros =
+ thread.body['1']?.['2']?.['39'];
+ const [pendingStateInfo, pendingTooltip] =
+ this.getPendingStateInfo(endPendingStateTimestampMicros);
+ if (pendingStateInfo) info.push(pendingStateInfo);
- // NOTE: These attributes don't seem to be included when calling
- // ViewThread (but are included when calling ViewForum).
- const isTrending = thread.body['1']?.['2']?.['25'];
- const isTrendingAutoMarked = thread.body['1']?.['39'];
- if (isTrendingAutoMarked)
- info.push(document.createTextNode('Automatically marked as trending'));
- else if (isTrending)
- info.push(document.createTextNode('Trending'));
+ const isTrending = thread.body['1']?.['2']?.['25'];
+ const isTrendingAutoMarked = thread.body['1']?.['39'];
+ if (isTrendingAutoMarked)
+ info.push(
+ document.createTextNode('Automatically marked as trending'));
+ else if (isTrending)
+ info.push(document.createTextNode('Trending'));
- const itemMetadata = thread.body['1']?.['2']?.['12'];
- const mdInfo = this.getMetadataInfo(itemMetadata);
- info.push(...mdInfo);
+ const itemMetadata = thread.body['1']?.['2']?.['12'];
+ const mdInfo = this.getMetadataInfo(itemMetadata);
+ info.push(...mdInfo);
- const liveReviewStatus = thread.body['1']?.['2']?.['38'];
- const [liveReviewInfo, liveReviewTooltip] =
- this.getLiveReviewStatusInfo(liveReviewStatus);
- if (liveReviewInfo) info.push(liveReviewInfo);
+ const liveReviewStatus = thread.body['1']?.['2']?.['38'];
+ const [liveReviewInfo, liveReviewTooltip] =
+ this.getLiveReviewStatusInfo(liveReviewStatus);
+ if (liveReviewInfo) info.push(liveReviewInfo);
- this.addExtraInfoElement(info, content);
- if (pendingTooltip) new MDCTooltip(pendingTooltip);
- if (liveReviewTooltip) new MDCTooltip(liveReviewTooltip);
- });
+ this.addExtraInfoElement(info, content);
+ if (pendingTooltip) new MDCTooltip(pendingTooltip);
+ if (liveReviewTooltip) new MDCTooltip(liveReviewTooltip);
+ })
+ .catch(err => {
+ console.error(
+ 'extraInfo: error while injecting question extra info: ', err);
+ });
}
injectAtQuestionIfEnabled(question) {
@@ -608,52 +630,69 @@
injectAtMessage(messageNode) {
let currentPage = parseUrl(location.href);
- if (currentPage === false) return;
+ if (currentPage === false) {
+ console.error('extraInfo: couldn\'t parse current URL:', location.href);
+ return;
+ }
let footer = messageNode.querySelector('.footer-fill');
- if (!footer) return;
+ if (!footer) {
+ console.error('extraInfo: message doesn\'t have a footer:', messageNode);
+ return;
+ }
const [type, index] =
this.getMessageInfo(this.lastThread.body, messageNode);
+ if (index == -1) {
+ console.error('extraInfo: this.getMessageInfo() returned index -1.');
+ return;
+ }
- waitFor(() => {
- let now = Date.now();
- let threadInfo = this.lastThread.body['1']?.['2']?.['1'];
- if (now - this.lastThread.timestamp < 30 * 1000 &&
- threadInfo?.['1'] == currentPage.thread &&
- threadInfo?.['3'] == currentPage.forum) {
- const message =
- this.getMessageByTypeAndIndex(this.lastThread.body, type, index);
- if (message) return Promise.resolve(message);
- }
+ waitFor(
+ () => {
+ let now = Date.now();
+ let threadInfo = this.lastThread.body['1']?.['2']?.['1'];
+ if (now - this.lastThread.timestamp < 30 * 1000 &&
+ threadInfo?.['1'] == currentPage.thread &&
+ threadInfo?.['3'] == currentPage.forum) {
+ const message = this.getMessageByTypeAndIndex(
+ this.lastThread.body, type, index);
+ if (message) return Promise.resolve(message);
+ }
- return Promise.reject(new Error(
- 'Didn\'t receive thread information (type: ' + type +
- ', index: ' + index + ')'));
- }, {
- interval: 1000,
- timeout: 30 * 1000,
- }).then(message => {
- let info = [];
+ return Promise.reject(new Error(
+ 'Didn\'t receive thread information (type: ' + type +
+ ', index: ' + index + ')'));
+ },
+ {
+ interval: 1000,
+ timeout: 30 * 1000,
+ })
+ .then(message => {
+ let info = [];
- const endPendingStateTimestampMicros = message['1']?.['17'];
- const [pendingStateInfo, pendingTooltip] =
- this.getPendingStateInfo(endPendingStateTimestampMicros);
- if (pendingStateInfo) info.push(pendingStateInfo);
+ const endPendingStateTimestampMicros = message['1']?.['17'];
+ const [pendingStateInfo, pendingTooltip] =
+ this.getPendingStateInfo(endPendingStateTimestampMicros);
+ if (pendingStateInfo) info.push(pendingStateInfo);
- const itemMetadata = message['1']?.['5'];
- const mdInfo = this.getMetadataInfo(itemMetadata);
- info.push(...mdInfo);
+ const itemMetadata = message['1']?.['5'];
+ const mdInfo = this.getMetadataInfo(itemMetadata);
+ info.push(...mdInfo);
- const liveReviewStatus = message['1']?.['36'];
- const [liveReviewInfo, liveReviewTooltip] =
- this.getLiveReviewStatusInfo(liveReviewStatus);
- if (liveReviewInfo) info.push(liveReviewInfo);
+ const liveReviewStatus = message['1']?.['36'];
+ const [liveReviewInfo, liveReviewTooltip] =
+ this.getLiveReviewStatusInfo(liveReviewStatus);
+ if (liveReviewInfo) info.push(liveReviewInfo);
- this.addExtraInfoElement(info, footer);
- if (pendingTooltip) new MDCTooltip(pendingTooltip);
- if (liveReviewTooltip) new MDCTooltip(liveReviewTooltip);
- });
+ this.addExtraInfoElement(info, footer);
+ if (pendingTooltip) new MDCTooltip(pendingTooltip);
+ if (liveReviewTooltip) new MDCTooltip(liveReviewTooltip);
+ })
+ .catch(err => {
+ console.error(
+ 'extraInfo: error while injecting message extra info: ', err);
+ });
}
injectAtMessageIfEnabled(message) {
@@ -667,24 +706,32 @@
*/
injectPerForumStats(chart) {
- waitFor(() => {
- let now = Date.now();
- if (now - this.lastProfile.timestamp < 15 * 1000)
- return Promise.resolve(this.lastProfile);
- return Promise.reject(new Error(
- 'Didn\'t receive profile information (for per-profile stats)'));
- }, {
- interval: 500,
- timeout: 15 * 1000,
- }).then(profile => {
- const message = {
- action: 'injectPerForumStatsSection',
- prefix: 'TWPT-extrainfo',
- profile: profile.body,
- locale: this.displayLanguage,
- };
- window.postMessage(message, '*');
- });
+ waitFor(
+ () => {
+ let now = Date.now();
+ if (now - this.lastProfile.timestamp < 15 * 1000)
+ return Promise.resolve(this.lastProfile);
+ return Promise.reject(new Error(
+ 'Didn\'t receive profile information (for per-profile stats)'));
+ },
+ {
+ interval: 500,
+ timeout: 15 * 1000,
+ })
+ .then(profile => {
+ const message = {
+ action: 'injectPerForumStatsSection',
+ prefix: 'TWPT-extrainfo',
+ profile: profile.body,
+ locale: this.displayLanguage,
+ };
+ window.postMessage(message, '*');
+ })
+ .catch(err => {
+ console.error(
+ 'extraInfo: error while preparing to inject per-forum stats: ',
+ err);
+ });
}
injectPerForumStatsIfEnabled(chart) {