diff --git a/projects/client/i18n/meta/en.json b/projects/client/i18n/meta/en.json
index 29aa170b20..d81daa9c00 100644
--- a/projects/client/i18n/meta/en.json
+++ b/projects/client/i18n/meta/en.json
@@ -6963,6 +6963,75 @@
}
}
},
+ "list_summary_range_up_to": {
+ "default": "Up to {value}",
+ "description": "Smart list filter summary for an upper-bound-only range, e.g. 'Up to 90'.",
+ "variables": {
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "list_summary_range_labeled_up_to": {
+ "default": "{label} up to {value}",
+ "description": "Smart list filter summary for a labeled upper-bound-only range, e.g. 'Trakt up to 80%'.",
+ "variables": {
+ "label": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "list_summary_range_between": {
+ "default": "{min} to {max}",
+ "description": "Smart list filter summary for a range with both bounds, e.g. '60 to 80'.",
+ "variables": {
+ "min": {
+ "type": "string"
+ },
+ "max": {
+ "type": "string"
+ }
+ }
+ },
+ "list_summary_range_labeled_between": {
+ "default": "{label} {min} to {max}",
+ "description": "Smart list filter summary for a labeled range with both bounds, e.g. 'Trakt 60% to 80%'.",
+ "variables": {
+ "label": {
+ "type": "string"
+ },
+ "min": {
+ "type": "string"
+ },
+ "max": {
+ "type": "string"
+ }
+ }
+ },
+ "list_summary_range_from": {
+ "default": "{value} and up",
+ "description": "Smart list filter summary for a lower-bound-only range, e.g. '60 and up'.",
+ "variables": {
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "list_summary_range_labeled_from": {
+ "default": "{label} {value} and up",
+ "description": "Smart list filter summary for a labeled lower-bound-only range, e.g. 'Trakt 60% and up'.",
+ "variables": {
+ "label": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
"warning_smart_lists_limit": {
"default": "You've reached your smart list limit",
"description": "Warning text shown when a user has reached their smart list limit and attempts to create a new smart list."
diff --git a/projects/client/src/lib/sections/lists/components/ListSummaryCard.svelte b/projects/client/src/lib/sections/lists/components/ListSummaryCard.svelte
new file mode 100644
index 0000000000..89c46a2de2
--- /dev/null
+++ b/projects/client/src/lib/sections/lists/components/ListSummaryCard.svelte
@@ -0,0 +1,61 @@
+
+
+
+
+ {@render children()}
+
+
+
+
diff --git a/projects/client/src/lib/sections/lists/components/list-summary/ListSummaryItem.svelte b/projects/client/src/lib/sections/lists/components/list-summary/ListSummaryItem.svelte
index 8667ac6af6..b613cdbf53 100644
--- a/projects/client/src/lib/sections/lists/components/list-summary/ListSummaryItem.svelte
+++ b/projects/client/src/lib/sections/lists/components/list-summary/ListSummaryItem.svelte
@@ -1,7 +1,7 @@
-
-
-
-
-
-
-
-
+
+
+
+
diff --git a/projects/client/src/lib/sections/lists/smart/SmartLists.svelte b/projects/client/src/lib/sections/lists/smart/SmartLists.svelte
index 2e3b778d4b..7f7bf1e9b3 100644
--- a/projects/client/src/lib/sections/lists/smart/SmartLists.svelte
+++ b/projects/client/src/lib/sections/lists/smart/SmartLists.svelte
@@ -1,24 +1,22 @@
@@ -26,38 +24,26 @@
{/snippet}
-{#if $list.length === 0}
-
- {#snippet item(_)}{/snippet}
- {#snippet empty()}
-
- {/snippet}
-
-{:else}
-
-
- {#snippet icon()}
-
- {/snippet}
-
-
-
-
-{/if}
+
+ {#snippet item(list)}
+
+ {/snippet}
-
+ {#snippet empty()}
+ {#if !$isLoading}
+
+ {/if}
+ {/snippet}
+
diff --git a/projects/client/src/lib/sections/lists/smart/_internal/SmartListSummaryItem.svelte b/projects/client/src/lib/sections/lists/smart/_internal/SmartListSummaryItem.svelte
new file mode 100644
index 0000000000..e7737e6410
--- /dev/null
+++ b/projects/client/src/lib/sections/lists/smart/_internal/SmartListSummaryItem.svelte
@@ -0,0 +1,294 @@
+
+
+
+
+
+
+
+ {#each $posters as poster, index (`${list.id}_poster_${index}`)}
+
+
+
+ {/each}
+
+
+
+
+
diff --git a/projects/client/src/lib/sections/lists/smart/_internal/useSmartListPreview.ts b/projects/client/src/lib/sections/lists/smart/_internal/useSmartListPreview.ts
new file mode 100644
index 0000000000..296734e31c
--- /dev/null
+++ b/projects/client/src/lib/sections/lists/smart/_internal/useSmartListPreview.ts
@@ -0,0 +1,48 @@
+import { map, of } from 'rxjs';
+import type { SmartList } from '$lib/requests/queries/users/smartListQuery.ts';
+import { useAnticipatedList } from '../../anticipated/useAnticipatedList.ts';
+import { usePopularList } from '../../popular/usePopularList.ts';
+import { useTrendingList } from '../../trending/useTrendingList.ts';
+
+const previewLimit = 8;
+
+function smartListToPreviewQuery(list: SmartList) {
+ const params = {
+ limit: previewLimit,
+ search: list.params,
+ type: list.type,
+ };
+
+ switch (list.target) {
+ case 'trending':
+ return useTrendingList(params);
+ case 'popular':
+ return usePopularList(params);
+ case 'anticipated':
+ return useAnticipatedList(params);
+ case 'unknown':
+ return undefined;
+ }
+}
+
+export function useSmartListPreview(list: SmartList) {
+ const query = smartListToPreviewQuery(list);
+
+ if (!query) {
+ return {
+ isLoading: of(false),
+ posters: of([]),
+ };
+ }
+
+ return {
+ isLoading: query.isLoading,
+ posters: query.list.pipe(
+ map((items) =>
+ items
+ .map((item) => item.poster.url.thumb)
+ .slice(0, previewLimit)
+ ),
+ ),
+ };
+}
diff --git a/projects/client/src/lib/sections/lists/user/PersonalLists.svelte b/projects/client/src/lib/sections/lists/user/PersonalLists.svelte
index dccec18d0e..c3f52494d2 100644
--- a/projects/client/src/lib/sections/lists/user/PersonalLists.svelte
+++ b/projects/client/src/lib/sections/lists/user/PersonalLists.svelte
@@ -19,12 +19,19 @@
import UserList from "./UserList.svelte";
const previewLimit = 3;
+ type PersonalListsDisplay = "auto" | "compact";
const {
type,
slug,
mode,
- }: { type: PersonalListType; slug: string; mode?: DiscoverMode } = $props();
+ display = "auto",
+ }: {
+ type: PersonalListType;
+ slug: string;
+ mode?: DiscoverMode;
+ display?: PersonalListsDisplay;
+ } = $props();
const {
list: lists,
@@ -35,13 +42,20 @@
const { isMe } = $derived(useIsMe(slug));
const variant = $derived.by(() => {
+ if (display === "compact") {
+ return "summary";
+ }
+
const shouldShowSummary =
$hasNextPage || $lists.length === 0 || $lists.length > previewLimit;
return shouldShowSummary ? "summary" : "preview";
});
const isMine = $derived(type === "personal" && $isMe);
- const isPresentable = $derived(isMine || (!$isLoading && $lists.length > 0));
+ const isPresentable = $derived(
+ (display === "compact" ? $isMe : isMine) ||
+ (!$isLoading && $lists.length > 0),
+ );
const title = $derived.by(() => {
switch (type) {
@@ -111,6 +125,7 @@
href: UrlBuilder.lists.all(slug, type),
label: m.button_label_view_all_lists(),
source: { id: "personal-lists", type },
+ mode: "always",
}}
--height-list="var(--height-lists-list)"
--height-override-list={$lists.length === 0
@@ -148,6 +163,6 @@
.trakt-lists-preview {
display: flex;
flex-direction: column;
- gap: var(--gap-micro);
+ gap: var(--content-gap);
}
diff --git a/projects/client/src/routes/users/[user]/lists/+page.svelte b/projects/client/src/routes/users/[user]/lists/+page.svelte
index 15d25f17e4..0c41a8406e 100644
--- a/projects/client/src/routes/users/[user]/lists/+page.svelte
+++ b/projects/client/src/routes/users/[user]/lists/+page.svelte
@@ -9,6 +9,7 @@
import TraktPageCoverSetter from "$lib/sections/layout/TraktPageCoverSetter.svelte";
import SmartLists from "$lib/sections/lists/smart/SmartLists.svelte";
import PersonalLists from "$lib/sections/lists/user/PersonalLists.svelte";
+ import type { PersonalListType } from "$lib/sections/lists/user/models/PersonalListType.ts";
import WatchList from "$lib/sections/lists/watchlist/WatchList.svelte";
import NavbarStateSetter from "$lib/sections/navbar/NavbarStateSetter.svelte";
import { DEFAULT_SHARE_COVER } from "$lib/utils/assets";
@@ -21,6 +22,12 @@
const { user } = useUser();
const { isMe } = $derived(useIsMe(params.user));
+
+ const personalListTypes: PersonalListType[] = [
+ "personal",
+ "liked",
+ "collaboration",
+ ];
-
-
-
+ {#each personalListTypes as type (type)}
+
+ {/each}