feat(library): genre sliders, artist links, and navigation utils
- music landing: diverse per-genre album sliders (online counts / offline wide-probe fallback) and home-screen library shortcuts - add ArtistLinks component and shared navigation/genreDiversity utils - player/playback-mode refinements across Rust and frontend
This commit is contained in:
+49
-1
@@ -4,11 +4,13 @@
|
||||
import { platform } from "@tauri-apps/plugin-os";
|
||||
import { auth, isAuthenticated } from "$lib/stores/auth";
|
||||
import { home } from "$lib/stores/home";
|
||||
import { library, libraries } from "$lib/stores/library";
|
||||
import { isServerReachable } from "$lib/stores/connectivity";
|
||||
import { currentMedia } from "$lib/stores/player";
|
||||
import HeroBanner from "$lib/components/home/HeroBanner.svelte";
|
||||
import Carousel from "$lib/components/home/Carousel.svelte";
|
||||
import type { MediaItem } from "$lib/api/types";
|
||||
import MediaCard from "$lib/components/library/MediaCard.svelte";
|
||||
import type { MediaItem, Library } from "$lib/api/types";
|
||||
|
||||
// Track if we've done an initial load (plain variable, not reactive)
|
||||
let hasLoadedOnce = false;
|
||||
@@ -34,6 +36,9 @@
|
||||
|
||||
if ($isAuthenticated) {
|
||||
await home.loadHomeSections();
|
||||
if ($libraries.length === 0) {
|
||||
await library.loadLibraries();
|
||||
}
|
||||
hasLoadedOnce = true;
|
||||
}
|
||||
});
|
||||
@@ -68,6 +73,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Playlist libraries live inside the Music landing page, not as top-level shortcuts.
|
||||
const shortcutLibraries = $derived(
|
||||
$libraries.filter((lib) => lib.collectionType !== "playlists")
|
||||
);
|
||||
|
||||
function handleLibraryClick(lib: Library) {
|
||||
// Mirror /library routing: dedicated landing pages need currentLibrary set.
|
||||
library.setCurrentLibrary(lib);
|
||||
switch (lib.collectionType) {
|
||||
case "music":
|
||||
goto("/library/music");
|
||||
break;
|
||||
case "tvshows":
|
||||
goto("/library/tv");
|
||||
break;
|
||||
case "movies":
|
||||
goto("/library/movies");
|
||||
break;
|
||||
default:
|
||||
library.clearGenres();
|
||||
goto("/library");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const heroItems = $derived($home.heroItems);
|
||||
const resumeItems = $derived($home.resumeItems.filter(
|
||||
i => i.type === "Movie" || i.type === "Episode"
|
||||
@@ -92,6 +122,24 @@
|
||||
<HeroBanner items={heroItems} />
|
||||
{/if}
|
||||
|
||||
<!-- Your Libraries: quick jump into each dedicated landing page -->
|
||||
{#if shortcutLibraries.length > 0}
|
||||
<div>
|
||||
<h2 class="text-xl font-bold text-white mb-4 px-4">Your Libraries</h2>
|
||||
<div class="flex gap-4 overflow-x-auto px-4 pb-2">
|
||||
{#each shortcutLibraries as lib (lib.id)}
|
||||
<div class="flex-shrink-0">
|
||||
<MediaCard
|
||||
item={lib}
|
||||
size="medium"
|
||||
onclick={() => handleLibraryClick(lib)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Next Movie -->
|
||||
{#if resumeMovies.length > 0}
|
||||
<Carousel
|
||||
|
||||
Reference in New Issue
Block a user