diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-02-22 16:45:07 +0100 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-03-11 16:02:34 +0100 |
commit | 5f19acec9bcff664f4e1516f2a58e1d1de1b7a3b (patch) | |
tree | 5a431d96a6f03dcc870a09392065088425a6a887 | |
parent | 84cb04f7c068defef353db8823ca8666d85874af (diff) | |
download | nextcloud-server-5f19acec9bcff664f4e1516f2a58e1d1de1b7a3b.tar.gz nextcloud-server-5f19acec9bcff664f4e1516f2a58e1d1de1b7a3b.zip |
feat: Add composable to fetch app icon as SVG for inline use
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r-- | apps/settings/src/composables/useAppIcon.ts | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/apps/settings/src/composables/useAppIcon.ts b/apps/settings/src/composables/useAppIcon.ts new file mode 100644 index 00000000000..719836433e8 --- /dev/null +++ b/apps/settings/src/composables/useAppIcon.ts @@ -0,0 +1,52 @@ +import type { Ref } from 'vue' +import type { IAppstoreApp } from '../app-types.ts' + +import { mdiCog } from '@mdi/js' +import { computed, ref, watchEffect } from 'vue' +import AppstoreCategoryIcons from '../constants/AppstoreCategoryIcons.ts' +import logger from '../logger.ts' + +/** + * Get the app icon raw SVG for use with `NcIconSvgWrapper` (do never use without sanitizing) + * It has a fallback to the categroy icon. + * + * @param app The app to get the icon for + */ +export function useAppIcon(app: Ref<IAppstoreApp>) { + const appIcon = ref<string|null>(null) + + /** + * Fallback value if no app icon available + */ + const categoryIcon = computed(() => { + const path = [app.value?.category ?? []].flat() + .map((name) => AppstoreCategoryIcons[name]) + .filter((icon) => !!icon) + .at(0) + ?? mdiCog + return path ? `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="${path}" /></svg>` : null + }) + + watchEffect(async () => { + // Note: Only variables until the first `await` will be watched! + if (!app.value?.preview) { + appIcon.value = categoryIcon.value + } else { + appIcon.value = null + // Now try to load the real app icon + try { + const response = await window.fetch(app.value.preview) + const blob = await response.blob() + const rawSvg = await blob.text() + appIcon.value = rawSvg.replaceAll(/fill="#(fff|ffffff)([a-z0-9]{1,2})?"/ig, 'fill="currentColor"') + } catch (error) { + appIcon.value = categoryIcon.value + logger.error('Could not load app icon', { error }) + } + } + }) + + return { + appIcon, + } +} |