mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +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 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 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:document use:shortcut={{ shortcut: { key: 'l', shift: shared }, onShortcut: onClick }} />
|
||||
<svelte:document use:shortcut={{ shortcut: { key: 'l' }, onShortcut: onClick }} />
|
||||
|
||||
<MenuOption
|
||||
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
||||
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
||||
{onClick}
|
||||
/>
|
||||
<MenuOption icon={mdiImageAlbum} text={$t('add_to_album')} {onClick} />
|
||||
|
||||
@@ -186,7 +186,6 @@
|
||||
<RestoreAction {asset} {onAction} />
|
||||
{:else}
|
||||
<AddToAlbumAction {asset} {onAction} />
|
||||
<AddToAlbumAction {asset} {onAction} shared />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
mdiImageSearch,
|
||||
mdiPause,
|
||||
mdiPlay,
|
||||
mdiPlus,
|
||||
mdiSelectAll,
|
||||
mdiVolumeHigh,
|
||||
mdiVolumeOff,
|
||||
@@ -339,10 +338,7 @@
|
||||
onclick={handleSelectAll}
|
||||
/>
|
||||
|
||||
<ButtonContextMenu icon={mdiPlus} title={$t('add_to')}>
|
||||
<AddToAlbum />
|
||||
<AddToAlbum shared />
|
||||
</ButtonContextMenu>
|
||||
<AddToAlbum />
|
||||
|
||||
<FavoriteAction removeFavorite={assetInteraction.isAllFavorite} />
|
||||
|
||||
|
||||
+12
-35
@@ -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, []);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<MenuOption
|
||||
{onClick}
|
||||
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
||||
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
||||
shortcut={{ key: 'l', shift: shared }}
|
||||
/>
|
||||
{#if menuItem}
|
||||
<MenuOption {onClick} text={$t('add_to_album')} icon={mdiImageAlbum} shortcut={{ key: 'l' }} />
|
||||
{/if}
|
||||
|
||||
{#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 () => {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user