diff --git a/web/src/lib/components/asset-viewer/actions/add-to-album-action.svelte b/web/src/lib/components/asset-viewer/actions/add-to-album-action.svelte index 2c6ac54ef7..cf8ba15024 100644 --- a/web/src/lib/components/asset-viewer/actions/add-to-album-action.svelte +++ b/web/src/lib/components/asset-viewer/actions/add-to-album-action.svelte @@ -8,19 +8,18 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import type { AssetResponseDto } from '@immich/sdk'; import { modalManager } from '@immich/ui'; - import { mdiImageAlbum, mdiShareVariantOutline } from '@mdi/js'; + import { mdiImageAlbum } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { asset: AssetResponseDto; onAction: OnAction; - shared?: boolean; } - let { asset, onAction, shared = false }: Props = $props(); + let { asset, onAction }: Props = $props(); const onClick = async () => { - const albums = await modalManager.show(AlbumPickerModal, { shared }); + const albums = await modalManager.show(AlbumPickerModal, {}); if (!albums || albums.length === 0) { return; @@ -40,10 +39,6 @@ }; - + - + diff --git a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte index 6754ad70cf..93ce2f01e3 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte @@ -186,7 +186,6 @@ {:else} - {/if} {/if} diff --git a/web/src/lib/components/memory-page/memory-viewer.svelte b/web/src/lib/components/memory-page/memory-viewer.svelte index efa425dd30..20d43f1974 100644 --- a/web/src/lib/components/memory-page/memory-viewer.svelte +++ b/web/src/lib/components/memory-page/memory-viewer.svelte @@ -48,7 +48,6 @@ mdiImageSearch, mdiPause, mdiPlay, - mdiPlus, mdiSelectAll, mdiVolumeHigh, mdiVolumeOff, @@ -339,10 +338,7 @@ onclick={handleSelectAll} /> - - - - + diff --git a/web/src/lib/components/shared-components/album-selection/album-selection-utils.spec.ts b/web/src/lib/components/shared-components/album-selection/album-selection-utils.spec.ts index a078e55762..9257c4585a 100644 --- a/web/src/lib/components/shared-components/album-selection/album-selection-utils.spec.ts +++ b/web/src/lib/components/shared-components/album-selection/album-selection-utils.spec.ts @@ -28,15 +28,15 @@ const createAlbumRow = (album: AlbumResponseDto, selected: boolean) => ({ }); describe('Album Modal', () => { - it('non-shared with no albums configured yet shows message and new', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + it('no albums configured yet shows message and new', () => { + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const modalRows = converter.toModalRows('', [], [], -1, []); expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_yet')]); }); - it('non-shared with no matching albums shows message and new', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + it('no matching albums shows message and new', () => { + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const modalRows = converter.toModalRows( 'matches_nothing', [], @@ -48,8 +48,8 @@ describe('Album Modal', () => { expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_with_name_yet')]); }); - it('non-shared displays single albums', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + it('displays single albums', () => { + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const modalRows = converter.toModalRows('', [], [holidayAlbum], -1, []); @@ -60,8 +60,8 @@ describe('Album Modal', () => { ]); }); - it('non-shared displays multiple albums and recents', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + it('displays multiple albums and recents', () => { + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' }); @@ -87,31 +87,8 @@ describe('Album Modal', () => { ]); }); - it('shared only displays albums and no recents', () => { - const converter = new AlbumModalRowConverter(true, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); - const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); - const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); - const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' }); - const christmasAlbum = albumFactory.build({ albumName: 'Christmas' }); - const modalRows = converter.toModalRows( - '', - [holidayAlbum, constructionAlbum], - [holidayAlbum, constructionAlbum, birthdayAlbum, christmasAlbum], - -1, - [], - ); - - expect(modalRows).toStrictEqual([ - createNewAlbumRow(false), - createAlbumRow(holidayAlbum, false), - createAlbumRow(constructionAlbum, false), - createAlbumRow(birthdayAlbum, false), - createAlbumRow(christmasAlbum, false), - ]); - }); - it('search changes messaging and removes recent and non-matching albums', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' }); @@ -132,7 +109,7 @@ describe('Album Modal', () => { }); it('selection can select new album row', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 0, []); @@ -148,7 +125,7 @@ describe('Album Modal', () => { }); it('selection can select recent row', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 1, []); @@ -164,7 +141,7 @@ describe('Album Modal', () => { }); it('selection can select last row', () => { - const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc); + const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc); const holidayAlbum = albumFactory.build({ albumName: 'Holidays' }); const constructionAlbum = albumFactory.build({ albumName: 'Construction' }); const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 3, []); diff --git a/web/src/lib/components/shared-components/album-selection/album-selection-utils.ts b/web/src/lib/components/shared-components/album-selection/album-selection-utils.ts index e65d42b183..56246ac6c4 100644 --- a/web/src/lib/components/shared-components/album-selection/album-selection-utils.ts +++ b/web/src/lib/components/shared-components/album-selection/album-selection-utils.ts @@ -27,12 +27,10 @@ export const isSelectableRowType = (type: AlbumModalRowType) => const $t = get(t); export class AlbumModalRowConverter { - private readonly shared: boolean; private readonly sortBy: string; private readonly orderBy: string; - constructor(shared: boolean, sortBy: string, orderBy: string) { - this.shared = shared; + constructor(sortBy: string, orderBy: string) { this.sortBy = sortBy; this.orderBy = orderBy; } @@ -44,8 +42,8 @@ export class AlbumModalRowConverter { selectedRowIndex: number, multiSelectedAlbumIds: string[], ): AlbumModalRow[] { - // only show recent albums if no search was entered, or we're in the normal albums (non-shared) modal. - const recentAlbumsToShow = !this.shared && search.length === 0 ? recentAlbums : []; + // only show recent albums if no search was entered + const recentAlbumsToShow = search.length === 0 ? recentAlbums : []; const rows: AlbumModalRow[] = [{ type: AlbumModalRowType.NEW_ALBUM, selected: selectedRowIndex === 0 }]; const filteredAlbums = sortAlbums( @@ -71,12 +69,10 @@ export class AlbumModalRowConverter { } } - if (!this.shared) { - rows.push({ - type: AlbumModalRowType.SECTION, - text: (search.length === 0 ? $t('all_albums') : $t('albums')).toUpperCase(), - }); - } + rows.push({ + type: AlbumModalRowType.SECTION, + text: (search.length === 0 ? $t('all_albums') : $t('albums')).toUpperCase(), + }); const selectedOffsetDueToNewAndRecents = 1 + recentAlbumsToShow.length; for (const [i, album] of filteredAlbums.entries()) { diff --git a/web/src/lib/components/timeline/actions/AddToAlbumAction.svelte b/web/src/lib/components/timeline/actions/AddToAlbumAction.svelte index 97b75b070d..6dce0ce084 100644 --- a/web/src/lib/components/timeline/actions/AddToAlbumAction.svelte +++ b/web/src/lib/components/timeline/actions/AddToAlbumAction.svelte @@ -4,21 +4,21 @@ import type { OnAddToAlbum } from '$lib/utils/actions'; import { addAssetsToAlbum, addAssetsToAlbums } from '$lib/utils/asset-utils'; import { getAssetControlContext } from '$lib/utils/context'; - import { modalManager } from '@immich/ui'; - import { mdiImageAlbum, mdiShareVariantOutline } from '@mdi/js'; + import { IconButton, modalManager } from '@immich/ui'; + import { mdiImageAlbum, mdiPlus } from '@mdi/js'; import { t } from 'svelte-i18n'; interface Props { - shared?: boolean; onAddToAlbum?: OnAddToAlbum; + menuItem?: boolean; } - let { shared = false, onAddToAlbum = () => {} }: Props = $props(); + let { onAddToAlbum = () => {}, menuItem = false }: Props = $props(); const { getAssets } = getAssetControlContext(); const onClick = async () => { - const albums = await modalManager.show(AlbumPickerModal, { shared }); + const albums = await modalManager.show(AlbumPickerModal, {}); if (!albums || albums.length === 0) { return; } @@ -38,9 +38,17 @@ }; - +{#if menuItem} + +{/if} + +{#if !menuItem} + +{/if} diff --git a/web/src/lib/components/workflows/WorkflowPickerField.svelte b/web/src/lib/components/workflows/WorkflowPickerField.svelte index 6ad4fdbeb2..0ba85904a2 100644 --- a/web/src/lib/components/workflows/WorkflowPickerField.svelte +++ b/web/src/lib/components/workflows/WorkflowPickerField.svelte @@ -42,7 +42,7 @@ const handlePicker = async () => { if (isAlbum) { - const albums = await modalManager.show(AlbumPickerModal, { shared: false }); + const albums = await modalManager.show(AlbumPickerModal); if (albums && albums.length > 0) { const newValue = multiple ? albums.map((album) => album.id) : albums[0].id; onchange(newValue); diff --git a/web/src/lib/modals/AlbumPickerModal.svelte b/web/src/lib/modals/AlbumPickerModal.svelte index 72f80043f5..b2420215bc 100644 --- a/web/src/lib/modals/AlbumPickerModal.svelte +++ b/web/src/lib/modals/AlbumPickerModal.svelte @@ -21,14 +21,13 @@ let selectedRowIndex: number = $state(-1); interface Props { - shared: boolean; onClose: (albums?: AlbumResponseDto[]) => void; } - let { shared, onClose }: Props = $props(); + let { onClose }: Props = $props(); onMount(async () => { - albums = await getAllAlbums({ shared: shared || undefined }); + albums = await getAllAlbums({}); recentAlbums = albums.sort((a, b) => (new Date(a.updatedAt) > new Date(b.updatedAt) ? -1 : 1)).slice(0, 3); loading = false; }); @@ -36,7 +35,7 @@ const multiSelectedAlbumIds: string[] = $state([]); const multiSelectActive = $derived(multiSelectedAlbumIds.length > 0); - const rowConverter = new AlbumModalRowConverter(shared, $albumViewSettings.sortBy, $albumViewSettings.sortOrder); + const rowConverter = new AlbumModalRowConverter($albumViewSettings.sortBy, $albumViewSettings.sortOrder); const albumModalRows = $derived( rowConverter.toModalRows(search, recentAlbums, albums, selectedRowIndex, multiSelectedAlbumIds), ); @@ -146,7 +145,7 @@ }; - +
{#if loading} diff --git a/web/src/lib/modals/ShortcutsModal.svelte b/web/src/lib/modals/ShortcutsModal.svelte index c5b09ffa1a..c233548878 100644 --- a/web/src/lib/modals/ShortcutsModal.svelte +++ b/web/src/lib/modals/ShortcutsModal.svelte @@ -40,7 +40,6 @@ { key: ['s'], action: $t('stack_selected_photos') }, { key: ['l'], action: $t('add_to_album') }, { key: ['t'], action: $t('tag_assets') }, - { key: ['⇧', 'l'], action: $t('add_to_shared_album') }, { key: ['⇧', 'a'], action: $t('archive_or_unarchive_photo') }, { key: ['⇧', 'd'], action: $t('download') }, { key: ['Space'], action: $t('play_or_pause_video') }, 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 88baa416b8..38817650c1 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 @@ -440,10 +440,7 @@ > - - - - + {#if assetInteraction.isAllUserOwned} - - - - + timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))} diff --git a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte index d33c5e7474..74993cb64b 100644 --- a/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/favorites/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -19,7 +19,7 @@ import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { preferences } from '$lib/stores/user.store'; - import { mdiDotsVertical, mdiPlus } from '@mdi/js'; + import { mdiDotsVertical } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { PageData } from './$types'; @@ -71,10 +71,7 @@ timelineManager.removeAssets(assetIds)} /> - - - - + diff --git a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte index 9bca4a9094..c9ac99d10f 100644 --- a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -31,7 +31,7 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { joinPaths } from '$lib/utils/tree-utils'; import { IconButton, Text } from '@immich/ui'; - import { mdiDotsVertical, mdiFolder, mdiFolderHome, mdiFolderOutline, mdiPlus, mdiSelectAll } from '@mdi/js'; + import { mdiDotsVertical, mdiFolder, mdiFolderHome, mdiFolderOutline, mdiSelectAll } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { PageData } from './$types'; @@ -130,10 +130,7 @@ icon={mdiSelectAll} onclick={handleSelectAllAssets} /> - - cancelMultiselect(assetInteraction)} /> - cancelMultiselect(assetInteraction)} shared /> - + cancelMultiselect(assetInteraction)} /> import { goto } from '$app/navigation'; - import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; import AddToAlbum from '$lib/components/timeline/actions/AddToAlbumAction.svelte'; import CreateSharedLink from '$lib/components/timeline/actions/CreateSharedLinkAction.svelte'; @@ -10,8 +9,7 @@ import { Route } from '$lib/route'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { AssetVisibility } from '@immich/sdk'; - import { mdiArrowLeft, mdiPlus } from '@mdi/js'; - import { t } from 'svelte-i18n'; + import { mdiArrowLeft } from '@mdi/js'; import type { PageData } from './$types'; interface Props { @@ -46,10 +44,7 @@ clearSelect={() => assetInteraction.clearMultiselect()} > - - - - + {:else} diff --git a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 57c5730b45..3c18b866c1 100644 --- a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -41,13 +41,7 @@ import { isExternalUrl } from '$lib/utils/navigation'; import { AssetVisibility, searchPerson, updatePerson, type PersonResponseDto } from '@immich/sdk'; import { ContextMenuButton, LoadingSpinner, modalManager, toastManager, type ActionItem } from '@immich/ui'; - import { - mdiAccountBoxOutline, - mdiAccountMultipleCheckOutline, - mdiArrowLeft, - mdiDotsVertical, - mdiPlus, - } from '@mdi/js'; + import { mdiAccountBoxOutline, mdiAccountMultipleCheckOutline, mdiArrowLeft, mdiDotsVertical } from '@mdi/js'; import { DateTime } from 'luxon'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; @@ -463,10 +457,7 @@ > - - - - + timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))} diff --git a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte index bea77bb443..bef36d5602 100644 --- a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte @@ -42,7 +42,7 @@ import { toTimelineAsset } from '$lib/utils/timeline-util'; import { AssetVisibility } from '@immich/sdk'; import { ImageCarousel } from '@immich/ui'; - import { mdiDotsVertical, mdiPlus } from '@mdi/js'; + import { mdiDotsVertical } from '@mdi/js'; import { t } from 'svelte-i18n'; let { isViewing: showAssetViewer } = assetViewingStore; @@ -134,10 +134,7 @@ - - - - + {#if isAllUserOwned} - - - - + {#if isAllUserOwned} + diff --git a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte index 2b498e56ea..868f23bf55 100644 --- a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -31,7 +31,7 @@ import { joinPaths, TreeNode } from '$lib/utils/tree-utils'; import { getAllTags, type TagResponseDto } from '@immich/sdk'; import { Text } from '@immich/ui'; - import { mdiDotsVertical, mdiPlus, mdiTag, mdiTagMultiple } from '@mdi/js'; + import { mdiDotsVertical, mdiTag, mdiTagMultiple } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { PageData } from './$types'; @@ -122,10 +122,7 @@ > - - - - + timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}