Make sidenav album list update properly when adding and deleting albums

This commit is contained in:
Stewart Rand 2025-09-12 11:56:11 -03:00
parent ec91762169
commit 1e634e98a3
8 changed files with 38 additions and 8 deletions

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { updateAlbumInfo } from '@immich/sdk'; import { updateAlbumInfo } from '@immich/sdk';
import { userInteraction } from '$lib/stores/user.svelte';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import AutogrowTextarea from '$lib/components/shared-components/autogrow-textarea.svelte'; import AutogrowTextarea from '$lib/components/shared-components/autogrow-textarea.svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
@ -20,6 +21,8 @@
description: newDescription, description: newDescription,
}, },
}); });
// Clear cached recent albums to refresh sidebar when album is updated
userInteraction.recentAlbums = undefined;
} catch (error) { } catch (error) {
handleError(error, $t('errors.unable_to_save_album')); handleError(error, $t('errors.unable_to_save_album'));
} }

View file

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { shortcut } from '$lib/actions/shortcut'; import { shortcut } from '$lib/actions/shortcut';
import { userInteraction } from '$lib/stores/user.svelte';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { updateAlbumInfo } from '@immich/sdk'; import { updateAlbumInfo } from '@immich/sdk';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
@ -27,6 +28,8 @@
albumName: newAlbumName, albumName: newAlbumName,
}, },
})); }));
// Clear cached recent albums to refresh sidebar when album name is updated
userInteraction.recentAlbums = undefined;
onUpdate(albumName); onUpdate(albumName);
} catch (error) { } catch (error) {
handleError(error, $t('errors.unable_to_save_album')); handleError(error, $t('errors.unable_to_save_album'));

View file

@ -246,6 +246,8 @@
} }
} }
// Clear cached recent albums to refresh sidebar when album is deleted
userInteraction.recentAlbums = undefined;
ownedAlbums = ownedAlbums.filter(({ id }) => id !== albumToDelete.id); ownedAlbums = ownedAlbums.filter(({ id }) => id !== albumToDelete.id);
sharedAlbums = sharedAlbums.filter(({ id }) => id !== albumToDelete.id); sharedAlbums = sharedAlbums.filter(({ id }) => id !== albumToDelete.id);
}; };

View file

