Fix sleep bug, fix menu return
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m1s
Traceability Validation / Check Requirement Traces (push) Successful in 23s
Build & Release / Run Tests (push) Successful in 4m7s
🏗️ Build and Test JellyTau / Build Android APK (push) Successful in 19m5s
Build & Release / Build Linux (push) Successful in 16m20s
Build & Release / Build Android (push) Successful in 19m12s
Build & Release / Create Release (push) Successful in 8s
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 4m1s
Traceability Validation / Check Requirement Traces (push) Successful in 23s
Build & Release / Run Tests (push) Successful in 4m7s
🏗️ Build and Test JellyTau / Build Android APK (push) Successful in 19m5s
Build & Release / Build Linux (push) Successful in 16m20s
Build & Release / Build Android (push) Successful in 19m12s
Build & Release / Create Release (push) Successful in 8s
This commit is contained in:
+21
-32
@@ -4,6 +4,7 @@
|
||||
import { writable, derived } from "svelte/store";
|
||||
import type { MediaItem } from "$lib/api/types";
|
||||
import { auth } from "./auth";
|
||||
import { buildHeroMix } from "$lib/utils/heroMix";
|
||||
|
||||
/** A single "by genre" row: the genre name plus the series in it. */
|
||||
export interface GenreRow {
|
||||
@@ -45,36 +46,11 @@ function createTvStore() {
|
||||
|
||||
const { subscribe, set, update } = writable<TvState>(initialState);
|
||||
|
||||
/**
|
||||
* Build the hero rotation. Prefer in-progress episodes (most personal),
|
||||
* then fall back to next-up, then recently added. De-duplicates by id and
|
||||
* prefers items that carry backdrop/primary artwork for a good banner.
|
||||
*/
|
||||
function buildHero(
|
||||
continueWatching: MediaItem[],
|
||||
nextUp: MediaItem[],
|
||||
recentlyAdded: MediaItem[]
|
||||
): MediaItem[] {
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!(i.backdropImageTags && i.backdropImageTags.length > 0) ||
|
||||
!!(i.parentBackdropImageTags && i.parentBackdropImageTags.length > 0) ||
|
||||
!!i.primaryImageTag;
|
||||
|
||||
const result: MediaItem[] = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
for (const pool of [continueWatching, nextUp, recentlyAdded]) {
|
||||
for (const item of pool) {
|
||||
if (result.length >= 6) break;
|
||||
if (hasArt(item) && !seen.has(item.id)) {
|
||||
seen.add(item.id);
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.slice(0, 6);
|
||||
}
|
||||
/** Artwork check for hero candidates: own/parent backdrop or primary image. */
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!(i.backdropImageTags && i.backdropImageTags.length > 0) ||
|
||||
!!(i.parentBackdropImageTags && i.parentBackdropImageTags.length > 0) ||
|
||||
!!i.primaryImageTag;
|
||||
|
||||
async function loadSections(libraryId: string) {
|
||||
update(s => ({
|
||||
@@ -86,17 +62,30 @@ function createTvStore() {
|
||||
try {
|
||||
const repo = auth.getRepository();
|
||||
|
||||
const [resume, nextUp, latest] = await Promise.all([
|
||||
const [resume, nextUp, latest, surprise] = await Promise.all([
|
||||
repo.getResumeItems(libraryId, SECTION_LIMIT),
|
||||
repo.getNextUpEpisodes(undefined, SECTION_LIMIT),
|
||||
repo.getLatestItems(libraryId, SECTION_LIMIT),
|
||||
// Random pool so the hero rotation changes between visits (SortBy=Random
|
||||
// shuffles server-side online, and via SQLite RANDOM() offline).
|
||||
repo
|
||||
.getItems(libraryId, {
|
||||
includeItemTypes: ["Series"],
|
||||
sortBy: "Random",
|
||||
recursive: true,
|
||||
limit: SECTION_LIMIT,
|
||||
})
|
||||
.then(r => r.items)
|
||||
.catch(() => [] as MediaItem[]),
|
||||
]);
|
||||
|
||||
// Resume items are already video-only from the server, but keep episodes
|
||||
// (and the occasional movie that lives in a mixed library) defensively.
|
||||
const continueWatching = resume.filter(i => i.type === "Episode" || i.type === "Movie");
|
||||
|
||||
const heroItems = buildHero(continueWatching, nextUp, latest);
|
||||
// Mix the hero: in-progress episodes first (most personal), then next-up,
|
||||
// recent additions, and random series from across the library.
|
||||
const heroItems = buildHeroMix([continueWatching, nextUp, latest, surprise], hasArt);
|
||||
|
||||
update(s => ({
|
||||
...s,
|
||||
|
||||
Reference in New Issue
Block a user