mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	feat(web): add delete button to asset viewer (#896)
This commit is contained in:
		
							parent
							
								
									6e638cd673
								
							
						
					
					
						commit
						1967c1e237
					
				@ -4,6 +4,7 @@
 | 
				
			|||||||
	import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
 | 
						import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
 | 
				
			||||||
	import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
 | 
						import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
 | 
				
			||||||
	import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
 | 
						import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
 | 
				
			||||||
 | 
						import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
 | 
				
			||||||
	import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
						import CircleIconButton from '../shared-components/circle-icon-button.svelte';
 | 
				
			||||||
	const dispatch = createEventDispatcher();
 | 
						const dispatch = createEventDispatcher();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
@ -17,5 +18,6 @@
 | 
				
			|||||||
	<div class="text-white flex gap-2">
 | 
						<div class="text-white flex gap-2">
 | 
				
			||||||
		<CircleIconButton logo={CloudDownloadOutline} on:click={() => dispatch('download')} />
 | 
							<CircleIconButton logo={CloudDownloadOutline} on:click={() => dispatch('download')} />
 | 
				
			||||||
		<CircleIconButton logo={InformationOutline} on:click={() => dispatch('showDetail')} />
 | 
							<CircleIconButton logo={InformationOutline} on:click={() => dispatch('showDetail')} />
 | 
				
			||||||
 | 
							<CircleIconButton logo={DeleteOutline} on:click={() => dispatch('delete')} />
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { createEventDispatcher, onMount, onDestroy } from 'svelte';
 | 
						import { createEventDispatcher, onMount, onDestroy } from 'svelte';
 | 
				
			||||||
	import { fly } from 'svelte/transition';
 | 
						import { fly } from 'svelte/transition';
 | 
				
			||||||
	import AsserViewerNavBar from './asser-viewer-nav-bar.svelte';
 | 
						import AsserViewerNavBar from './asset-viewer-nav-bar.svelte';
 | 
				
			||||||
	import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
 | 
						import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
 | 
				
			||||||
	import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
 | 
						import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
 | 
				
			||||||
	import PhotoViewer from './photo-viewer.svelte';
 | 
						import PhotoViewer from './photo-viewer.svelte';
 | 
				
			||||||
@ -13,6 +13,7 @@
 | 
				
			|||||||
		notificationController,
 | 
							notificationController,
 | 
				
			||||||
		NotificationType
 | 
							NotificationType
 | 
				
			||||||
	} from '../shared-components/notification/notification';
 | 
						} from '../shared-components/notification/notification';
 | 
				
			||||||
 | 
						import { assetStore } from '$lib/stores/assets.store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export let asset: AssetResponseDto;
 | 
						export let asset: AssetResponseDto;
 | 
				
			||||||
	$: {
 | 
						$: {
 | 
				
			||||||
@ -44,6 +45,9 @@
 | 
				
			|||||||
			case 'Escape':
 | 
								case 'Escape':
 | 
				
			||||||
				closeViewer();
 | 
									closeViewer();
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
 | 
								case 'Delete':
 | 
				
			||||||
 | 
									deleteAsset();
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
			case 'i':
 | 
								case 'i':
 | 
				
			||||||
				isShowDetail = !isShowDetail;
 | 
									isShowDetail = !isShowDetail;
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
@ -135,6 +139,34 @@
 | 
				
			|||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const deleteAsset = async () => {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								if (
 | 
				
			||||||
 | 
									window.confirm(
 | 
				
			||||||
 | 
										`Caution! Are you sure you want to delete this asset? This step also deletes this asset in the album(s) to which it belongs. You can not undo this action!`
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
								) {
 | 
				
			||||||
 | 
									const { data: deletedAssets } = await api.assetApi.deleteAsset({
 | 
				
			||||||
 | 
										ids: [asset.id]
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									navigateAssetForward();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									for (const asset of deletedAssets) {
 | 
				
			||||||
 | 
										if (asset.status == 'SUCCESS') {
 | 
				
			||||||
 | 
											assetStore.removeAsset(asset.id);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} catch (e) {
 | 
				
			||||||
 | 
								notificationController.show({
 | 
				
			||||||
 | 
									type: NotificationType.Error,
 | 
				
			||||||
 | 
									message: 'Error deleting this asset, check console for more details'
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								console.error('Error deleteSelectedAssetHandler', e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<section
 | 
					<section
 | 
				
			||||||
@ -146,6 +178,7 @@
 | 
				
			|||||||
			on:goBack={closeViewer}
 | 
								on:goBack={closeViewer}
 | 
				
			||||||
			on:showDetail={showDetailInfoHandler}
 | 
								on:showDetail={showDetailInfoHandler}
 | 
				
			||||||
			on:download={downloadFile}
 | 
								on:download={downloadFile}
 | 
				
			||||||
 | 
								on:delete={deleteAsset}
 | 
				
			||||||
		/>
 | 
							/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ function createAssetInteractionStore() {
 | 
				
			|||||||
	let _viewingAssetStoreState: AssetResponseDto;
 | 
						let _viewingAssetStoreState: AssetResponseDto;
 | 
				
			||||||
	let _selectedAssets: Set<AssetResponseDto>;
 | 
						let _selectedAssets: Set<AssetResponseDto>;
 | 
				
			||||||
	let _selectedGroup: Set<string>;
 | 
						let _selectedGroup: Set<string>;
 | 
				
			||||||
	let _assetsInAblums: AssetResponseDto[];
 | 
						let _assetsInAlbums: AssetResponseDto[];
 | 
				
			||||||
	let savedAssetLength = 0;
 | 
						let savedAssetLength = 0;
 | 
				
			||||||
	let assetSortedByDate: AssetResponseDto[] = [];
 | 
						let assetSortedByDate: AssetResponseDto[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,7 +44,7 @@ function createAssetInteractionStore() {
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	assetsInAlbumStoreState.subscribe((assets) => {
 | 
						assetsInAlbumStoreState.subscribe((assets) => {
 | 
				
			||||||
		_assetsInAblums = assets;
 | 
							_assetsInAlbums = assets;
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Methods
 | 
						// Methods
 | 
				
			||||||
@ -95,15 +95,17 @@ function createAssetInteractionStore() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const nextAsset = assetSortedByDate[nextIndex];
 | 
							const nextAsset = assetSortedByDate[nextIndex];
 | 
				
			||||||
 | 
							if (nextAsset) {
 | 
				
			||||||
			setViewingAsset(nextAsset);
 | 
								setViewingAsset(nextAsset);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Multiselect
 | 
						 * Multiselect
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	const addAssetToMultiselectGroup = (asset: AssetResponseDto) => {
 | 
						const addAssetToMultiselectGroup = (asset: AssetResponseDto) => {
 | 
				
			||||||
		// Not select if in album alreaady
 | 
							// Not select if in album already
 | 
				
			||||||
		if (_assetsInAblums.find((a) => a.id === asset.id)) {
 | 
							if (_assetsInAlbums.find((a) => a.id === asset.id)) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -129,12 +131,13 @@ function createAssetInteractionStore() {
 | 
				
			|||||||
	const clearMultiselect = () => {
 | 
						const clearMultiselect = () => {
 | 
				
			||||||
		_selectedAssets.clear();
 | 
							_selectedAssets.clear();
 | 
				
			||||||
		_selectedGroup.clear();
 | 
							_selectedGroup.clear();
 | 
				
			||||||
		_assetsInAblums = [];
 | 
							_assetsInAlbums = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		selectedAssets.set(_selectedAssets);
 | 
							selectedAssets.set(_selectedAssets);
 | 
				
			||||||
		selectedGroup.set(_selectedGroup);
 | 
							selectedGroup.set(_selectedGroup);
 | 
				
			||||||
		assetsInAlbumStoreState.set(_assetsInAblums);
 | 
							assetsInAlbumStoreState.set(_assetsInAlbums);
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return {
 | 
						return {
 | 
				
			||||||
		setViewingAsset,
 | 
							setViewingAsset,
 | 
				
			||||||
		setIsViewingAsset,
 | 
							setIsViewingAsset,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user