diff --git a/web/src/lib/components/photos-page/asset-date-group.svelte b/web/src/lib/components/photos-page/asset-date-group.svelte index 2e42a2bb77..e45ebea1e7 100644 --- a/web/src/lib/components/photos-page/asset-date-group.svelte +++ b/web/src/lib/components/photos-page/asset-date-group.svelte @@ -1,6 +1,12 @@ <script lang="ts"> import Icon from '$lib/components/elements/icon.svelte'; - import { AssetBucket, assetSnapshot, assetsSnapshot } from '$lib/stores/assets-store.svelte'; + import { + type AssetStore, + type AssetBucket, + assetSnapshot, + assetsSnapshot, + isSelectingAllAssets, + } from '$lib/stores/assets-store.svelte'; import { navigate } from '$lib/utils/navigation'; import { getDateLocaleString } from '$lib/utils/timeline-util'; import type { AssetResponseDto } from '@immich/sdk'; @@ -22,6 +28,7 @@ withStacked: boolean; showArchiveIcon: boolean; bucket: AssetBucket; + assetStore: AssetStore; assetInteraction: AssetInteraction; onSelect: ({ title, assets }: { title: string; assets: AssetResponseDto[] }) => void; @@ -36,6 +43,7 @@ showArchiveIcon, bucket = $bindable(), assetInteraction, + assetStore, onSelect, onSelectAssets, onSelectAssetCandidates, @@ -46,9 +54,9 @@ const transitionDuration = $derived.by(() => (bucket.store.suspendTransitions && !$isUploading ? 0 : 150)); const scaleDuration = $derived(transitionDuration === 0 ? 0 : transitionDuration + 100); - const onClick = (assets: AssetResponseDto[], groupTitle: string, asset: AssetResponseDto) => { + const onClick = (assetStore: AssetStore, assets: AssetResponseDto[], groupTitle: string, asset: AssetResponseDto) => { if (isSelectionMode || assetInteraction.selectionActive) { - assetSelectHandler(asset, assets, groupTitle); + assetSelectHandler(assetStore, asset, assets, groupTitle); return; } void navigate({ targetRoute: 'current', assetId: asset.id }); @@ -56,7 +64,12 @@ const handleSelectGroup = (title: string, assets: AssetResponseDto[]) => onSelect({ title, assets }); - const assetSelectHandler = (asset: AssetResponseDto, assetsInDateGroup: AssetResponseDto[], groupTitle: string) => { + const assetSelectHandler = ( + assetStore: AssetStore, + asset: AssetResponseDto, + assetsInDateGroup: AssetResponseDto[], + groupTitle: string, + ) => { onSelectAssets(asset); // Check if all assets are selected in a group to toggle the group selection's icon @@ -70,6 +83,12 @@ } else { assetInteraction.removeGroupFromMultiselectGroup(groupTitle); } + + if (assetStore.getAssets().length == assetInteraction.selectedAssets.length) { + isSelectingAllAssets.set(true); + } else { + isSelectingAllAssets.set(false); + } }; const assetMouseEventHandler = (groupTitle: string, asset: AssetResponseDto | null) => { @@ -164,8 +183,8 @@ {asset} {groupIndex} focussed={assetInteraction.isFocussedAsset(asset.id)} - onClick={(asset) => onClick(dateGroup.getAssets(), dateGroup.groupTitle, asset)} - onSelect={(asset) => assetSelectHandler(asset, dateGroup.getAssets(), dateGroup.groupTitle)} + onClick={(asset) => onClick(assetStore, dateGroup.getAssets(), dateGroup.groupTitle, asset)} + onSelect={(asset) => assetSelectHandler(assetStore, asset, dateGroup.getAssets(), dateGroup.groupTitle)} onMouseEvent={() => assetMouseEventHandler(dateGroup.groupTitle, assetSnapshot(asset))} selected={assetInteraction.hasSelectedAsset(asset.id) || dateGroup.bucket.store.albumAssets.has(asset.id)} selectionCandidate={assetInteraction.hasSelectionCandidate(asset.id)} diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index e458e36f38..d3afdc6072 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -4,7 +4,7 @@ import type { Action } from '$lib/components/asset-viewer/actions/action'; import { AppRoute, AssetAction } from '$lib/constants'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; - import { AssetBucket, assetsSnapshot, AssetStore } from '$lib/stores/assets-store.svelte'; + import { AssetBucket, assetsSnapshot, AssetStore, isSelectingAllAssets } from '$lib/stores/assets-store.svelte'; import { showDeleteModal } from '$lib/stores/preferences.store'; import { isSearchEnabled } from '$lib/stores/search.store'; import { featureFlags } from '$lib/stores/server-config.store'; @@ -456,7 +456,7 @@ lastAssetMouseEvent = asset; }; - const handleGroupSelect = (group: string, assets: AssetResponseDto[]) => { + const handleGroupSelect = (assetStore: AssetStore, group: string, assets: AssetResponseDto[]) => { if (assetInteraction.selectedGroup.has(group)) { assetInteraction.removeGroupFromMultiselectGroup(group); for (const asset of assets) { @@ -468,6 +468,12 @@ handleSelectAsset(asset); } } + + if (assetStore.getAssets().length == assetInteraction.selectedAssets.length) { + isSelectingAllAssets.set(true); + } else { + isSelectingAllAssets.set(false); + } }; const handleSelectAssets = async (asset: AssetResponseDto) => { @@ -774,10 +780,11 @@ {withStacked} {showArchiveIcon} {assetInteraction} + {assetStore} {isSelectionMode} {singleSelect} {bucket} - onSelect={({ title, assets }) => handleGroupSelect(title, assets)} + onSelect={({ title, assets }) => handleGroupSelect(assetStore, title, assets)} onSelectAssetCandidates={handleSelectAssetCandidates} onSelectAssets={handleSelectAssets} /> diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts index 242515b02a..1dcd2c95b1 100644 --- a/web/src/lib/utils/asset-utils.ts +++ b/web/src/lib/utils/asset-utils.ts @@ -486,6 +486,10 @@ export const selectAllAssets = async (assetStore: AssetStore, assetInteraction: break; // Cancelled } assetInteraction.selectAssets(assetsSnapshot(bucket.getAssets())); + + for (const dateGroup of bucket.dateGroups) { + assetInteraction.addGroupToMultiselectGroup(dateGroup.groupTitle); + } } } catch (error) { const $t = get(t);