feat: Display the number of selected items in AlbumPickerModal title (#30485)

This commit is contained in:
Adrien Fabre 2026-08-03 16:00:04 +02:00 committed by GitHub
parent 774a9fd868
commit c2db36934f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 70 additions and 4 deletions

View file

@ -30,6 +30,7 @@
"add_to_album_bottom_sheet_added": "Added to {album}",
"add_to_album_bottom_sheet_already_exists": "Already in {album}",
"add_to_album_bottom_sheet_some_local_assets": "Some local assets could not be added to album",
"add_to_album_item_count": "Add {count, plural, one {# item} other {# items}} to album",
"add_to_albums": "Add to albums",
"add_to_albums_count": "Add to albums ({count})",
"add_to_bottom_bar": "Add to",

View file

@ -14,7 +14,7 @@
let { array, label, description, albumIds = $bindable([]) }: Props = $props();
const onAlbums = async () => {
const albums = await modalManager.show(AlbumPickerModal);
const albums = await modalManager.show(AlbumPickerModal, {});
if (!albums || albums.length === 0) {
return;
}

View file

@ -0,0 +1,58 @@
import { render, screen, waitFor } from '@testing-library/svelte';
import { init, register, waitLocale } from 'svelte-i18n';
import { getAnimateMock } from '$lib/__mocks__/animate.mock';
import { getIntersectionObserverMock } from '$lib/__mocks__/intersection-observer.mock';
import { sdkMock } from '$lib/__mocks__/sdk.mock';
import { getVisualViewportMock } from '$lib/__mocks__/visual-viewport.mock';
import AlbumPickerModal from './AlbumPickerModal.svelte';
describe('AlbumPickerModal component', () => {
const onClose = vi.fn();
beforeAll(async () => {
await init({ fallbackLocale: 'en-US' });
register('en-US', () => import('$i18n/en.json'));
await waitLocale('en-US');
});
beforeEach(() => {
vi.stubGlobal('IntersectionObserver', getIntersectionObserverMock());
vi.stubGlobal('visualViewport', getVisualViewportMock());
vi.resetAllMocks();
Element.prototype.animate = getAnimateMock();
});
afterAll(async () => {
await waitFor(() => {
expect(document.body.style.pointerEvents).not.toBe('none');
});
});
it('shows the singular selection count title when selectedItemsCount is 1', async () => {
// Called by onMount()
sdkMock.getAllAlbums.mockResolvedValueOnce([]);
render(AlbumPickerModal, { props: { onClose, selectedItemsCount: 1 } });
expect(await screen.findByText('Add 1 item to album')).toBeInTheDocument();
expect(screen.queryByText('Select albums')).not.toBeInTheDocument();
});
it('shows the plural selection count title when selectedItemsCount is greater than 1', async () => {
sdkMock.getAllAlbums.mockResolvedValueOnce([]);
render(AlbumPickerModal, { props: { onClose, selectedItemsCount: 3 } });
expect(await screen.findByText('Add 3 items to album')).toBeInTheDocument();
expect(screen.queryByText('Select albums')).not.toBeInTheDocument();
});
it('shows the generic title when selectedItemsCount is not provided', async () => {
sdkMock.getAllAlbums.mockResolvedValueOnce([]);
render(AlbumPickerModal, { props: { onClose } });
expect(await screen.findByText('Select albums')).toBeInTheDocument();
expect(screen.queryByText('Add 1 item to album')).not.toBeInTheDocument();
});
});

View file

@ -23,9 +23,10 @@
type Props = {
onClose: (albums?: AlbumResponseDto[]) => void;
selectedItemsCount?: number;
};
let { onClose }: Props = $props();
let { onClose, selectedItemsCount }: Props = $props();
onMount(async () => {
albums = await getAllAlbums({});
@ -147,9 +148,15 @@
}
}
};
const title = $derived(
selectedItemsCount === undefined
? $t('select_albums')
: $t('add_to_album_item_count', { values: { count: selectedItemsCount } }),
);
</script>
<Modal title={$t('add_to_album')} {onClose} size="small">
<Modal {title} {onClose} size="small">
<ModalBody>
<div class="mb-2 flex max-h-100 flex-col">
{#if loading}

View file

@ -24,4 +24,4 @@
};
</script>
<AlbumPickerModal onClose={handleClose} />
<AlbumPickerModal selectedItemsCount={assetIds.length} onClose={handleClose} />