From 81506203c4e385392b731f0678677b087c0c1941 Mon Sep 17 00:00:00 2001 From: Wilfred Asomani Date: Fri, 27 Oct 2023 11:35:31 +0000 Subject: [PATCH] web/satellite/vuetify-poc: add image preview to browser card view This change adds image preview to the browser card view. Issue: #6427 Change-Id: Iab8110fb3fa70fea29a98d8f96bac9b357dd401d --- .../components/BrowserCardViewComponent.vue | 69 +++++++++++++++- .../vuetify-poc/src/components/FileCard.vue | 81 ++++++++++++++----- .../vuetify-poc/src/views/Bucket.vue | 29 ++++--- 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/web/satellite/vuetify-poc/src/components/BrowserCardViewComponent.vue b/web/satellite/vuetify-poc/src/components/BrowserCardViewComponent.vue index cfbac480f..229cd99a8 100644 --- a/web/satellite/vuetify-poc/src/components/BrowserCardViewComponent.vue +++ b/web/satellite/vuetify-poc/src/components/BrowserCardViewComponent.vue @@ -43,10 +43,7 @@ import { computed, ref, watch } from 'vue'; import { useRouter } from 'vue-router'; import { VBtn, VCard, VCardText, VCol, VDivider, VRow } from 'vuetify/components'; -import { - BrowserObject, - useObjectBrowserStore, -} from '@/store/modules/objectBrowserStore'; +import { BrowserObject, PreviewCache, useObjectBrowserStore } from '@/store/modules/objectBrowserStore'; import { useProjectsStore } from '@/store/modules/projectsStore'; import { useNotify } from '@/utils/hooks'; import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames'; @@ -55,6 +52,7 @@ import { useConfigStore } from '@/store/modules/configStore'; import { LocalData } from '@/utils/localData'; import { useAppStore } from '@/store/modules/appStore'; import { BrowserObjectTypeInfo, BrowserObjectWrapper, EXTENSION_INFOS, FILE_INFO, FOLDER_INFO } from '@/types/browser'; +import { useLinksharing } from '@/composables/useLinksharing'; import FilePreviewDialog from '@poc/components/dialogs/FilePreviewDialog.vue'; import DeleteFileDialog from '@poc/components/dialogs/DeleteFileDialog.vue'; @@ -80,6 +78,8 @@ const appStore = useAppStore(); const notify = useNotify(); const router = useRouter(); +const { generateObjectPreviewAndMapURL } = useLinksharing(); + const isFetching = ref(false); const search = ref(''); const selected = ref([]); @@ -90,6 +90,13 @@ const fileToShare = ref(null); const isShareDialogShown = ref(false); const isFileGuideShown = ref(false); +/** + * Returns object preview URLs cache from store. + */ +const cachedObjectPreviewURLs = computed((): Map => { + return obStore.state.cachedObjectPreviewURLs; +}); + /** * Returns the name of the selected bucket. */ @@ -198,6 +205,60 @@ function onShareClick(file: BrowserObject): void { isShareDialogShown.value = true; } +/** + * Get the object preview url. + */ +async function fetchPreviewUrl(file : BrowserObject) { + let url = ''; + try { + url = await generateObjectPreviewAndMapURL(bucketsStore.state.fileComponentBucketName, file.path + file.Key); + } catch (error) { + error.message = `Unable to get file preview URL. ${error.message}`; + notify.notifyError(error, AnalyticsErrorEventSource.FILE_BROWSER_ENTRY); + } + + if (!url) { + return; + } + const filePath = encodeURIComponent(`${bucketName.value}/${file.path}${file.Key}`); + obStore.cacheObjectPreviewURL(filePath, { url, lastModified: file.LastModified.getTime() }); +} + +/** + * Try to find current object's url in cache. + */ +function findCachedURL(file: BrowserObject): string | undefined { + const filePath = encodeURIComponent(`${bucketName.value}/${file.path}${file.Key}`); + const cache = cachedObjectPreviewURLs.value.get(filePath); + + if (!cache) return undefined; + + if (cache.lastModified !== file.LastModified.getTime()) { + obStore.removeFromObjectPreviewCache(filePath); + return undefined; + } + + return cache.url; +} + +/** + * Loads object URL from cache or generates new URL. + */ +async function processFilePath(file: BrowserObjectWrapper) { + if (file.browserObject.type === 'folder') return; + if (file.typeInfo.title !== 'Image') return; + const url = findCachedURL(file.browserObject); + if (!url) { + await fetchPreviewUrl(file.browserObject); + } +} + watch(filePath, fetchFiles, { immediate: true }); watch(() => props.forceEmpty, v => !v && fetchFiles()); + +watch(allFiles, async (files: BrowserObjectWrapper[]) => { + for (const file of files) { + await processFilePath(file); + } +}); \ No newline at end of file diff --git a/web/satellite/vuetify-poc/src/components/FileCard.vue b/web/satellite/vuetify-poc/src/components/FileCard.vue index e2998f211..00d2eed45 100644 --- a/web/satellite/vuetify-poc/src/components/FileCard.vue +++ b/web/satellite/vuetify-poc/src/components/FileCard.vue @@ -4,12 +4,18 @@