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:
+20
-29
@@ -6,6 +6,7 @@ import type { MediaItem, Genre } from "$lib/api/types";
|
||||
import { auth } from "./auth";
|
||||
import { excludePodcasts } from "$lib/utils/podcastFilter";
|
||||
import { selectDiverseGenres, sampleAcross } from "$lib/utils/genreDiversity";
|
||||
import { buildHeroMix } from "$lib/utils/heroMix";
|
||||
|
||||
/** A single "by genre" row: the genre name plus the albums in it. */
|
||||
export interface GenreRow {
|
||||
@@ -52,33 +53,9 @@ function createMusicStore() {
|
||||
|
||||
const { subscribe, set, update } = writable<MusicState>(initialState);
|
||||
|
||||
/**
|
||||
* Build the hero rotation from a mix of recently played and rediscover
|
||||
* albums, interleaved so the banner alternates "fresh in your ears" with
|
||||
* "remember this?". De-duplicates by id and prefers items that have artwork.
|
||||
*/
|
||||
function buildHero(recent: MediaItem[], rediscover: MediaItem[]): MediaItem[] {
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!i.primaryImageTag || !!(i.backdropImageTags && i.backdropImageTags.length > 0);
|
||||
|
||||
const recentPool = recent.filter(hasArt);
|
||||
const rediscoverPool = rediscover.filter(hasArt);
|
||||
|
||||
const result: MediaItem[] = [];
|
||||
const seen = new Set<string>();
|
||||
const maxLen = Math.max(recentPool.length, rediscoverPool.length);
|
||||
|
||||
for (let i = 0; i < maxLen && result.length < 6; i++) {
|
||||
for (const candidate of [recentPool[i], rediscoverPool[i]]) {
|
||||
if (candidate && !seen.has(candidate.id)) {
|
||||
seen.add(candidate.id);
|
||||
result.push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.slice(0, 6);
|
||||
}
|
||||
/** Artwork check for hero candidates: needs a primary image or backdrop. */
|
||||
const hasArt = (i: MediaItem) =>
|
||||
!!i.primaryImageTag || !!(i.backdropImageTags && i.backdropImageTags.length > 0);
|
||||
|
||||
async function loadSections(libraryId: string) {
|
||||
update(s => ({
|
||||
@@ -90,7 +67,7 @@ function createMusicStore() {
|
||||
try {
|
||||
const repo = auth.getRepository();
|
||||
|
||||
const [recentlyPlayed, newlyAdded, playlistsResult, rediscover] = await Promise.all([
|
||||
const [recentlyPlayed, newlyAdded, playlistsResult, rediscover, surprise] = await Promise.all([
|
||||
repo.getRecentlyPlayedAudio(SECTION_LIMIT),
|
||||
repo.getItems(libraryId, {
|
||||
includeItemTypes: ["MusicAlbum"],
|
||||
@@ -107,6 +84,17 @@ function createMusicStore() {
|
||||
limit: SECTION_LIMIT,
|
||||
}),
|
||||
repo.getRediscoverAlbums(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: ["MusicAlbum"],
|
||||
sortBy: "Random",
|
||||
recursive: true,
|
||||
limit: SECTION_LIMIT,
|
||||
})
|
||||
.then(r => r.items)
|
||||
.catch(() => [] as MediaItem[]),
|
||||
]);
|
||||
|
||||
// HACK: drop the "Podcasts" folder that lives inside the music library.
|
||||
@@ -114,8 +102,11 @@ function createMusicStore() {
|
||||
const newlyAddedAlbums = excludePodcasts(newlyAdded.items);
|
||||
const playlistItems = excludePodcasts(playlistsResult.items);
|
||||
const rediscoverAlbums = excludePodcasts(rediscover);
|
||||
const surpriseAlbums = excludePodcasts(surprise);
|
||||
|
||||
const heroItems = buildHero(recentlyPlayedAlbums, rediscoverAlbums);
|
||||
// Mix the hero: fresh-in-your-ears first, then "remember this?", then
|
||||
// random albums from across the library.
|
||||
const heroItems = buildHeroMix([recentlyPlayedAlbums, rediscoverAlbums, surpriseAlbums], hasArt);
|
||||
|
||||
update(s => ({
|
||||
...s,
|
||||
|
||||
Reference in New Issue
Block a user