mirror of
https://github.com/KevinMidboe/immich.git
synced 2026-01-18 07:06:46 +00:00
feat(web): timeline bucket for albums (4) (#3604)
* feat: server changes for album timeline * feat(web): album timeline view * chore: open api * chore: remove archive action * fix: favorite for non-owners
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import type { AssetResponseDto } from '@api';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { AssetResponseDto } from '../../api/open-api';
|
||||
|
||||
export interface AssetInteractionStore {
|
||||
addAssetToMultiselectGroup: (asset: AssetResponseDto) => void;
|
||||
selectAsset: (asset: AssetResponseDto) => void;
|
||||
removeAssetFromMultiselectGroup: (asset: AssetResponseDto) => void;
|
||||
addGroupToMultiselectGroup: (group: string) => void;
|
||||
removeGroupFromMultiselectGroup: (group: string) => void;
|
||||
@@ -13,13 +13,6 @@ export interface AssetInteractionStore {
|
||||
isMultiSelectState: {
|
||||
subscribe: (run: (value: boolean) => void, invalidate?: (value?: boolean) => void) => () => void;
|
||||
};
|
||||
assetsInAlbumState: {
|
||||
subscribe: (
|
||||
run: (value: AssetResponseDto[]) => void,
|
||||
invalidate?: (value?: AssetResponseDto[]) => void,
|
||||
) => () => void;
|
||||
set: (value: AssetResponseDto[]) => void;
|
||||
};
|
||||
selectedAssets: {
|
||||
subscribe: (
|
||||
run: (value: Set<AssetResponseDto>) => void,
|
||||
@@ -46,11 +39,9 @@ export interface AssetInteractionStore {
|
||||
export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
let _selectedAssets: Set<AssetResponseDto>;
|
||||
let _selectedGroup: Set<string>;
|
||||
let _assetsInAlbums: AssetResponseDto[];
|
||||
let _assetSelectionCandidates: Set<AssetResponseDto>;
|
||||
let _assetSelectionStart: AssetResponseDto | null;
|
||||
|
||||
const assetsInAlbumStoreState = writable<AssetResponseDto[]>([]);
|
||||
// Selected assets
|
||||
const selectedAssets = writable<Set<AssetResponseDto>>(new Set());
|
||||
// Selected date groups
|
||||
@@ -72,10 +63,6 @@ export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
_selectedGroup = group;
|
||||
});
|
||||
|
||||
assetsInAlbumStoreState.subscribe((assets) => {
|
||||
_assetsInAlbums = assets;
|
||||
});
|
||||
|
||||
assetSelectionCandidates.subscribe((assets) => {
|
||||
_assetSelectionCandidates = assets;
|
||||
});
|
||||
@@ -84,12 +71,7 @@ export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
_assetSelectionStart = asset;
|
||||
});
|
||||
|
||||
const addAssetToMultiselectGroup = (asset: AssetResponseDto) => {
|
||||
// Not select if in album already
|
||||
if (_assetsInAlbums.find((a) => a.id === asset.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectAsset = (asset: AssetResponseDto) => {
|
||||
_selectedAssets.add(asset);
|
||||
selectedAssets.set(_selectedAssets);
|
||||
};
|
||||
@@ -128,7 +110,6 @@ export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
// Multi-selection
|
||||
_selectedAssets.clear();
|
||||
_selectedGroup.clear();
|
||||
_assetsInAlbums = [];
|
||||
|
||||
// Range selection
|
||||
_assetSelectionCandidates.clear();
|
||||
@@ -136,13 +117,12 @@ export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
|
||||
selectedAssets.set(_selectedAssets);
|
||||
selectedGroup.set(_selectedGroup);
|
||||
assetsInAlbumStoreState.set(_assetsInAlbums);
|
||||
assetSelectionCandidates.set(_assetSelectionCandidates);
|
||||
assetSelectionStart.set(_assetSelectionStart);
|
||||
};
|
||||
|
||||
return {
|
||||
addAssetToMultiselectGroup,
|
||||
selectAsset,
|
||||
removeAssetFromMultiselectGroup,
|
||||
addGroupToMultiselectGroup,
|
||||
removeGroupFromMultiselectGroup,
|
||||
@@ -153,10 +133,6 @@ export function createAssetInteractionStore(): AssetInteractionStore {
|
||||
isMultiSelectState: {
|
||||
subscribe: isMultiSelectStoreState.subscribe,
|
||||
},
|
||||
assetsInAlbumState: {
|
||||
subscribe: assetsInAlbumStoreState.subscribe,
|
||||
set: assetsInAlbumStoreState.set,
|
||||
},
|
||||
selectedAssets: {
|
||||
subscribe: selectedAssets.subscribe,
|
||||
},
|
||||
|
||||
@@ -43,14 +43,21 @@ export class AssetStore {
|
||||
timelineHeight = 0;
|
||||
buckets: AssetBucket[] = [];
|
||||
assets: AssetResponseDto[] = [];
|
||||
albumAssets: Set<string> = new Set();
|
||||
|
||||
constructor(private options: AssetStoreOptions) {
|
||||
constructor(private options: AssetStoreOptions, private albumId?: string) {
|
||||
this.store$.set(this);
|
||||
}
|
||||
|
||||
subscribe = this.store$.subscribe;
|
||||
|
||||
async init(viewport: Viewport) {
|
||||
this.timelineHeight = 0;
|
||||
this.buckets = [];
|
||||
this.assets = [];
|
||||
this.assetToBucket = {};
|
||||
this.albumAssets = new Set();
|
||||
|
||||
const { data: buckets } = await api.assetApi.getTimeBuckets(this.options);
|
||||
|
||||
this.buckets = buckets.map((bucket) => {
|
||||
@@ -104,6 +111,22 @@ export class AssetStore {
|
||||
{ signal: bucket.cancelToken.signal },
|
||||
);
|
||||
|
||||
if (this.albumId) {
|
||||
const { data: albumAssets } = await api.assetApi.getByTimeBucket(
|
||||
{
|
||||
albumId: this.albumId,
|
||||
timeBucket: bucketDate,
|
||||
size: this.options.size,
|
||||
key: this.options.key,
|
||||
},
|
||||
{ signal: bucket.cancelToken.signal },
|
||||
);
|
||||
|
||||
for (const asset of albumAssets) {
|
||||
this.albumAssets.add(asset.id);
|
||||
}
|
||||
}
|
||||
|
||||
bucket.assets = assets;
|
||||
this.emit(true);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user