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:
+19
-26
@@ -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 movies in it. */
|
||||
export interface GenreRow {
|
||||
@@ -42,30 +43,9 @@ function createMoviesStore() {
|
||||
|
||||
const { subscribe, set, update } = writable<MoviesState>(initialState);
|
||||
|
||||
/**
|
||||
* Build the hero rotation. Prefer in-progress movies (most personal), then
|
||||
* fall back to recently added. De-duplicates by id and prefers items that
|
||||
* carry backdrop/primary artwork for a good banner.
|
||||
*/
|
||||
function buildHero(continueWatching: MediaItem[], recentlyAdded: MediaItem[]): MediaItem[] {
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!(i.backdropImageTags && i.backdropImageTags.length > 0) || !!i.primaryImageTag;
|
||||
|
||||
const result: MediaItem[] = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
for (const pool of [continueWatching, 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: needs a backdrop or a primary image. */
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!(i.backdropImageTags && i.backdropImageTags.length > 0) || !!i.primaryImageTag;
|
||||
|
||||
async function loadSections(libraryId: string) {
|
||||
update(s => ({
|
||||
@@ -77,12 +57,25 @@ function createMoviesStore() {
|
||||
try {
|
||||
const repo = auth.getRepository();
|
||||
|
||||
const [resume, latest] = await Promise.all([
|
||||
const [resume, latest, surprise] = await Promise.all([
|
||||
repo.getResumeMovies(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: ["Movie"],
|
||||
sortBy: "Random",
|
||||
recursive: true,
|
||||
limit: SECTION_LIMIT,
|
||||
})
|
||||
.then(r => r.items)
|
||||
.catch(() => [] as MediaItem[]),
|
||||
]);
|
||||
|
||||
const heroItems = buildHero(resume, latest);
|
||||
// Mix the hero: in-progress movies first (most personal), then recent
|
||||
// additions, then random picks from across the library.
|
||||
const heroItems = buildHeroMix([resume, latest, surprise], hasArt);
|
||||
|
||||
update(s => ({
|
||||
...s,
|
||||
|
||||
Reference in New Issue
Block a user