add: indicate sync error as 'x' in icon badge (#1166)

* indicate sync error as 'x' in icon badge

* fix/simplify

* Add: show more errors on badge

Co-authored-by: eight04 <eight04@gmail.com>
This commit is contained in:
tophf 2021-02-09 09:58:30 +03:00 committed by GitHub
parent 1746235d0d
commit c60c764d34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 23 deletions

View File

@ -1530,6 +1530,14 @@
"message": "The value cannot be saved. Try reducing the amount of text.", "message": "The value cannot be saved. Try reducing the amount of text.",
"description": "Displayed when trying to save an excessively big value via storage.sync API" "description": "Displayed when trying to save an excessively big value via storage.sync API"
}, },
"syncError": {
"message": "Sync failed",
"description": "Tooltip for the toolbar icon"
},
"syncErrorRelogin": {
"message": "Sync failed.\nTry to re-login in Stylus options:\nclick 'disconnect' first, then 'connect'.",
"description": "Tooltip for the toolbar icon"
},
"toggleStyle": { "toggleStyle": {
"message": "Toggle style", "message": "Toggle style",
"description": "Label for the checkbox to enable/disable a style" "description": "Label for the checkbox to enable/disable a style"

View File

@ -5,10 +5,12 @@
/* global CHROME FIREFOX VIVALDI debounce ignoreChromeError */// toolbox.js /* global CHROME FIREFOX VIVALDI debounce ignoreChromeError */// toolbox.js
'use strict'; 'use strict';
(() => { /* exported iconMan */
const iconMan = (() => {
const ICON_SIZES = FIREFOX || CHROME >= 55 && !VIVALDI ? [16, 32] : [19, 38]; const ICON_SIZES = FIREFOX || CHROME >= 55 && !VIVALDI ? [16, 32] : [19, 38];
const staleBadges = new Set(); const staleBadges = new Set();
const imageDataCache = new Map(); const imageDataCache = new Map();
const badgeOvr = {color: '', text: ''};
// https://github.com/openstyles/stylus/issues/335 // https://github.com/openstyles/stylus/issues/335
let hasCanvas = loadImage(`/images/icon/${ICON_SIZES[0]}.png`) let hasCanvas = loadImage(`/images/icon/${ICON_SIZES[0]}.png`)
.then(({data}) => (hasCanvas = data.some(b => b !== 255))); .then(({data}) => (hasCanvas = data.some(b => b !== 255)));
@ -54,6 +56,27 @@
], () => debounce(refreshAllIcons), {runNow: true}); ], () => debounce(refreshAllIcons), {runNow: true});
}); });
return {
/** Calling with no params clears the override */
overrideBadge({text = '', color = '', title = ''} = {}) {
if (badgeOvr.text === text) {
return;
}
badgeOvr.text = text;
badgeOvr.color = color;
refreshIconBadgeColor();
setBadgeText({text});
for (const tabId of tabMan.list()) {
if (badgeOvr) {
setBadgeText({tabId, text});
} else {
refreshIconBadgeText(tabId);
}
}
chrome.browserAction.setTitle({title});
},
};
function onPortDisconnected({sender}) { function onPortDisconnected({sender}) {
if (tabMan.get(sender.tab.id, 'styleIds')) { if (tabMan.get(sender.tab.id, 'styleIds')) {
API.updateIconBadge.call({sender}, [], {lazyBadge: true}); API.updateIconBadge.call({sender}, [], {lazyBadge: true});
@ -61,6 +84,7 @@
} }
function refreshIconBadgeText(tabId) { function refreshIconBadgeText(tabId) {
if (badgeOvr.text) return;
const text = prefs.get('show-badge') ? `${getStyleCount(tabId)}` : ''; const text = prefs.get('show-badge') ? `${getStyleCount(tabId)}` : '';
setBadgeText({tabId, text}); setBadgeText({tabId, text});
} }
@ -133,9 +157,9 @@
} }
function refreshIconBadgeColor() { function refreshIconBadgeColor() {
const color = prefs.get(prefs.get('disableAll') ? 'badgeDisabled' : 'badgeNormal');
setBadgeBackgroundColor({ setBadgeBackgroundColor({
color, color: badgeOvr.color ||
prefs.get(prefs.get('disableAll') ? 'badgeDisabled' : 'badgeNormal'),
}); });
} }

View File

