web/satellite: add gallery view caching

Add caching for gallery view previews and map.

Issue:
https://github.com/storj/storj/issues/5969

Change-Id: I6c9755aec6e1d4143005835adad212cafd46f649
This commit is contained in:
Vitalii 2023-06-22 16:31:30 +03:00 committed by Storj Robot
parent 578724e9b1
commit 6f078acb8d
2 changed files with 74 additions and 8 deletions

View File

@ -116,10 +116,11 @@ import { Component, computed, onBeforeMount, onMounted, ref, Teleport, watch } f
import { useRoute } from 'vue-router';
import prettyBytes from 'pretty-bytes';
import { BrowserObject, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
import { BrowserObject, PreviewCache, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { useAppStore } from '@/store/modules/appStore';
import { useNotify } from '@/utils/hooks';
import { useBucketsStore } from '@/store/modules/bucketsStore';
import { RouteConfig } from '@/types/router';
import ButtonIcon from '@/components/browser/galleryView/ButtonIcon.vue';
@ -145,6 +146,7 @@ import ArrowIcon from '@/../static/images/browser/galleryView/arrow.svg';
const appStore = useAppStore();
const obStore = useObjectBrowserStore();
const bucketsStore = useBucketsStore();
const notify = useNotify();
const route = useRoute();
@ -159,6 +161,13 @@ const objectPreviewUrl = ref<string>('');
const folderType = 'folder';
/**
* Returns object preview URLs cache from store.
*/
const cachedObjectPreviewURLs = computed((): Map<string, PreviewCache> => {
return obStore.state.cachedObjectPreviewURLs;
});
/**
* Retrieve the file object that the modal is set to from the store.
*/
@ -194,6 +203,13 @@ const extension = computed((): string | undefined => {
return filePath.value.split('.').pop();
});
/**
* Returns bucket name from store.
*/
const bucket = computed((): string => {
return bucketsStore.state.fileComponentBucketName;
});
/**
* Check to see if the current file is an image file.
*/
@ -263,6 +279,9 @@ async function fetchPreviewAndMapUrl(): Promise<void> {
return;
}
const encodedPath = encodeURIComponent(`${bucket.value}/${filePath.value.trim()}`);
obStore.cacheObjectPreviewURL(encodedPath, { url, lastModified: file.value.LastModified.getTime() });
objectMapUrl.value = `${url}?map=1`;
objectPreviewUrl.value = `${url}?view=1`;
isLoading.value = false;
@ -386,11 +405,41 @@ function setNewObjectPath(objectKey: string): void {
obStore.setObjectPathForModal(`${currentPath.value}${objectKey}`);
}
/**
* Loads object URL from cache or generates new URL.
*/
function processFilePath(): void {
const url = findCachedURL();
if (!url) {
fetchPreviewAndMapUrl();
return;
}
objectMapUrl.value = `${url}?map=1`;
objectPreviewUrl.value = `${url}?view=1`;
}
/**
* Try to find current object path in cache.
*/
function findCachedURL(): string | undefined {
const encodedPath = encodeURIComponent(`${bucket.value}/${filePath.value.trim()}`);
const cache = cachedObjectPreviewURLs.value.get(encodedPath);
if (!cache) return undefined;
if (cache.lastModified !== file.value.LastModified.getTime()) {
obStore.removeFromObjectPreviewCache(encodedPath);
return undefined;
}
return cache.url;
}
/**
* Call `fetchPreviewAndMapUrl` on before mount lifecycle method.
*/
onBeforeMount((): void => {
fetchPreviewAndMapUrl();
processFilePath();
});
onMounted((): void => {
@ -403,7 +452,7 @@ onMounted((): void => {
watch(filePath, () => {
if (!filePath.value) return;
fetchPreviewAndMapUrl();
processFilePath();
});
</script>

View File

@ -31,7 +31,7 @@ type Promisable<T> = T | PromiseLike<T>;
export type BrowserObject = {
Key: string;
Size: number;
LastModified: number;
LastModified: Date;
type?: 'file' | 'folder';
progress?: number;
upload?: {
@ -58,6 +58,11 @@ export type UploadingBrowserObject = BrowserObject & {
failedMessage?: FailedUploadMessage;
}
export type PreviewCache = {
url: string,
lastModified: number,
}
export class FilesState {
s3: S3Client | null = null;
accessKey: null | string = null;
@ -80,6 +85,7 @@ export class FilesState {
openModalOnFirstUpload = false;
objectPathForModal = '';
objectsCount = 0;
cachedObjectPreviewURLs: Map<string, PreviewCache> = new Map<string, PreviewCache>();
}
type InitializedFilesState = FilesState & {
@ -273,7 +279,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
Prefix: string;
}): BrowserObject => ({
Key: Prefix.slice(path.length, -1),
LastModified: 0,
LastModified: new Date(),
Size: 0,
type: 'folder',
});
@ -455,7 +461,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
upload,
progress: 0,
Size: 0,
LastModified: 0,
LastModified: new Date(),
Body: file,
status: UploadingStatus.Failed,
failedMessage: FailedUploadMessage.TooBig,
@ -471,7 +477,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
upload,
progress: 0,
Size: 0,
LastModified: 0,
LastModified: new Date(),
status: UploadingStatus.InProgress,
});
@ -552,7 +558,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
upload,
progress: 0,
Size: 0,
LastModified: 0,
LastModified: new Date(),
status: UploadingStatus.InProgress,
};
@ -770,6 +776,14 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
state.objectPathForModal = path;
}
function cacheObjectPreviewURL(path: string, cacheValue: PreviewCache): void {
state.cachedObjectPreviewURLs.set(path, cacheValue);
}
function removeFromObjectPreviewCache(path: string): void {
state.cachedObjectPreviewURLs.delete(path);
}
function setSelectedAnchorFile(file: BrowserObject | null): void {
state.selectedAnchorFile = file;
}
@ -803,6 +817,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
state.orderBy = 'asc';
state.openModalOnFirstUpload = false;
state.objectPathForModal = '';
state.cachedObjectPreviewURLs = new Map<string, PreviewCache>();
}
return {
@ -835,6 +850,8 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
setSelectedAnchorFile,
setUnselectedAnchorFile,
cancelUpload,
cacheObjectPreviewURL,
removeFromObjectPreviewCache,
clearUploading,
clear,
};