diff --git a/src/app.css b/src/app.css index 18c8c1b..89027e2 100644 --- a/src/app.css +++ b/src/app.css @@ -90,6 +90,10 @@ html[data-useragent*="Tizen"] .selectable-secondary { @apply font-semibold text-2xl text-secondary-100; } +.header4 { + @apply font-semibold text-4xl text-secondary-100 tracking-wider; +} + @media tv { html { font-size: 24px; diff --git a/src/lib/components/VideoPlayer/JellyfinVideoPlayerModal.svelte b/src/lib/components/VideoPlayer/JellyfinVideoPlayerModal.svelte index d8456c9..1ac9a49 100644 --- a/src/lib/components/VideoPlayer/JellyfinVideoPlayerModal.svelte +++ b/src/lib/components/VideoPlayer/JellyfinVideoPlayerModal.svelte @@ -22,6 +22,17 @@ export let modalId: symbol; export let hidden: boolean = false; + const itemP = jellyfinApi.getLibraryItem(id); + + let title: string = ''; + let subtitle: string = ''; + itemP.then((item) => { + title = item?.Name || ''; + subtitle = `${item?.SeriesName || ''} S${item?.ParentIndexNumber || ''}E${ + item?.IndexNumber || '' + }`; + }); + let video: HTMLVideoElement; let paused: boolean; let progressTime: number; @@ -46,11 +57,9 @@ }; async function loadPlaybackInfo( - id: string, options: { audioStreamIndex?: number; bitrate?: number; playbackPosition?: number } = {} ) { - const item = await jellyfinApi.getLibraryItem(id); - + const item = await itemP; const mediaLanguagesStore = createLocalStorageStore( 'media-tracks-' + (item?.SeriesName || id), {} @@ -154,7 +163,7 @@ language: s.Language || '' })) || [], selectAudioTrack: (index: number) => - loadPlaybackInfo(id, { + loadPlaybackInfo({ ...options, audioStreamIndex: index, playbackPosition: progressTime * 10_000_000 @@ -179,7 +188,7 @@ }, 10_000); } - loadPlaybackInfo(id); + loadPlaybackInfo(); onDestroy(() => { if (reportProgressInterval) clearInterval(reportProgressInterval); @@ -197,6 +206,8 @@ (); let pausedBeforeSeeking = paused; @@ -31,49 +34,71 @@ dispatch('jumpTo', progressTime); } + + function handleNavigateEvent({ detail }: CustomEvent) { + if (detail.direction === 'left') { + dispatch('jumpTo', progressTime - 10); + detail.preventNavigation(); + } else if (detail.direction === 'right') { + dispatch('jumpTo', progressTime + 30); + detail.preventNavigation(); + } + } - -
+
+ dispatch('playPause')} + > +
- -
+ +
- -
+ +
-
+ /> - - + + +
+ {formatSecondsToTime(progressTime)} + -{formatSecondsToTime(totalTime - progressTime)} +
+
diff --git a/src/lib/components/VideoPlayer/VideoPlayer.svelte b/src/lib/components/VideoPlayer/VideoPlayer.svelte index 7cbd2a5..49782cf 100644 --- a/src/lib/components/VideoPlayer/VideoPlayer.svelte +++ b/src/lib/components/VideoPlayer/VideoPlayer.svelte @@ -15,6 +15,8 @@ export let playbackInfo: PlaybackInfo | undefined; export let subtitleInfo: SubtitleInfo | undefined; + export let title: string; + export let subtitle: string; export let modalHidden = false; @@ -121,12 +123,22 @@ bind:video bind:buffering /> + + +
- Title + {#if buffering || !videoDidLoad}
@@ -148,9 +160,12 @@ handleHideInterface(); } }} - class="flex justify-between p-2" + class="flex justify-between px-2 py-4 items-end" > -
+
+
{subtitle}
+

{title}

+
{ @@ -183,6 +198,10 @@ on:jumpTo={(e) => { video.currentTime = e.detail; }} + on:playPause={() => { + if (paused) video.play(); + else video.pause(); + }} bind:totalTime bind:progressTime bind:bufferedTime diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 484b9bb..736c838 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,5 +1,16 @@ import { type Readable, writable } from 'svelte/store'; +export function formatSecondsToTime(seconds: number) { + const days = Math.floor(seconds / 60 / 60 / 24); + const hours = Math.floor((seconds / 60 / 60) % 24); + const minutes = Math.floor((seconds / 60) % 60); + const secondsLeft = Math.floor(seconds % 60); + + return `${days > 0 ? days + ':' : ''}${hours > 0 ? hours + ':' : ''}${ + days > 0 || hours > 0 ? minutes.toString().padStart(2, '0') : minutes + }:${secondsLeft.toString().padStart(2, '0')}`; +} + export function formatMinutesToTime(minutes: number) { const days = Math.floor(minutes / 60 / 24); const hours = Math.floor((minutes / 60) % 24);