feat(server)!: add isOwned filter to albums API (#28213)

* feat(server)!: add owned filter to albums API

BREAKING CHANGE: GET /albums with no parameters now returns all accessible albums (owned + shared-with-me) instead of only owned albums.

* document tri-state matrix

* web impl

* collapse to single method and handover branching to sql

* dedupe

* verify that owned, shared, and notShared counts are mapped independently from their respective queries

* refactor(server): add select:['id'] overload to albumRepository.getAll

Avoid fetching full album rows (with albumUsers/sharedLinks subqueries) in map.service where only album IDs are needed.

* focus relevant test filters

* fmt

* Revert "verify that owned, shared, and notShared counts are mapped independently from their respective queries"

This reverts commit 47aab458192c766de4662aada5a6841b091d2a80.

* sync sql

* Revert "document tri-state matrix"

This reverts commit a5b2355d0c.

* address review comments

* inline shared condition and return as ternary

* sync sql

* use [...albums].sort

Array.toSorted() is not supported in Chrome 109

* use isShared and isOwned nomenclature

* fix e2e tests

* add params to sql query
This commit is contained in:
Timon
2026-05-07 18:13:07 +02:00
committed by GitHub
parent 7de73dc176
commit 1fcc2b704b
16 changed files with 284 additions and 327 deletions
+2 -5
View File
@@ -28,11 +28,8 @@
let { onClose }: Props = $props();
onMount(async () => {
// TODO the server should *really* just return all albums (paginated ideally)
const ownedAlbums = await getAllAlbums({ shared: false });
ownedAlbums.push.apply(ownedAlbums, await getAllAlbums({ shared: true }));
albums = ownedAlbums;
recentAlbums = albums.sort((a, b) => (new Date(a.updatedAt) > new Date(b.updatedAt) ? -1 : 1)).slice(0, 3);
albums = await getAllAlbums({});
recentAlbums = [...albums].sort((a, b) => (new Date(a.updatedAt) > new Date(b.updatedAt) ? -1 : 1)).slice(0, 3);
loading = false;
});
+2 -2
View File
@@ -5,8 +5,8 @@ import type { PageLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url);
const sharedAlbums = await getAllAlbums({ shared: true });
const albums = await getAllAlbums({});
const sharedAlbums = await getAllAlbums({ isShared: true });
const albums = await getAllAlbums({ isOwned: true });
const $t = await getFormatter();
return {
+1 -1
View File
@@ -5,7 +5,7 @@ import type { PageLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url);
const sharedAlbums = await getAllAlbums({ shared: true });
const sharedAlbums = await getAllAlbums({ isShared: true });
const partners = await getPartners({ direction: PartnerDirection.SharedWith });
const $t = await getFormatter();