mirror of
https://github.com/immich-app/immich.git
synced 2026-02-28 01:29:04 +03:00
chore(web): merge "Add to album" and "Add to shared album" actions into a single action (#24669)
* refactor: simplify album selection actions by removing shared option * Removed the shared option from AddToAlbumAction and related components. * Updated AlbumPickerModal and other components to reflect this change. * Cleaned up related tests and documentation for consistency. * fix lint
This commit is contained in:
@@ -8,19 +8,18 @@
|
|||||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||||
import type { AssetResponseDto } from '@immich/sdk';
|
import type { AssetResponseDto } from '@immich/sdk';
|
||||||
import { modalManager } from '@immich/ui';
|
import { modalManager } from '@immich/ui';
|
||||||
import { mdiImageAlbum, mdiShareVariantOutline } from '@mdi/js';
|
import { mdiImageAlbum } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
asset: AssetResponseDto;
|
asset: AssetResponseDto;
|
||||||
onAction: OnAction;
|
onAction: OnAction;
|
||||||
shared?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { asset, onAction, shared = false }: Props = $props();
|
let { asset, onAction }: Props = $props();
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
const albums = await modalManager.show(AlbumPickerModal, { shared });
|
const albums = await modalManager.show(AlbumPickerModal, {});
|
||||||
|
|
||||||
if (!albums || albums.length === 0) {
|
if (!albums || albums.length === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -40,10 +39,6 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:document use:shortcut={{ shortcut: { key: 'l', shift: shared }, onShortcut: onClick }} />
|
<svelte:document use:shortcut={{ shortcut: { key: 'l' }, onShortcut: onClick }} />
|
||||||
|
|
||||||
<MenuOption
|
<MenuOption icon={mdiImageAlbum} text={$t('add_to_album')} {onClick} />
|
||||||
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
|
||||||
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
|
||||||
{onClick}
|
|
||||||
/>
|
|
||||||
|
|||||||
@@ -186,7 +186,6 @@
|
|||||||
<RestoreAction {asset} {onAction} />
|
<RestoreAction {asset} {onAction} />
|
||||||
{:else}
|
{:else}
|
||||||
<AddToAlbumAction {asset} {onAction} />
|
<AddToAlbumAction {asset} {onAction} />
|
||||||
<AddToAlbumAction {asset} {onAction} shared />
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
mdiImageSearch,
|
mdiImageSearch,
|
||||||
mdiPause,
|
mdiPause,
|
||||||
mdiPlay,
|
mdiPlay,
|
||||||
mdiPlus,
|
|
||||||
mdiSelectAll,
|
mdiSelectAll,
|
||||||
mdiVolumeHigh,
|
mdiVolumeHigh,
|
||||||
mdiVolumeOff,
|
mdiVolumeOff,
|
||||||
@@ -339,10 +338,7 @@
|
|||||||
onclick={handleSelectAll}
|
onclick={handleSelectAll}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
|
|
||||||
<FavoriteAction removeFavorite={assetInteraction.isAllFavorite} />
|
<FavoriteAction removeFavorite={assetInteraction.isAllFavorite} />
|
||||||
|
|
||||||
|
|||||||
@@ -28,15 +28,15 @@ const createAlbumRow = (album: AlbumResponseDto, selected: boolean) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Album Modal', () => {
|
describe('Album Modal', () => {
|
||||||
it('non-shared with no albums configured yet shows message and new', () => {
|
it('no albums configured yet shows message and new', () => {
|
||||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||||
const modalRows = converter.toModalRows('', [], [], -1, []);
|
const modalRows = converter.toModalRows('', [], [], -1, []);
|
||||||
|
|
||||||
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_yet')]);
|
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_yet')]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('non-shared with no matching albums shows message and new', () => {
|
it('no matching albums shows message and new', () => {
|
||||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||||
const modalRows = converter.toModalRows(
|
const modalRows = converter.toModalRows(
|
||||||
'matches_nothing',
|
'matches_nothing',
|
||||||
[],
|
[],
|
||||||
@@ -48,8 +48,8 @@ describe('Album Modal', () => {
|
|||||||
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_with_name_yet')]);
|
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_with_name_yet')]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('non-shared displays single albums', () => {
|
it('displays single 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 holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const modalRows = converter.toModalRows('', [], [holidayAlbum], -1, []);
|
const modalRows = converter.toModalRows('', [], [holidayAlbum], -1, []);
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ describe('Album Modal', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('non-shared displays multiple albums and recents', () => {
|
it('displays multiple albums and recents', () => {
|
||||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
const converter = new AlbumModalRowConverter(AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||||
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||||
const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' });
|
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', () => {
|
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 holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||||
const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' });
|
const birthdayAlbum = albumFactory.build({ albumName: 'Birthday' });
|
||||||
@@ -132,7 +109,7 @@ describe('Album Modal', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('selection can select new album row', () => {
|
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 holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 0, []);
|
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 0, []);
|
||||||
@@ -148,7 +125,7 @@ describe('Album Modal', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('selection can select recent row', () => {
|
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 holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 1, []);
|
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 1, []);
|
||||||
@@ -164,7 +141,7 @@ describe('Album Modal', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('selection can select last row', () => {
|
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 holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 3, []);
|
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 3, []);
|
||||||
|
|||||||
@@ -27,12 +27,10 @@ export const isSelectableRowType = (type: AlbumModalRowType) =>
|
|||||||
const $t = get(t);
|
const $t = get(t);
|
||||||
|
|
||||||
export class AlbumModalRowConverter {
|
export class AlbumModalRowConverter {
|
||||||
private readonly shared: boolean;
|
|
||||||
private readonly sortBy: string;
|
private readonly sortBy: string;
|
||||||
private readonly orderBy: string;
|
private readonly orderBy: string;
|
||||||
|
|
||||||
constructor(shared: boolean, sortBy: string, orderBy: string) {
|
constructor(sortBy: string, orderBy: string) {
|
||||||
this.shared = shared;
|
|
||||||
this.sortBy = sortBy;
|
this.sortBy = sortBy;
|
||||||
this.orderBy = orderBy;
|
this.orderBy = orderBy;
|
||||||
}
|
}
|
||||||
@@ -44,8 +42,8 @@ export class AlbumModalRowConverter {
|
|||||||
selectedRowIndex: number,
|
selectedRowIndex: number,
|
||||||
multiSelectedAlbumIds: string[],
|
multiSelectedAlbumIds: string[],
|
||||||
): AlbumModalRow[] {
|
): AlbumModalRow[] {
|
||||||
// only show recent albums if no search was entered, or we're in the normal albums (non-shared) modal.
|
// only show recent albums if no search was entered
|
||||||
const recentAlbumsToShow = !this.shared && search.length === 0 ? recentAlbums : [];
|
const recentAlbumsToShow = search.length === 0 ? recentAlbums : [];
|
||||||
const rows: AlbumModalRow[] = [{ type: AlbumModalRowType.NEW_ALBUM, selected: selectedRowIndex === 0 }];
|
const rows: AlbumModalRow[] = [{ type: AlbumModalRowType.NEW_ALBUM, selected: selectedRowIndex === 0 }];
|
||||||
|
|
||||||
const filteredAlbums = sortAlbums(
|
const filteredAlbums = sortAlbums(
|
||||||
@@ -71,12 +69,10 @@ export class AlbumModalRowConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.shared) {
|
|
||||||
rows.push({
|
rows.push({
|
||||||
type: AlbumModalRowType.SECTION,
|
type: AlbumModalRowType.SECTION,
|
||||||
text: (search.length === 0 ? $t('all_albums') : $t('albums')).toUpperCase(),
|
text: (search.length === 0 ? $t('all_albums') : $t('albums')).toUpperCase(),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
const selectedOffsetDueToNewAndRecents = 1 + recentAlbumsToShow.length;
|
const selectedOffsetDueToNewAndRecents = 1 + recentAlbumsToShow.length;
|
||||||
for (const [i, album] of filteredAlbums.entries()) {
|
for (const [i, album] of filteredAlbums.entries()) {
|
||||||
|
|||||||
@@ -4,21 +4,21 @@
|
|||||||
import type { OnAddToAlbum } from '$lib/utils/actions';
|
import type { OnAddToAlbum } from '$lib/utils/actions';
|
||||||
import { addAssetsToAlbum, addAssetsToAlbums } from '$lib/utils/asset-utils';
|
import { addAssetsToAlbum, addAssetsToAlbums } from '$lib/utils/asset-utils';
|
||||||
import { getAssetControlContext } from '$lib/utils/context';
|
import { getAssetControlContext } from '$lib/utils/context';
|
||||||
import { modalManager } from '@immich/ui';
|
import { IconButton, modalManager } from '@immich/ui';
|
||||||
import { mdiImageAlbum, mdiShareVariantOutline } from '@mdi/js';
|
import { mdiImageAlbum, mdiPlus } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
shared?: boolean;
|
|
||||||
onAddToAlbum?: OnAddToAlbum;
|
onAddToAlbum?: OnAddToAlbum;
|
||||||
|
menuItem?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { shared = false, onAddToAlbum = () => {} }: Props = $props();
|
let { onAddToAlbum = () => {}, menuItem = false }: Props = $props();
|
||||||
|
|
||||||
const { getAssets } = getAssetControlContext();
|
const { getAssets } = getAssetControlContext();
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
const albums = await modalManager.show(AlbumPickerModal, { shared });
|
const albums = await modalManager.show(AlbumPickerModal, {});
|
||||||
if (!albums || albums.length === 0) {
|
if (!albums || albums.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -38,9 +38,17 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<MenuOption
|
{#if menuItem}
|
||||||
{onClick}
|
<MenuOption {onClick} text={$t('add_to_album')} icon={mdiImageAlbum} shortcut={{ key: 'l' }} />
|
||||||
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
{/if}
|
||||||
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
|
||||||
shortcut={{ key: 'l', shift: shared }}
|
{#if !menuItem}
|
||||||
/>
|
<IconButton
|
||||||
|
shape="round"
|
||||||
|
color="secondary"
|
||||||
|
variant="ghost"
|
||||||
|
icon={mdiPlus}
|
||||||
|
aria-label={$t('add_to_album')}
|
||||||
|
onclick={onClick}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
const handlePicker = async () => {
|
const handlePicker = async () => {
|
||||||
if (isAlbum) {
|
if (isAlbum) {
|
||||||
const albums = await modalManager.show(AlbumPickerModal, { shared: false });
|
const albums = await modalManager.show(AlbumPickerModal);
|
||||||
if (albums && albums.length > 0) {
|
if (albums && albums.length > 0) {
|
||||||
const newValue = multiple ? albums.map((album) => album.id) : albums[0].id;
|
const newValue = multiple ? albums.map((album) => album.id) : albums[0].id;
|
||||||
onchange(newValue);
|
onchange(newValue);
|
||||||
|
|||||||
@@ -21,14 +21,13 @@
|
|||||||
let selectedRowIndex: number = $state(-1);
|
let selectedRowIndex: number = $state(-1);
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
shared: boolean;
|
|
||||||
onClose: (albums?: AlbumResponseDto[]) => void;
|
onClose: (albums?: AlbumResponseDto[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { shared, onClose }: Props = $props();
|
let { onClose }: Props = $props();
|
||||||
|
|
||||||
onMount(async () => {
|
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);
|
recentAlbums = albums.sort((a, b) => (new Date(a.updatedAt) > new Date(b.updatedAt) ? -1 : 1)).slice(0, 3);
|
||||||
loading = false;
|
loading = false;
|
||||||
});
|
});
|
||||||
@@ -36,7 +35,7 @@
|
|||||||
const multiSelectedAlbumIds: string[] = $state([]);
|
const multiSelectedAlbumIds: string[] = $state([]);
|
||||||
const multiSelectActive = $derived(multiSelectedAlbumIds.length > 0);
|
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(
|
const albumModalRows = $derived(
|
||||||
rowConverter.toModalRows(search, recentAlbums, albums, selectedRowIndex, multiSelectedAlbumIds),
|
rowConverter.toModalRows(search, recentAlbums, albums, selectedRowIndex, multiSelectedAlbumIds),
|
||||||
);
|
);
|
||||||
@@ -146,7 +145,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal title={shared ? $t('add_to_shared_album') : $t('add_to_album')} {onClose} size="small">
|
<Modal title={$t('add_to_album')} {onClose} size="small">
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<div class="mb-2 flex max-h-100 flex-col">
|
<div class="mb-2 flex max-h-100 flex-col">
|
||||||
{#if loading}
|
{#if loading}
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
{ key: ['s'], action: $t('stack_selected_photos') },
|
{ key: ['s'], action: $t('stack_selected_photos') },
|
||||||
{ key: ['l'], action: $t('add_to_album') },
|
{ key: ['l'], action: $t('add_to_album') },
|
||||||
{ key: ['t'], action: $t('tag_assets') },
|
{ key: ['t'], action: $t('tag_assets') },
|
||||||
{ key: ['⇧', 'l'], action: $t('add_to_shared_album') },
|
|
||||||
{ key: ['⇧', 'a'], action: $t('archive_or_unarchive_photo') },
|
{ key: ['⇧', 'a'], action: $t('archive_or_unarchive_photo') },
|
||||||
{ key: ['⇧', 'd'], action: $t('download') },
|
{ key: ['⇧', 'd'], action: $t('download') },
|
||||||
{ key: ['Space'], action: $t('play_or_pause_video') },
|
{ key: ['Space'], action: $t('play_or_pause_video') },
|
||||||
|
|||||||
@@ -440,10 +440,7 @@
|
|||||||
>
|
>
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
{#if assetInteraction.isAllUserOwned}
|
{#if assetInteraction.isAllUserOwned}
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { AssetVisibility } from '@immich/sdk';
|
import { AssetVisibility } from '@immich/sdk';
|
||||||
import { mdiDotsVertical, mdiPlus } from '@mdi/js';
|
import { mdiDotsVertical } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
@@ -70,10 +70,7 @@
|
|||||||
/>
|
/>
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { preferences } from '$lib/stores/user.store';
|
import { preferences } from '$lib/stores/user.store';
|
||||||
import { mdiDotsVertical, mdiPlus } from '@mdi/js';
|
import { mdiDotsVertical } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
@@ -71,10 +71,7 @@
|
|||||||
<FavoriteAction removeFavorite onFavorite={(assetIds) => timelineManager.removeAssets(assetIds)} />
|
<FavoriteAction removeFavorite onFavorite={(assetIds) => timelineManager.removeAssets(assetIds)} />
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
|
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
|
||||||
<DownloadAction menuItem />
|
<DownloadAction menuItem />
|
||||||
<ChangeDate menuItem />
|
<ChangeDate menuItem />
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||||
import { joinPaths } from '$lib/utils/tree-utils';
|
import { joinPaths } from '$lib/utils/tree-utils';
|
||||||
import { IconButton, Text } from '@immich/ui';
|
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 { t } from 'svelte-i18n';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
@@ -130,10 +130,7 @@
|
|||||||
icon={mdiSelectAll}
|
icon={mdiSelectAll}
|
||||||
onclick={handleSelectAllAssets}
|
onclick={handleSelectAllAssets}
|
||||||
/>
|
/>
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum onAddToAlbum={() => cancelMultiselect(assetInteraction)} />
|
<AddToAlbum onAddToAlbum={() => cancelMultiselect(assetInteraction)} />
|
||||||
<AddToAlbum onAddToAlbum={() => cancelMultiselect(assetInteraction)} shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
onFavorite={function handleFavoriteUpdate(ids, isFavorite) {
|
onFavorite={function handleFavoriteUpdate(ids, isFavorite) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
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 ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||||
import AddToAlbum from '$lib/components/timeline/actions/AddToAlbumAction.svelte';
|
import AddToAlbum from '$lib/components/timeline/actions/AddToAlbumAction.svelte';
|
||||||
import CreateSharedLink from '$lib/components/timeline/actions/CreateSharedLinkAction.svelte';
|
import CreateSharedLink from '$lib/components/timeline/actions/CreateSharedLinkAction.svelte';
|
||||||
@@ -10,8 +9,7 @@
|
|||||||
import { Route } from '$lib/route';
|
import { Route } from '$lib/route';
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { AssetVisibility } from '@immich/sdk';
|
import { AssetVisibility } from '@immich/sdk';
|
||||||
import { mdiArrowLeft, mdiPlus } from '@mdi/js';
|
import { mdiArrowLeft } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -46,10 +44,7 @@
|
|||||||
clearSelect={() => assetInteraction.clearMultiselect()}
|
clearSelect={() => assetInteraction.clearMultiselect()}
|
||||||
>
|
>
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<DownloadAction />
|
<DownloadAction />
|
||||||
</AssetSelectControlBar>
|
</AssetSelectControlBar>
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@@ -41,13 +41,7 @@
|
|||||||
import { isExternalUrl } from '$lib/utils/navigation';
|
import { isExternalUrl } from '$lib/utils/navigation';
|
||||||
import { AssetVisibility, searchPerson, updatePerson, type PersonResponseDto } from '@immich/sdk';
|
import { AssetVisibility, searchPerson, updatePerson, type PersonResponseDto } from '@immich/sdk';
|
||||||
import { ContextMenuButton, LoadingSpinner, modalManager, toastManager, type ActionItem } from '@immich/ui';
|
import { ContextMenuButton, LoadingSpinner, modalManager, toastManager, type ActionItem } from '@immich/ui';
|
||||||
import {
|
import { mdiAccountBoxOutline, mdiAccountMultipleCheckOutline, mdiArrowLeft, mdiDotsVertical } from '@mdi/js';
|
||||||
mdiAccountBoxOutline,
|
|
||||||
mdiAccountMultipleCheckOutline,
|
|
||||||
mdiArrowLeft,
|
|
||||||
mdiDotsVertical,
|
|
||||||
mdiPlus,
|
|
||||||
} from '@mdi/js';
|
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@@ -463,10 +457,7 @@
|
|||||||
>
|
>
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||||
import { AssetVisibility } from '@immich/sdk';
|
import { AssetVisibility } from '@immich/sdk';
|
||||||
import { ImageCarousel } from '@immich/ui';
|
import { ImageCarousel } from '@immich/ui';
|
||||||
import { mdiDotsVertical, mdiPlus } from '@mdi/js';
|
import { mdiDotsVertical } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
let { isViewing: showAssetViewer } = assetViewingStore;
|
let { isViewing: showAssetViewer } = assetViewingStore;
|
||||||
@@ -134,10 +134,7 @@
|
|||||||
|
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
|
|
||||||
{#if isAllUserOwned}
|
{#if isAllUserOwned}
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
type SmartSearchDto,
|
type SmartSearchDto,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { Icon, IconButton, LoadingSpinner } from '@immich/ui';
|
import { Icon, IconButton, LoadingSpinner } from '@immich/ui';
|
||||||
import { mdiArrowLeft, mdiDotsVertical, mdiImageOffOutline, mdiPlus, mdiSelectAll } from '@mdi/js';
|
import { mdiArrowLeft, mdiDotsVertical, mdiImageOffOutline, mdiSelectAll } from '@mdi/js';
|
||||||
import { tick, untrack } from 'svelte';
|
import { tick, untrack } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
@@ -339,10 +339,7 @@
|
|||||||
icon={mdiSelectAll}
|
icon={mdiSelectAll}
|
||||||
onclick={handleSelectAll}
|
onclick={handleSelectAll}
|
||||||
/>
|
/>
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum {onAddToAlbum} />
|
<AddToAlbum {onAddToAlbum} />
|
||||||
<AddToAlbum shared {onAddToAlbum} />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
{#if isAllUserOwned}
|
{#if isAllUserOwned}
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
@@ -357,6 +354,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
|
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
|
||||||
|
<AddToAlbum menuItem {onAddToAlbum} />
|
||||||
<DownloadAction menuItem />
|
<DownloadAction menuItem />
|
||||||
<ChangeDate menuItem />
|
<ChangeDate menuItem />
|
||||||
<ChangeDescription menuItem />
|
<ChangeDescription menuItem />
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
import { joinPaths, TreeNode } from '$lib/utils/tree-utils';
|
import { joinPaths, TreeNode } from '$lib/utils/tree-utils';
|
||||||
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
import { getAllTags, type TagResponseDto } from '@immich/sdk';
|
||||||
import { Text } from '@immich/ui';
|
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 { t } from 'svelte-i18n';
|
||||||
import type { PageData } from './$types';
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
@@ -122,10 +122,7 @@
|
|||||||
>
|
>
|
||||||
<CreateSharedLink />
|
<CreateSharedLink />
|
||||||
<SelectAllAssets {timelineManager} {assetInteraction} />
|
<SelectAllAssets {timelineManager} {assetInteraction} />
|
||||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
|
||||||
<AddToAlbum />
|
<AddToAlbum />
|
||||||
<AddToAlbum shared />
|
|
||||||
</ButtonContextMenu>
|
|
||||||
<FavoriteAction
|
<FavoriteAction
|
||||||
removeFavorite={assetInteraction.isAllFavorite}
|
removeFavorite={assetInteraction.isAllFavorite}
|
||||||
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
onFavorite={(ids, isFavorite) => timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))}
|
||||||
|
|||||||
Reference in New Issue
Block a user