@ -4,6 +4,7 @@
notificationController, notificationController,
NotificationType, NotificationType,
} from '$lib/components/shared-components/notification/notification'; } from '$lib/components/shared-components/notification/notification';
import { userInteraction } from '$lib/stores/user.svelte';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { updateAlbumInfo, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk'; import { updateAlbumInfo, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk';
import { mdiImageOutline } from '@mdi/js'; import { mdiImageOutline } from '@mdi/js';
@ -24,6 +25,8 @@
albumThumbnailAssetId: asset.id, albumThumbnailAssetId: asset.id,
}, },
}); });
// Clear cached recent albums to refresh sidebar when album cover is updated
userInteraction.recentAlbums = undefined;
notificationController.show({ notificationController.show({
type: NotificationType.Info, type: NotificationType.Info,
message: $t('album_cover_updated'), message: $t('album_cover_updated'),

View file

@ -3,23 +3,31 @@
import { getAssetThumbnailUrl } from '$lib/utils'; import { getAssetThumbnailUrl } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { getAllAlbums, type AlbumResponseDto } from '@immich/sdk'; import { getAllAlbums, type AlbumResponseDto } from '@immich/sdk';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
let albums: AlbumResponseDto[] = $state([]); let albums: AlbumResponseDto[] = $state([]);
onMount(async () => { const loadRecentAlbums = async () => {
if (userInteraction.recentAlbums) {
albums = userInteraction.recentAlbums;
return;
}
try { try {
const allAlbums = await getAllAlbums({}); const allAlbums = await getAllAlbums({});
albums = allAlbums.sort((a, b) => (a.updatedAt > b.updatedAt ? -1 : 1)).slice(0, 3); // Filter out albums with empty names (newly created albums that haven't been named yet)
userInteraction.recentAlbums = albums; const namedAlbums = allAlbums.filter(album => album.albumName.trim() !== '');
const recentAlbums = namedAlbums.sort((a, b) => (a.updatedAt > b.updatedAt ? -1 : 1)).slice(0, 3);
albums = recentAlbums;
userInteraction.recentAlbums = recentAlbums;
} catch (error) { } catch (error) {
handleError(error, $t('failed_to_load_assets')); handleError(error, $t('failed_to_load_assets'));
} }
};
$effect(() => {
if (userInteraction.recentAlbums) {
// Apply the same filtering to cached albums to ensure consistency
const filteredCachedAlbums = userInteraction.recentAlbums.filter(album => album.albumName.trim() !== '');
albums = filteredCachedAlbums;
} else {
void loadRecentAlbums();
}
}); });
</script> </script>

View file

@ -6,6 +6,7 @@
isSelectableRowType, isSelectableRowType,
} from '$lib/components/shared-components/album-selection/album-selection-utils'; } from '$lib/components/shared-components/album-selection/album-selection-utils';
import { albumViewSettings } from '$lib/stores/preferences.store'; import { albumViewSettings } from '$lib/stores/preferences.store';
import { userInteraction } from '$lib/stores/user.svelte';
import { createAlbum, getAllAlbums, type AlbumResponseDto } from '@immich/sdk'; import { createAlbum, getAllAlbums, type AlbumResponseDto } from '@immich/sdk';
import { Button, Icon, Modal, ModalBody, ModalFooter, Text } from '@immich/ui'; import { Button, Icon, Modal, ModalBody, ModalFooter, Text } from '@immich/ui';
import { mdiKeyboardReturn } from '@mdi/js'; import { mdiKeyboardReturn } from '@mdi/js';
@ -44,6 +45,8 @@
const onNewAlbum = async (name: string) => { const onNewAlbum = async (name: string) => {
const album = await createAlbum({ createAlbumDto: { albumName: name } }); const album = await createAlbum({ createAlbumDto: { albumName: name } });
// Clear cached recent albums to force refresh in sidebar
userInteraction.recentAlbums = undefined;
onClose([album]); onClose([album]);
}; };

View file

@ -9,6 +9,7 @@ import {
locale, locale,
type AlbumViewSettings, type AlbumViewSettings,
} from '$lib/stores/preferences.store'; } from '$lib/stores/preferences.store';
import { userInteraction } from '$lib/stores/user.svelte';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import type { AlbumResponseDto } from '@immich/sdk'; import type { AlbumResponseDto } from '@immich/sdk';
import * as sdk from '@immich/sdk'; import * as sdk from '@immich/sdk';
@ -30,6 +31,8 @@ export const createAlbum = async (name?: string, assetIds?: string[]) => {
assetIds, assetIds,
}, },
}); });
// Clear cached recent albums to force refresh in sidebar
userInteraction.recentAlbums = undefined;
return newAlbum; return newAlbum;
} catch (error) { } catch (error) {
const $t = get(t); const $t = get(t);

View file

@ -46,6 +46,7 @@
import { featureFlags } from '$lib/stores/server-config.store'; import { featureFlags } from '$lib/stores/server-config.store';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { preferences, user } from '$lib/stores/user.store'; import { preferences, user } from '$lib/stores/user.store';
import { userInteraction } from '$lib/stores/user.svelte';
import { handlePromiseError, makeSharedLinkUrl } from '$lib/utils'; import { handlePromiseError, makeSharedLinkUrl } from '$lib/utils';
import { confirmAlbumDelete } from '$lib/utils/album-utils'; import { confirmAlbumDelete } from '$lib/utils/album-utils';
import { cancelMultiselect, downloadAlbum } from '$lib/utils/asset-utils'; import { cancelMultiselect, downloadAlbum } from '$lib/utils/asset-utils';
@ -254,6 +255,8 @@
try { try {
await deleteAlbum({ id: album.id }); await deleteAlbum({ id: album.id });
// Clear cached recent albums to refresh sidebar when album is deleted
userInteraction.recentAlbums = undefined;
await goto(backUrl); await goto(backUrl);
} catch (error) { } catch (error) {
handleError(error, $t('errors.unable_to_delete_album')); handleError(error, $t('errors.unable_to_delete_album'));
@ -316,6 +319,8 @@
onNavigate(async ({ to }) => { onNavigate(async ({ to }) => {
if (!isAlbumsRoute(to?.route.id) && album.assetCount === 0 && !album.albumName) { if (!isAlbumsRoute(to?.route.id) && album.assetCount === 0 && !album.albumName) {
await deleteAlbum(album); await deleteAlbum(album);
// Clear cached recent albums to refresh sidebar when album is auto-deleted
userInteraction.recentAlbums = undefined;
} }
}); });