From 709fefe7c969364771b77500cd9d80a12ea0190e Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sun, 31 Dec 2023 01:17:51 +0100 Subject: [PATCH] Handle extension update failure The failure was never handled and instead, the update was infinitely stuck in progress. --- src/components/ExtensionCard.tsx | 74 +++++++++++++++++++++----------- src/i18n/locale/en.json | 4 +- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/components/ExtensionCard.tsx b/src/components/ExtensionCard.tsx index 01e2d40c7b..26f7c48eb1 100644 --- a/src/components/ExtensionCard.tsx +++ b/src/components/ExtensionCard.tsx @@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next'; import { PartialExtension, TranslationKey } from '@/typings'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts'; +import { makeToast } from '@/components/util/Toast.tsx'; interface IProps { extension: PartialExtension; @@ -62,6 +63,30 @@ const INSTALLED_STATE_TO_TRANSLATION_KEY_MAP: { [installedState in InstalledStat [InstalledState.INSTALLING]: 'extension.state.label.installing', } as const; +const EXTENSION_ACTION_TO_FAILURE_TRANSLATION_KEY_MAP: { + [action in ExtensionAction]: TranslationKey; +} = { + [ExtensionAction.UPDATE]: 'extension.label.update_failed', + [ExtensionAction.INSTALL]: 'extension.label.installation_failed', + [ExtensionAction.UNINSTALL]: 'extension.label.uninstallation_failed', +}; + +const getInstalledState = ( + isInstalled: boolean, + isObsolete: boolean, + hasUpdate: boolean, +): ExtensionAction | ExtensionState.OBSOLETE => { + if (isObsolete) { + return InstalledState.OBSOLETE; + } + + if (hasUpdate) { + return InstalledState.UPDATE; + } + + return isInstalled ? InstalledState.UNINSTALL : InstalledState.INSTALL; +}; + export function ExtensionCard(props: IProps) { const { t } = useTranslation(); @@ -69,15 +94,9 @@ export function ExtensionCard(props: IProps) { extension: { name, lang, versionName, isInstalled, hasUpdate, isObsolete, pkgName, iconUrl, isNsfw }, handleUpdate, } = props; - const [installedState, setInstalledState] = useState(() => { - if (isObsolete) { - return InstalledState.OBSOLETE; - } - if (hasUpdate) { - return InstalledState.UPDATE; - } - return isInstalled ? InstalledState.UNINSTALL : InstalledState.INSTALL; - }); + const [installedState, setInstalledState] = useState( + getInstalledState(isInstalled, isObsolete, hasUpdate), + ); const langPress = lang === 'all' ? t('extension.language.all') : lang.toUpperCase(); @@ -85,23 +104,28 @@ export function ExtensionCard(props: IProps) { const nextAction = EXTENSION_ACTION_TO_NEXT_ACTION_MAP[action]; const state = EXTENSION_ACTION_TO_STATE_MAP[action]; - setInstalledState(state); - switch (action) { - case ExtensionAction.INSTALL: - await requestManager.updateExtension(pkgName, { install: true }).response; - break; - case ExtensionAction.UNINSTALL: - await requestManager.updateExtension(pkgName, { uninstall: true }).response; - break; - case ExtensionAction.UPDATE: - await requestManager.updateExtension(pkgName, { update: true }).response; - break; - default: - throw new Error(`Unexpected ExtensionAction "${action}"`); + try { + setInstalledState(state); + switch (action) { + case ExtensionAction.INSTALL: + await requestManager.updateExtension(pkgName, { install: true }).response; + break; + case ExtensionAction.UNINSTALL: + await requestManager.updateExtension(pkgName, { uninstall: true }).response; + break; + case ExtensionAction.UPDATE: + await requestManager.updateExtension(pkgName, { update: true }).response; + break; + default: + throw new Error(`Unexpected ExtensionAction "${action}"`); + } + setInstalledState(nextAction); + + handleUpdate(); + } catch (e) { + setInstalledState(getInstalledState(isInstalled, isObsolete, hasUpdate)); + makeToast(t(EXTENSION_ACTION_TO_FAILURE_TRANSLATION_KEY_MAP[action]), 'error'); } - setInstalledState(nextAction); - - handleUpdate(); }; function handleButtonClick() { diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 7ecfc1cdda..126dfd9bee 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -225,7 +225,9 @@ "label": { "installation_failed": "Could not install the extension", "installed_successfully": "Extension installed", - "installing_file": "Installing extension file…" + "installing_file": "Installing extension file…", + "uninstallation_failed": "Could not uninstall the extension", + "update_failed": "Could not update the extension" }, "language": { "all": "All",