diff --git a/web/src/lib/services/album.service.ts b/web/src/lib/services/album.service.ts
index 862456cae..c021b0277 100644
--- a/web/src/lib/services/album.service.ts
+++ b/web/src/lib/services/album.service.ts
@@ -27,6 +27,7 @@ import {
mdiTrashCanOutline,
mdiExitToApp,
mdiUpload,
+ mdiCogOutline,
} from '@mdi/js';
import { type MessageFormatter } from 'svelte-i18n';
import { goto } from '$app/navigation';
@@ -73,7 +74,7 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
};
const Delete: ActionItem = {
- title: $t('delete'),
+ title: $t('delete_album'),
icon: mdiTrashCanOutline,
$if: () => isOwned,
onAction: () => handleDeleteAlbum(album),
@@ -82,16 +83,10 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
const Download: ActionItem = {
title: $t('download'),
icon: mdiDownload,
+ $if: () => album.assetCount > 0,
onAction: () => handleDownloadAlbum(album),
};
- const Leave: ActionItem = {
- title: $t('leave_album'),
- icon: mdiExitToApp,
- $if: () => !isOwned,
- onAction: () => handleLeaveAlbum(album),
- };
-
const Edit: ActionItem = {
title: $t('edit_album'),
icon: mdiRenameOutline,
@@ -99,6 +94,20 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
onAction: () => modalManager.show(AlbumEditModal, { album }),
};
+ const Leave: ActionItem = {
+ title: $t('leave_album'),
+ icon: mdiExitToApp,
+ $if: () => !isOwned,
+ onAction: () => handleLeaveAlbum(album),
+ };
+
+ const Options: ActionItem = {
+ title: $t('options'),
+ icon: mdiCogOutline,
+ $if: () => album.assetCount > 0,
+ onAction: () => modalManager.show(AlbumOptionsModal, { album, readOnly: !isOwned }),
+ };
+
const Share: ActionItem = {
title: $t('share'),
icon: mdiShareVariantOutline,
@@ -106,7 +115,7 @@ export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) =
onAction: () => modalManager.show(AlbumOptionsModal, { album }),
};
- return { AddUsers, CreateSharedLink, Delete, Download, Edit, Leave, Share };
+ return { AddUsers, CreateSharedLink, Delete, Download, Edit, Leave, Options, Share };
};
export const getAlbumAssetActions = ($t: MessageFormatter, album: AlbumResponseDto, asset: AssetResponseDto) => {
diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
index 778165244..fce64dbdb 100644
--- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -34,14 +34,8 @@
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
- import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte';
import { Route } from '$lib/route';
- import {
- getAlbumActions,
- getAlbumAssetsActions,
- handleDeleteAlbum,
- handleDownloadAlbum,
- } from '$lib/services/album.service';
+ import { getAlbumActions, getAlbumAssetsActions, handleDeleteAlbum } from '$lib/services/album.service';
import { getGlobalActions } from '$lib/services/app.service';
import { getAssetBulkActions } from '$lib/services/asset.service';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
@@ -49,23 +43,13 @@
import { handleError } from '$lib/utils/handle-error';
import { isAlbumsRoute, navigate, type AssetGridRouteSearchParams } from '$lib/utils/navigation';
import { AlbumUserRole, AssetVisibility, getAlbumInfo, updateAlbumInfo, type AlbumResponseDto } from '@immich/sdk';
- import {
- ActionButton,
- CommandPaletteDefaultProvider,
- Icon,
- IconButton,
- modalManager,
- toastManager,
- } from '@immich/ui';
+ import { ActionButton, CommandPaletteDefaultProvider, Icon, IconButton, toastManager } from '@immich/ui';
import {
mdiAccountEye,
mdiAccountEyeOutline,
mdiArrowLeft,
- mdiCogOutline,
- mdiDeleteOutline,
mdiDotsHorizontal,
mdiDotsVertical,
- mdiDownload,
mdiImageOutline,
mdiImagePlusOutline,
mdiLink,
@@ -218,6 +202,7 @@
let album = $state(data.album);
let albumId = $derived(album.id);
+ const albumHasViewers = $derived(album.albumUsers.some(({ role }) => role === AlbumUserRole.Viewer));
const containsEditors = $derived(album?.shared && album.albumUsers.some(({ role }) => role === AlbumUserRole.Editor));
const albumUsers = $derived(showAlbumUsers && containsEditors ? album.albumUsers.map(({ user }) => user) : []);
@@ -261,7 +246,6 @@
album.albumUsers.find(({ user: { id } }) => id === authManager.user.id)?.role === AlbumUserRole.Editor || isOwned,
);
- let albumHasViewers = $derived(album.albumUsers.some(({ role }) => role === AlbumUserRole.Viewer));
const isSelectionMode = $derived(
viewMode === AlbumPageViewMode.SELECT_ASSETS ? true : viewMode === AlbumPageViewMode.SELECT_THUMBNAIL,
);
@@ -278,10 +262,6 @@
viewMode === AlbumPageViewMode.SELECT_ASSETS ? timelineMultiSelectManager : assetMultiSelectManager,
);
- const onSharedLinkCreate = async () => {
- await refreshAlbum();
- };
-
const onAlbumDelete = async ({ id }: AlbumResponseDto) => {
if (id !== album.id) {
return;
@@ -328,7 +308,7 @@
};
const { Cast } = $derived(getGlobalActions($t));
- const { Share, Leave } = $derived(getAlbumActions($t, album));
+ const Actions = $derived(getAlbumActions($t, album));
const { AddAssets, Upload } = $derived(getAlbumAssetsActions($t, album, timelineMultiSelectManager.assets));
const Close = $derived({
@@ -341,7 +321,7 @@