mirror of
https://github.com/immich-app/immich.git
synced 2025-12-06 09:13:13 +03:00
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
import { sortAlbums } from '$lib/utils/album-utils';
|
|
import { normalizeSearchString } from '$lib/utils/string-utils';
|
|
import type { AlbumResponseDto } from '@immich/sdk';
|
|
import { t } from 'svelte-i18n';
|
|
import { get } from 'svelte/store';
|
|
|
|
export const SCROLL_PROPERTIES: ScrollIntoViewOptions = { block: 'center', behavior: 'smooth' };
|
|
|
|
export enum AlbumModalRowType {
|
|
SECTION = 'section',
|
|
MESSAGE = 'message',
|
|
NEW_ALBUM = 'newAlbum',
|
|
ALBUM_ITEM = 'albumItem',
|
|
}
|
|
|
|
export type AlbumModalRow = {
|
|
type: AlbumModalRowType;
|
|
selected?: boolean;
|
|
multiSelected?: boolean;
|
|
text?: string;
|
|
album?: AlbumResponseDto;
|
|
};
|
|
|
|
export const isSelectableRowType = (type: AlbumModalRowType) =>
|
|
type === AlbumModalRowType.NEW_ALBUM || type === AlbumModalRowType.ALBUM_ITEM;
|
|
|
|
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;
|
|
this.sortBy = sortBy;
|
|
this.orderBy = orderBy;
|
|
}
|
|
|
|
toModalRows(
|
|
search: string,
|
|
recentAlbums: AlbumResponseDto[],
|
|
albums: AlbumResponseDto[],
|
|
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 : [];
|
|
const rows: AlbumModalRow[] = [{ type: AlbumModalRowType.NEW_ALBUM, selected: selectedRowIndex === 0 }];
|
|
|
|
const filteredAlbums = sortAlbums(
|
|
search.length > 0 && albums.length > 0
|
|
? albums.filter((album) => {
|
|
return normalizeSearchString(album.albumName).includes(normalizeSearchString(search));
|
|
})
|
|
: albums,
|
|
{ sortBy: this.sortBy, orderBy: this.orderBy },
|
|
);
|
|
|
|
if (filteredAlbums.length > 0) {
|
|
if (recentAlbumsToShow.length > 0) {
|
|
rows.push({ type: AlbumModalRowType.SECTION, text: $t('recent').toUpperCase() });
|
|
const selectedOffsetDueToNewAlbumRow = 1;
|
|
for (const [i, album] of recentAlbums.entries()) {
|
|
rows.push({
|
|
type: AlbumModalRowType.ALBUM_ITEM,
|
|
selected: selectedRowIndex === i + selectedOffsetDueToNewAlbumRow,
|
|
multiSelected: multiSelectedAlbumIds.includes(album.id),
|
|
album,
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!this.shared) {
|
|
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()) {
|
|
rows.push({
|
|
type: AlbumModalRowType.ALBUM_ITEM,
|
|
selected: selectedRowIndex === i + selectedOffsetDueToNewAndRecents,
|
|
multiSelected: multiSelectedAlbumIds.includes(album.id),
|
|
album,
|
|
});
|
|
}
|
|
} else if (albums.length > 0) {
|
|
rows.push({ type: AlbumModalRowType.MESSAGE, text: $t('no_albums_with_name_yet') });
|
|
} else {
|
|
rows.push({ type: AlbumModalRowType.MESSAGE, text: $t('no_albums_yet') });
|
|
}
|
|
return rows;
|
|
}
|
|
}
|