fix: albums page reactivity loops (#24046)

feat/sync-adjustment-time
Daniel Dietzler 2025-11-24 17:14:24 +07:00 committed by GitHub
parent 24e5dabb51
commit 0498f6cb9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 23 additions and 42 deletions

@ -33,7 +33,6 @@
import { groupBy } from 'lodash-es'; import { groupBy } from 'lodash-es';
import { onMount, type Snippet } from 'svelte'; import { onMount, type Snippet } from 'svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import { run } from 'svelte/legacy';
interface Props { interface Props {
ownedAlbums?: AlbumResponseDto[]; ownedAlbums?: AlbumResponseDto[];
@ -128,63 +127,45 @@
}, },
}; };
let albums: AlbumResponseDto[] = $state([]); let albums = $derived.by(() => {
let filteredAlbums: AlbumResponseDto[] = $state([]);
let groupedAlbums: AlbumGroup[] = $state([]);
let albumGroupOption: string = $state(AlbumGroupBy.None);
let contextMenuPosition: ContextMenuPosition = $state({ x: 0, y: 0 });
let selectedAlbum: AlbumResponseDto | undefined = $state();
let isOpen = $state(false);
// Step 1: Filter between Owned and Shared albums, or both.
run(() => {
switch (userSettings.filter) { switch (userSettings.filter) {
case AlbumFilter.Owned: { case AlbumFilter.Owned: {
albums = ownedAlbums; return ownedAlbums;
break;
} }
case AlbumFilter.Shared: { case AlbumFilter.Shared: {
albums = sharedAlbums; return sharedAlbums;
break;
} }
default: { default: {
const userId = $user.id; const nonOwnedAlbums = sharedAlbums.filter((album) => album.ownerId !== $user.id);
const nonOwnedAlbums = sharedAlbums.filter((album) => album.ownerId !== userId); return nonOwnedAlbums.length > 0 ? ownedAlbums.concat(nonOwnedAlbums) : ownedAlbums;
albums = nonOwnedAlbums.length > 0 ? ownedAlbums.concat(nonOwnedAlbums) : ownedAlbums;
} }
} }
}); });
const normalizedSearchQuery = $derived(normalizeSearchString(searchQuery));
// Step 2: Filter using the given search query. let filteredAlbums = $derived(
run(() => { normalizedSearchQuery
if (searchQuery) { ? albums.filter(({ albumName }) => normalizeSearchString(albumName).includes(normalizedSearchQuery))
const searchAlbumNormalized = normalizeSearchString(searchQuery); : albums,
);
filteredAlbums = albums.filter((album) => {
return normalizeSearchString(album.albumName).includes(searchAlbumNormalized); let albumGroupOption = $derived(getSelectedAlbumGroupOption(userSettings));
}); let groupedAlbums = $derived.by(() => {
} else {
filteredAlbums = albums;
}
});
// Step 3: Group albums.
run(() => {
albumGroupOption = getSelectedAlbumGroupOption(userSettings);
const groupFunc = groupOptions[albumGroupOption] ?? groupOptions[AlbumGroupBy.None]; const groupFunc = groupOptions[albumGroupOption] ?? groupOptions[AlbumGroupBy.None];
groupedAlbums = groupFunc(stringToSortOrder(userSettings.groupOrder), filteredAlbums); const groupedAlbums = groupFunc(stringToSortOrder(userSettings.groupOrder), filteredAlbums);
});
// Step 4: Sort albums amongst each group. return groupedAlbums.map((group) => ({
run(() => {
groupedAlbums = groupedAlbums.map((group) => ({
id: group.id, id: group.id,
name: group.name, name: group.name,
albums: sortAlbums(group.albums, { sortBy: userSettings.sortBy, orderBy: userSettings.sortOrder }), albums: sortAlbums(group.albums, { sortBy: userSettings.sortBy, orderBy: userSettings.sortOrder }),
})); }));
});
let contextMenuPosition: ContextMenuPosition = $state({ x: 0, y: 0 });
let selectedAlbum: AlbumResponseDto | undefined = $state();
let isOpen = $state(false);
// TODO get rid of this
$effect(() => {
albumGroupIds = groupedAlbums.map(({ id }) => id); albumGroupIds = groupedAlbums.map(({ id }) => id);
}); });