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 { useRoute } from 'vue-router';
|
||||||
import prettyBytes from 'pretty-bytes';
|
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 { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
||||||
import { useAppStore } from '@/store/modules/appStore';
|
import { useAppStore } from '@/store/modules/appStore';
|
||||||
import { useNotify } from '@/utils/hooks';
|
import { useNotify } from '@/utils/hooks';
|
||||||
|
import { useBucketsStore } from '@/store/modules/bucketsStore';
|
||||||
import { RouteConfig } from '@/types/router';
|
import { RouteConfig } from '@/types/router';
|
||||||
|
|
||||||
import ButtonIcon from '@/components/browser/galleryView/ButtonIcon.vue';
|
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 appStore = useAppStore();
|
||||||
const obStore = useObjectBrowserStore();
|
const obStore = useObjectBrowserStore();
|
||||||
|
const bucketsStore = useBucketsStore();
|
||||||
const notify = useNotify();
|
const notify = useNotify();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -159,6 +161,13 @@ const objectPreviewUrl = ref<string>('');
|
|||||||
|
|
||||||
const folderType = 'folder';
|
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.
|
* 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();
|
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.
|
* Check to see if the current file is an image file.
|
||||||
*/
|
*/
|
||||||
@ -263,6 +279,9 @@ async function fetchPreviewAndMapUrl(): Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const encodedPath = encodeURIComponent(`${bucket.value}/${filePath.value.trim()}`);
|
||||||
|
obStore.cacheObjectPreviewURL(encodedPath, { url, lastModified: file.value.LastModified.getTime() });
|
||||||
|
|
||||||
objectMapUrl.value = `${url}?map=1`;
|
objectMapUrl.value = `${url}?map=1`;
|
||||||
objectPreviewUrl.value = `${url}?view=1`;
|
objectPreviewUrl.value = `${url}?view=1`;
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
@ -386,11 +405,41 @@ function setNewObjectPath(objectKey: string): void {
|
|||||||
obStore.setObjectPathForModal(`${currentPath.value}${objectKey}`);
|
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.
|
* Call `fetchPreviewAndMapUrl` on before mount lifecycle method.
|
||||||
*/
|
*/
|
||||||
onBeforeMount((): void => {
|
onBeforeMount((): void => {
|
||||||
fetchPreviewAndMapUrl();
|
processFilePath();
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted((): void => {
|
onMounted((): void => {
|
||||||
@ -403,7 +452,7 @@ onMounted((): void => {
|
|||||||
watch(filePath, () => {
|
watch(filePath, () => {
|
||||||
if (!filePath.value) return;
|
if (!filePath.value) return;
|
||||||
|
|
||||||
fetchPreviewAndMapUrl();
|
processFilePath();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ type Promisable<T> = T | PromiseLike<T>;
|
|||||||
export type BrowserObject = {
|
export type BrowserObject = {
|
||||||
Key: string;
|
Key: string;
|
||||||
Size: number;
|
Size: number;
|
||||||
LastModified: number;
|
LastModified: Date;
|
||||||
type?: 'file' | 'folder';
|
type?: 'file' | 'folder';
|
||||||
progress?: number;
|
progress?: number;
|
||||||
upload?: {
|
upload?: {
|
||||||
@ -58,6 +58,11 @@ export type UploadingBrowserObject = BrowserObject & {
|
|||||||
failedMessage?: FailedUploadMessage;
|
failedMessage?: FailedUploadMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type PreviewCache = {
|
||||||
|
url: string,
|
||||||
|
lastModified: number,
|
||||||
|
}
|
||||||
|
|
||||||
export class FilesState {
|
export class FilesState {
|
||||||
s3: S3Client | null = null;
|
s3: S3Client | null = null;
|
||||||
accessKey: null | string = null;
|
accessKey: null | string = null;
|
||||||
@ -80,6 +85,7 @@ export class FilesState {
|
|||||||
openModalOnFirstUpload = false;
|
openModalOnFirstUpload = false;
|
||||||
objectPathForModal = '';
|
objectPathForModal = '';
|
||||||
objectsCount = 0;
|
objectsCount = 0;
|
||||||
|
cachedObjectPreviewURLs: Map<string, PreviewCache> = new Map<string, PreviewCache>();
|
||||||
}
|
}
|
||||||
|
|
||||||
type InitializedFilesState = FilesState & {
|
type InitializedFilesState = FilesState & {
|
||||||
@ -273,7 +279,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
Prefix: string;
|
Prefix: string;
|
||||||
}): BrowserObject => ({
|
}): BrowserObject => ({
|
||||||
Key: Prefix.slice(path.length, -1),
|
Key: Prefix.slice(path.length, -1),
|
||||||
LastModified: 0,
|
LastModified: new Date(),
|
||||||
Size: 0,
|
Size: 0,
|
||||||
type: 'folder',
|
type: 'folder',
|
||||||
});
|
});
|
||||||
@ -455,7 +461,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
upload,
|
upload,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
Size: 0,
|
Size: 0,
|
||||||
LastModified: 0,
|
LastModified: new Date(),
|
||||||
Body: file,
|
Body: file,
|
||||||
status: UploadingStatus.Failed,
|
status: UploadingStatus.Failed,
|
||||||
failedMessage: FailedUploadMessage.TooBig,
|
failedMessage: FailedUploadMessage.TooBig,
|
||||||
@ -471,7 +477,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
upload,
|
upload,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
Size: 0,
|
Size: 0,
|
||||||
LastModified: 0,
|
LastModified: new Date(),
|
||||||
status: UploadingStatus.InProgress,
|
status: UploadingStatus.InProgress,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -552,7 +558,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
upload,
|
upload,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
Size: 0,
|
Size: 0,
|
||||||
LastModified: 0,
|
LastModified: new Date(),
|
||||||
status: UploadingStatus.InProgress,
|
status: UploadingStatus.InProgress,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -770,6 +776,14 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
state.objectPathForModal = path;
|
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 {
|
function setSelectedAnchorFile(file: BrowserObject | null): void {
|
||||||
state.selectedAnchorFile = file;
|
state.selectedAnchorFile = file;
|
||||||
}
|
}
|
||||||
@ -803,6 +817,7 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
state.orderBy = 'asc';
|
state.orderBy = 'asc';
|
||||||
state.openModalOnFirstUpload = false;
|
state.openModalOnFirstUpload = false;
|
||||||
state.objectPathForModal = '';
|
state.objectPathForModal = '';
|
||||||
|
state.cachedObjectPreviewURLs = new Map<string, PreviewCache>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -835,6 +850,8 @@ export const useObjectBrowserStore = defineStore('objectBrowser', () => {
|
|||||||
setSelectedAnchorFile,
|
setSelectedAnchorFile,
|
||||||
setUnselectedAnchorFile,
|
setUnselectedAnchorFile,
|
||||||
cancelUpload,
|
cancelUpload,
|
||||||
|
cacheObjectPreviewURL,
|
||||||
|
removeFromObjectPreviewCache,
|
||||||
clearUploading,
|
clearUploading,
|
||||||
clear,
|
clear,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user