import { AssetGridState } from '$lib/models/asset-grid-state'; import { api, AssetResponseDto } from '@api'; import { derived, writable } from 'svelte/store'; import { assetGridState, assetStore } from './assets.store'; import _ from 'lodash-es'; // Asset Viewer export const viewingAssetStoreState = writable(); export const isViewingAssetStoreState = writable(false); // Multi-Selection mode export const assetsInAlbumStoreState = writable([]); export const selectedAssets = writable>(new Set()); export const selectedGroup = writable>(new Set()); export const isMultiSelectStoreState = derived( selectedAssets, ($selectedAssets) => $selectedAssets.size > 0 ); function createAssetInteractionStore() { let _assetGridState = new AssetGridState(); let _viewingAssetStoreState: AssetResponseDto; let _selectedAssets: Set; let _selectedGroup: Set; let _assetsInAblums: AssetResponseDto[]; let savedAssetLength = 0; let assetSortedByDate: AssetResponseDto[] = []; // Subscriber assetGridState.subscribe((state) => { _assetGridState = state; }); viewingAssetStoreState.subscribe((asset) => { _viewingAssetStoreState = asset; }); selectedAssets.subscribe((assets) => { _selectedAssets = assets; }); selectedGroup.subscribe((group) => { _selectedGroup = group; }); assetsInAlbumStoreState.subscribe((assets) => { _assetsInAblums = assets; }); // Methods /** * Asset Viewer */ const setViewingAsset = async (asset: AssetResponseDto) => { const { data } = await api.assetApi.getAssetById(asset.id); viewingAssetStoreState.set(data); isViewingAssetStoreState.set(true); }; const setIsViewingAsset = (isViewing: boolean) => { isViewingAssetStoreState.set(isViewing); }; const navigateAsset = async (direction: 'next' | 'previous') => { // Flatten and sort the asset by date if there are new assets if (assetSortedByDate.length === 0 || savedAssetLength !== _assetGridState.assets.length) { assetSortedByDate = _.sortBy(_assetGridState.assets, (a) => a.createdAt); savedAssetLength = _assetGridState.assets.length; } // Find the index of the current asset const currentIndex = assetSortedByDate.findIndex((a) => a.id === _viewingAssetStoreState.id); // Get the next or previous asset const nextIndex = direction === 'previous' ? currentIndex + 1 : currentIndex - 1; // Run out of asset, this might be because there is no asset in the next bucket. if (nextIndex == -1) { let nextBucket = ''; // Find next bucket that doesn't have all assets loaded for (const bucket of _assetGridState.buckets) { if (bucket.assets.length === 0) { nextBucket = bucket.bucketDate; break; } } if (nextBucket !== '') { await assetStore.getAssetsByBucket(nextBucket); navigateAsset(direction); } return; } const nextAsset = assetSortedByDate[nextIndex]; setViewingAsset(nextAsset); }; /** * Multiselect */ const addAssetToMultiselectGroup = (asset: AssetResponseDto) => { // Not select if in album alreaady if (_assetsInAblums.find((a) => a.id === asset.id)) { return; } _selectedAssets.add(asset); selectedAssets.set(_selectedAssets); }; const removeAssetFromMultiselectGroup = (asset: AssetResponseDto) => { _selectedAssets.delete(asset); selectedAssets.set(_selectedAssets); }; const addGroupToMultiselectGroup = (group: string) => { _selectedGroup.add(group); selectedGroup.set(_selectedGroup); }; const removeGroupFromMultiselectGroup = (group: string) => { _selectedGroup.delete(group); selectedGroup.set(_selectedGroup); }; const clearMultiselect = () => { _selectedAssets.clear(); _selectedGroup.clear(); _assetsInAblums = []; selectedAssets.set(_selectedAssets); selectedGroup.set(_selectedGroup); assetsInAlbumStoreState.set(_assetsInAblums); }; return { setViewingAsset, setIsViewingAsset, navigateAsset, addAssetToMultiselectGroup, removeAssetFromMultiselectGroup, addGroupToMultiselectGroup, removeGroupFromMultiselectGroup, clearMultiselect }; } export const assetInteractionStore = createAssetInteractionStore();