@ -1,6 +1,7 @@
/* global API msg */// msg.js /* global API msg */// msg.js
/* global chromeLocal */// storage-util.js /* global chromeLocal */// storage-util.js
/* global compareRevision */// common.js /* global compareRevision */// common.js
/* global iconMan */
/* global prefs */ /* global prefs */
/* global tokenMan */ /* global tokenMan */
'use strict'; 'use strict';
@ -26,6 +27,7 @@ const syncMan = (() => {
errorMessage: null, errorMessage: null,
login: false, login: false,
}; };
let lastError = null;
let ctrl; let ctrl;
let currentDrive; let currentDrive;
/** @type {Promise|boolean} will be `true` to avoid wasting a microtask tick on each `await` */ /** @type {Promise|boolean} will be `true` to avoid wasting a microtask tick on each `await` */
@ -99,8 +101,10 @@ const syncMan = (() => {
} }
await syncMan.syncNow(); await syncMan.syncNow();
status.errorMessage = null; status.errorMessage = null;
lastError = null;
} catch (err) { } catch (err) {
status.errorMessage = err.message; status.errorMessage = err.message;
lastError = err;
// FIXME: should we move this logic to options.js? // FIXME: should we move this logic to options.js?
if (!fromPref) { if (!fromPref) {
console.error(err); console.error(err);
@ -138,8 +142,10 @@ const syncMan = (() => {
try { try {
await (ctrl.isInit() ? ctrl.syncNow() : ctrl.start()).catch(handle401Error); await (ctrl.isInit() ? ctrl.syncNow() : ctrl.start()).catch(handle401Error);
status.errorMessage = null; status.errorMessage = null;
lastError = null;
} catch (err) { } catch (err) {
status.errorMessage = err.message; status.errorMessage = err.message;
lastError = err;
} }
emitStatusChange(); emitStatusChange();
}, },
@ -187,14 +193,14 @@ const syncMan = (() => {
} }
async function handle401Error(err) { async function handle401Error(err) {
let emit; let authError = false;
if (err.code === 401) { if (err.code === 401) {
await tokenMan.revokeToken(currentDrive.name).catch(console.error); await tokenMan.revokeToken(currentDrive.name).catch(console.error);
emit = true; authError = true;
} else if (/User interaction required|Requires user interaction/i.test(err.message)) { } else if (/User interaction required|Requires user interaction/i.test(err.message)) {
emit = true; authError = true;
} }
if (emit) { if (authError) {
status.login = false; status.login = false;
emitStatusChange(); emitStatusChange();
} }
@ -203,6 +209,32 @@ const syncMan = (() => {
function emitStatusChange() { function emitStatusChange() {
msg.broadcastExtension({method: 'syncStatusUpdate', status}); msg.broadcastExtension({method: 'syncStatusUpdate', status});
if (status.state !== STATES.connected || !lastError || isNetworkError(lastError)) {
iconMan.overrideBadge({});
} else if (isGrantError(lastError)) {
iconMan.overrideBadge({
text: 'x',
color: '#F00',
title: chrome.i18n.getMessage('syncErrorRelogin'),
});
} else {
iconMan.overrideBadge({
text: 'x',
color: '#F00',
title: chrome.i18n.getMessage('syncError'),
});
}
}
function isNetworkError(err) {
return err.name === 'TypeError' && /networkerror|failed to fetch/i.test(err.message);
}
function isGrantError(err) {
if (err.code === 401) return true;
if (err.code === 400 && /invalid_grant/.test(err.message)) return true;
return false;
} }
function getDrive(name) { function getDrive(name) {

View File

@ -53,6 +53,7 @@ const tabMan = (() => {
} }
}, },
/** @returns {IterableIterator<number>} */
list() { list() {
return cache.keys(); return cache.keys();
}, },

17
package-lock.json generated
View File

@ -645,7 +645,6 @@
"espree": "7.3.0", "espree": "7.3.0",
"esprima": "4.0.1", "esprima": "4.0.1",
"fluent-syntax": "0.13.0", "fluent-syntax": "0.13.0",
"fsevents": "2.2.1",
"glob": "7.1.6", "glob": "7.1.6",
"is-mergeable-object": "1.1.1", "is-mergeable-object": "1.1.1",
"jed": "1.1.1", "jed": "1.1.1",
@ -1855,12 +1854,6 @@
"engines": [ "engines": [
"node >=0.10.0" "node >=0.10.0"
], ],
"dependencies": {
"dtrace-provider": "~0.8",
"moment": "^2.19.3",
"mv": "~2",
"safe-json-stringify": "~1"
},
"bin": { "bin": {
"bunyan": "bin/bunyan" "bunyan": "bin/bunyan"
}, },
@ -2144,7 +2137,6 @@
"dependencies": { "dependencies": {
"anymatch": "~3.1.1", "anymatch": "~3.1.1",
"braces": "~3.0.2", "braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0", "glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0", "is-binary-path": "~2.1.0",
"is-glob": "~4.0.1", "is-glob": "~4.0.1",
@ -4559,9 +4551,6 @@
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true, "dev": true,
"dependencies": {
"graceful-fs": "^4.1.6"
},
"optionalDependencies": { "optionalDependencies": {
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
@ -6995,7 +6984,6 @@
"integrity": "sha512-ssHt0dkljEDaKmTgQ04DQgx2ag6G2gMPxA5hpcsoeTbfDgRf2fC2gNSRc6kISjD7ckCpHwwQvXxuTBK8402fXg==", "integrity": "sha512-ssHt0dkljEDaKmTgQ04DQgx2ag6G2gMPxA5hpcsoeTbfDgRf2fC2gNSRc6kISjD7ckCpHwwQvXxuTBK8402fXg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"encoding": "^0.1.12",
"minipass": "^3.1.0", "minipass": "^3.1.0",
"minipass-pipeline": "^1.2.2", "minipass-pipeline": "^1.2.2",
"minipass-sized": "^1.0.3", "minipass-sized": "^1.0.3",
@ -11284,10 +11272,8 @@
"integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": "^3.4.1",
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"neo-async": "^2.5.0", "neo-async": "^2.5.0"
"watchpack-chokidar2": "^2.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"chokidar": "^3.4.1", "chokidar": "^3.4.1",
@ -11371,7 +11357,6 @@
"anymatch": "^2.0.0", "anymatch": "^2.0.0",
"async-each": "^1.0.1", "async-each": "^1.0.1",
"braces": "^2.3.2", "braces": "^2.3.2",
"fsevents": "^1.2.7",
"glob-parent": "^3.1.0", "glob-parent": "^3.1.0",
"inherits": "^2.0.3", "inherits": "^2.0.3",
"is-binary-path": "^1.0.0", "is-binary-path": "^1.0.0",