From b074de26a23758b8900591f31200c8359fe6b5da Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Mon, 29 Jan 2024 20:59:27 +0100 Subject: [PATCH] Fix/install external extension does not update extension list (#580) * Update extension list after installing external extension file The cache was never updated after the installation * Make it possible to install external extension while having an empty list * Show toasts while having an empty extension list * Use correct extension id * Update extension action after manual file installation When installing an external extension the action button did not get updated due to this being an internal state of the ExtensionCard. By including this in the key, it gets ensured that the component will get correctly updated --- src/lib/requests/RequestManager.ts | 58 +++++++++++++++++++++++++++++- src/screens/Extensions.tsx | 55 +++++++++++++++++----------- 2 files changed, 92 insertions(+), 21 deletions(-) diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index f35e1a07..1380ab43 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -1005,12 +1005,68 @@ export class RequestManager { extensionFile: File, options?: MutationOptions, ): AbortableApolloMutationResponse { - return this.doRequest( + const result = this.doRequest( GQLMethod.MUTATION, INSTALL_EXTERNAL_EXTENSION, { file: extensionFile }, { refetchQueries: [GET_EXTENSIONS], ...options }, ); + + result.response.then((response) => { + this.graphQLClient.client.cache.evict({ fieldName: 'sources' }); + const cachedExtensions = this.cache.getResponseFor>( + EXTENSION_LIST_CACHE_KEY, + undefined, + ); + + const installedExtension = response.data?.installExternalExtension.extension; + + if (!cachedExtensions || !cachedExtensions.data) { + this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, { + data: { + fetchExtensions: { + extensions: [installedExtension], + }, + }, + }); + return; + } + + const isExtensionCached = !!cachedExtensions.data.fetchExtensions.extensions.find( + (extension) => installedExtension?.pkgName === extension.pkgName, + ); + + const updatedCachedExtensions: MutationResult = { + ...cachedExtensions, + data: { + ...cachedExtensions.data, + fetchExtensions: { + ...cachedExtensions.data.fetchExtensions, + extensions: isExtensionCached + ? cachedExtensions.data.fetchExtensions.extensions.map((extension) => { + const isUpdatedExtension = installedExtension?.pkgName === extension.pkgName; + if (!isUpdatedExtension) { + return extension; + } + + return { + ...extension, + ...installedExtension, + hasUpdate: installedExtension?.versionCode < extension.versionCode, + }; + }) + : [ + ...cachedExtensions.data.fetchExtensions.extensions, + installedExtension as (typeof cachedExtensions.data.fetchExtensions.extensions)[number], + ], + }, + }, + }; + + this.cache.cacheResponse(EXTENSION_LIST_CACHE_KEY, undefined, updatedCachedExtensions); + }); + + return result; } public updateExtension( diff --git a/src/screens/Extensions.tsx b/src/screens/Extensions.tsx index 62c4f402..cd35a8a7 100644 --- a/src/screens/Extensions.tsx +++ b/src/screens/Extensions.tsx @@ -160,6 +160,7 @@ export function Extensions() { requestManager .installExternalExtension(file) .response.then(() => { + handleExtensionUpdate(); makeToast(t('extension.label.installed_successfully'), 'success'); }) .catch(() => makeToast(t('extension.label.installation_failed'), 'error')); @@ -207,25 +208,8 @@ export function Extensions() { }; }, []); - if (!allExtensions && (isLoading || !called)) { - return ; - } - - const showAddRepoInfo = !allExtensions?.length && !areReposDefined; - if (showAddRepoInfo) { - return ( - - {t('extension.label.add_repository_info')} - - - ); - } - - return ( - <> - {toasts} + const FileInputComponent = useMemo( + () => ( + ), + [], + ); + + if (!allExtensions && (isLoading || !called)) { + return ; + } + + const showAddRepoInfo = !allExtensions?.length && !areReposDefined; + if (showAddRepoInfo) { + return ( + <> + {toasts} + {FileInputComponent} + + {t('extension.label.add_repository_info')} + + + + ); + } + + return ( + <> + {toasts} + {FileInputComponent} +