jellyfin panel app: browse, detail and player

adds the /jellyfin screen and its two panels (nav + view) on top of the
jellyfin sidecar, following the photos/invoiceshelf shape.

the transcode path is a progressive mp4 rather than hls, so no hls.js
dependency is added under the frozen-install rule. that stream has no
length and no byte ranges, so the player owns its own scrubber and seeks
by re-negotiating at a new startTimeTicks, tracking offset + currentTime;
a direct file keeps native controls. the hls url is still returned, so
switching later is a player change only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 18:16:45 +00:00
co-authored by Claude Opus 5
parent 904edefd62
commit a894d64cb3
27 changed files with 2206 additions and 16 deletions
@@ -141,6 +141,7 @@ import {
Images,
CalendarDays,
Contact,
Clapperboard,
} from 'lucide-react';
export const ALL_DOCK_ITEMS: DockItem[] = [
@@ -152,6 +153,7 @@ export const ALL_DOCK_ITEMS: DockItem[] = [
{ label: 'Chat', to: '/chat', icon: MessageCircle, color: '#60a5fa' },
{ label: 'Music', to: '/music', icon: Music, color: '#22c55e' },
{ label: 'Photos', to: '/photos', icon: Images, color: '#10b981' },
{ label: 'Video', to: '/jellyfin', icon: Clapperboard, color: '#a855f7' },
{ label: 'Soulseek', to: '/soulseek', image: '/slskd.png', color: '#ffffff' },
{ label: 'Headscale', to: '/headscale', icon: Network, color: '#818cf8' },
{ label: 'Transmission', to: '/transmission', icon: ArrowDownUp, color: '#e11d48' },