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:
parent
578724e9b1
commit
6f078acb8d
@ -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>
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user