perf(web): asset delete (#7555)

* perf(web): asset delete

* update asset delete on search page

* don't use arrow function in class
This commit is contained in:
Michel Heusschen 2024-03-02 01:49:31 +01:00 committed by GitHub
parent 7303fab9d9
commit a4e6c43823
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 40 additions and 51 deletions

View file

@ -72,7 +72,7 @@
const trashOrDelete = async (force: boolean = false) => {
isShowDeleteConfirmation = false;
await deleteAssets(!(isTrashEnabled && !force), (assetId) => assetStore.removeAsset(assetId), idsSelectedAssets);
await deleteAssets(!(isTrashEnabled && !force), (assetIds) => assetStore.removeAssets(assetIds), idsSelectedAssets);
assetInteractionStore.clearMultiselect();
};
@ -169,7 +169,7 @@
(await handleNext()) || (await handlePrevious()) || handleClose();
// delete after find the next one
assetStore.removeAsset(asset.id);
assetStore.removeAssets([asset.id]);
break;
}
@ -414,7 +414,7 @@
<slot name="empty" />
{/if}
<section id="virtual-timeline" style:height={$assetStore.timelineHeight + 'px'}>
{#each $assetStore.buckets as bucket, bucketIndex (bucketIndex)}
{#each $assetStore.buckets as bucket (bucket.bucketDate)}
<IntersectionObserver
on:intersected={intersectedHandler}
on:hidden={() => assetStore.cancelBucket(bucket)}

View file

@ -59,14 +59,14 @@ interface DeleteAsset {
value: string;
}
interface TrashAsset {
interface TrashAssets {
type: 'trash';
value: string;
value: string[];
}
export const photoViewer = writable<HTMLImageElement | null>(null);
type PendingChange = AddAsset | UpdateAsset | DeleteAsset | TrashAsset;
type PendingChange = AddAsset | UpdateAsset | DeleteAsset | TrashAssets;
export class AssetStore {
private store$ = writable(this);
@ -105,7 +105,7 @@ export class AssetStore {
this.addPendingChanges({ type: 'add', value: asset });
}),
websocketEvents.on('on_asset_trash', (ids) => {
this.addPendingChanges(...ids.map((id): TrashAsset => ({ type: 'trash', value: id })));
this.addPendingChanges({ type: 'trash', value: ids });
}),
websocketEvents.on('on_asset_update', (asset) => {
this.addPendingChanges({ type: 'update', value: asset });
@ -137,13 +137,13 @@ export class AssetStore {
case 'trash': {
if (!this.options.isTrashed) {
this.removeAsset(value);
this.removeAssets(value);
}
break;
}
case 'delete': {
this.removeAsset(value);
this.removeAssets([value]);
break;
}
}
@ -363,7 +363,7 @@ export class AssetStore {
const recalculate = asset.fileCreatedAt !== _asset.fileCreatedAt;
if (recalculate) {
this.removeAsset(asset.id);
this.removeAssets([asset.id]);
this.addAssetToBucket(_asset);
return;
}
@ -373,33 +373,29 @@ export class AssetStore {
}
removeAssets(ids: string[]) {
// TODO: this could probably be more efficient
for (const id of ids) {
this.removeAsset(id);
}
}
const idSet = new Set(ids);
this.assets = this.assets.filter((asset) => !idSet.has(asset.id));
removeAsset(id: string) {
this.assets = this.assets.filter((asset) => asset.id !== id);
delete this.assetToBucket[id];
for (let index = 0; index < this.buckets.length; index++) {
// Iterate in reverse to allow array splicing.
for (let index = this.buckets.length - 1; index >= 0; index--) {
const bucket = this.buckets[index];
for (let index_ = 0; index_ < bucket.assets.length; index_++) {
for (let index_ = bucket.assets.length - 1; index_ >= 0; index_--) {
const asset = bucket.assets[index_];
if (asset.id !== id) {
if (!idSet.has(asset.id)) {
continue;
}
bucket.assets.splice(index_, 1);
if (bucket.assets.length === 0) {
bucket.bucketCount = bucket.assets.length;
if (bucket.bucketCount === 0) {
this.buckets.splice(index, 1);
}
this.emit(true);
return;
delete this.assetToBucket[asset.id];
}
}
this.emit(false);
}
async getPreviousAssetId(assetId: string): Promise<string | null> {

View file

@ -2,7 +2,7 @@ import { notificationController, NotificationType } from '$lib/components/shared
import { deleteAssets as deleteBulk } from '@immich/sdk';
import { handleError } from './handle-error';
export type OnDelete = (assetId: string) => void;
export type OnDelete = (assetIds: string[]) => void;
export type OnRestore = (ids: string[]) => void;
export type OnArchive = (ids: string[], isArchived: boolean) => void;
export type OnFavorite = (ids: string[], favorite: boolean) => void;
@ -11,9 +11,7 @@ export type OnStack = (ids: string[]) => void;
export const deleteAssets = async (force: boolean, onAssetDelete: OnDelete, ids: string[]) => {
try {
await deleteBulk({ assetBulkDeleteDto: { ids, force } });
for (const id of ids) {
onAssetDelete(id);
}
onAssetDelete(ids);
notificationController.show({
message: `${force ? 'Permanently deleted' : 'Trashed'} ${ids.length} assets`,