style: Redesign manage media ui
This commit is contained in:
@@ -28,7 +28,11 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Container class="fixed inset-0 z-20 bg-stone-950 overflow-y-auto" trapFocus direction="horizontal">
|
||||
<Container
|
||||
class="fixed inset-0 z-20 bg-secondary-800 overflow-y-auto"
|
||||
trapFocus
|
||||
direction="horizontal"
|
||||
>
|
||||
<Container />
|
||||
<Container on:navigate={handleGoToTop} on:back={handleGoToTop} focusOnMount>
|
||||
<slot {handleGoBack} registrar={selectable.registrar} />
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
export let urls: Promise<string[]>;
|
||||
export let index: number;
|
||||
export let hasFocus = true;
|
||||
export let hideInterface = false;
|
||||
let visibleIndex = -2;
|
||||
let visibleIndexTimeout: ReturnType<typeof setTimeout>;
|
||||
|
||||
@@ -75,7 +76,11 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="absolute inset-0 flex flex-col -z-10">
|
||||
<div class="h-screen bg-gradient-to-t from-secondary-500 to-transparent" />
|
||||
<div class="flex-1 bg-secondary-500" />
|
||||
<div
|
||||
class={classNames('absolute inset-0 flex flex-col -z-10 transition-opacity', {
|
||||
'opacity-0': hideInterface
|
||||
})}
|
||||
>
|
||||
<div class="h-screen bg-gradient-to-b from-transparent to-secondary-900" />
|
||||
<div class="flex-1 bg-secondary-900" />
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
import PageDots from '../HeroShowcase/PageDots.svelte';
|
||||
import type { Readable, Writable } from 'svelte/store';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let urls: Promise<string[]>;
|
||||
|
||||
export let index = 0;
|
||||
export let hideInterface = false;
|
||||
|
||||
let length = 0;
|
||||
|
||||
$: urls.then((urls) => (length = urls.length));
|
||||
@@ -68,8 +70,12 @@
|
||||
bind:hasFocusWithin
|
||||
bind:focusIndex
|
||||
>
|
||||
<HeroShowcaseBackground {urls} {index} hasFocus={backgroundHasFocus} />
|
||||
<div class="flex flex-1 z-10">
|
||||
<HeroShowcaseBackground {urls} {index} hasFocus={backgroundHasFocus} {hideInterface} />
|
||||
<div
|
||||
class={classNames('flex flex-1 z-10 transition-opacity', {
|
||||
'opacity-0': hideInterface
|
||||
})}
|
||||
>
|
||||
<slot />
|
||||
<div class="flex flex-col justify-end ml-4">
|
||||
<div class="flex flex-1 justify-end items-center">
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
import { formatSize } from '../../utils.js';
|
||||
import type { FileResource } from '../../apis/combined-types';
|
||||
import { scrollIntoView } from '../../selectable';
|
||||
import Container from '../../../Container.svelte';
|
||||
|
||||
export let files: Promise<FileResource[]>;
|
||||
export let handleSelectFile: (file: FileResource) => void;
|
||||
</script>
|
||||
|
||||
<Container class="flex flex-col -my-2">
|
||||
<div class="flex flex-col -my-2">
|
||||
{#await files}
|
||||
{#each new Array(5) as _, index}
|
||||
<div class="flex-1 my-2">
|
||||
@@ -47,4 +46,4 @@
|
||||
<div class="text-sm text-zinc-400">No local files found</div>
|
||||
{/each}
|
||||
{/await}
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
@@ -16,12 +16,19 @@
|
||||
}}
|
||||
focusOnMount
|
||||
trapFocus
|
||||
class={classNames('fixed inset-0 bg-stone-950/80 overflow-auto', {
|
||||
'opacity-0': hidden
|
||||
})}
|
||||
class={classNames(
|
||||
'fixed inset-0 overflow-x-hidden overflow-y-auto',
|
||||
{
|
||||
'opacity-0': hidden
|
||||
},
|
||||
// 'bg-[radial-gradient(169.40%_89.55%_at_94.76%_6.29%,rgba(0,0,0,0.40)_0%,rgba(255,255,255,0.00)_100%)]'
|
||||
// 'bg-[radial-gradient(150%_50%_at_50%_-25%,_#DFAA2BF0_0%,_#073AFF00_100%),linear-gradient(0deg,_#1A1914FF_0%,_#1A1914FF_0%)]'
|
||||
'bg-secondary-900'
|
||||
)}
|
||||
canFocusEmpty
|
||||
>
|
||||
<div class="mx-20 py-16">
|
||||
<slot />
|
||||
</div>
|
||||
<div
|
||||
class="absolute top-0 inset-x-0 h-screen -z-10 bg-[radial-gradient(150%_50%_at_50%_-25%,_#DFAA2Bcc_0%,_#00000000_100%)]"
|
||||
/>
|
||||
<slot />
|
||||
</Container>
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
import { type RadarrRelease } from '../../apis/radarr/radarr-api';
|
||||
import classNames from 'classnames';
|
||||
import { useRequest } from '../../stores/data.store';
|
||||
import Button from '../Button.svelte';
|
||||
import { ChevronRight, DotFilled } from 'radix-icons-svelte';
|
||||
import { formatMinutesToTime, formatSize } from '../../utils';
|
||||
import { derived } from 'svelte/store';
|
||||
import ButtonGhost from '../Ghosts/ButtonGhost.svelte';
|
||||
import type { SonarrRelease } from '../../apis/sonarr/sonarr-api';
|
||||
import Container from '../../../Container.svelte';
|
||||
import MMReleaseListRow from '../MediaManagerModal/MMReleaseListRow.svelte';
|
||||
import AnimateScale from '../AnimateScale.svelte';
|
||||
|
||||
type Release = RadarrRelease | SonarrRelease;
|
||||
|
||||
@@ -34,7 +33,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<Container class="flex flex-col -my-2">
|
||||
<table class="w-full border-spacing-y-2 border-spacing-x-2 border-separate -mx-8">
|
||||
{#if $isLoading}
|
||||
{#each new Array(5) as _, index}
|
||||
<div class="flex-1 my-2">
|
||||
@@ -42,81 +41,74 @@
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each (showAll ? $releases : $filteredReleases)?.filter((r) => r.guid && r.indexerId) || [] as release, index}
|
||||
<div class="flex-1 my-2">
|
||||
<Button
|
||||
on:clickOrSelect={() => selectRelease(release)}
|
||||
let:hasFocus
|
||||
focusOnMount={index === 0}
|
||||
>
|
||||
<div class="w-full flex">
|
||||
<div class="flex-1 flex flex-col mr-2">
|
||||
<div class="flex-1 flex items-center">
|
||||
<div class="tracking-wide mr-2">{release.indexer}</div>
|
||||
<div
|
||||
class={classNames('mr-2', {
|
||||
'text-zinc-400': !hasFocus,
|
||||
'text-zinc-700': hasFocus
|
||||
})}
|
||||
>
|
||||
{release?.quality?.quality?.name}
|
||||
</div>
|
||||
<div
|
||||
class={classNames('mr-2', {
|
||||
'text-zinc-400': !hasFocus,
|
||||
'text-zinc-700': hasFocus
|
||||
})}
|
||||
>
|
||||
{release.seeders} seeders
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if hasFocus}
|
||||
<div class="flex text-xs text-zinc-700 items-center flex-wrap mt-2">
|
||||
<div>
|
||||
{release.title}
|
||||
</div>
|
||||
<DotFilled size={15} />
|
||||
<div>{formatMinutesToTime(release.ageMinutes || 0)} old</div>
|
||||
<DotFilled size={15} />
|
||||
<div><b>{release.seeders} seeders</b> / {release.leechers} leechers</div>
|
||||
<DotFilled size={15} />
|
||||
{#if release.seeders}
|
||||
<div>
|
||||
{formatSize((release.size || 0) / release.seeders)} per seeder
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<thead>
|
||||
<Container tag="tr" direction="horizontal">
|
||||
<Container tag="th" let:hasFocus>
|
||||
<AnimateScale {hasFocus} class="ml-8">
|
||||
<div
|
||||
class={classNames('float-left rounded-full px-3 py-1', {
|
||||
'bg-primary-500 text-secondary-800': hasFocus
|
||||
})}
|
||||
>
|
||||
Title
|
||||
</div>
|
||||
{#if hasFocus}
|
||||
<div class="flex items-center">
|
||||
<ChevronRight size={32} />
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class={classNames({
|
||||
'text-zinc-400': !hasFocus,
|
||||
'text-zinc-700': hasFocus
|
||||
})}
|
||||
>
|
||||
{formatSize(release?.size || 0)}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
{/each}
|
||||
{#if !showAll && $releases?.length}
|
||||
<div class="my-1 w-full">
|
||||
<Button on:clickOrSelect={() => (showAll = true)}
|
||||
>Show all {$releases?.length} releases</Button
|
||||
>
|
||||
</div>
|
||||
{:else if showAll}
|
||||
<div class="my-1 w-full">
|
||||
<Button on:clickOrSelect={() => (showAll = false)}>Show less</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</AnimateScale>
|
||||
</Container>
|
||||
<Container tag="th" let:hasFocus>
|
||||
<AnimateScale {hasFocus}>
|
||||
<div
|
||||
class={classNames('float-left rounded-full px-3 py-1', {
|
||||
'bg-primary-500 text-secondary-800': hasFocus
|
||||
})}
|
||||
>
|
||||
Size
|
||||
</div>
|
||||
</AnimateScale>
|
||||
</Container>
|
||||
<Container tag="th" let:hasFocus>
|
||||
<AnimateScale {hasFocus}>
|
||||
<div
|
||||
class={classNames('float-left rounded-full px-3 py-1', {
|
||||
'bg-primary-500 text-secondary-800': hasFocus
|
||||
})}
|
||||
>
|
||||
Peers
|
||||
</div>
|
||||
</AnimateScale>
|
||||
</Container>
|
||||
<Container tag="th" let:hasFocus>
|
||||
<AnimateScale {hasFocus}>
|
||||
<div
|
||||
class={classNames('float-left rounded-full px-3 py-1', {
|
||||
'bg-primary-500 text-secondary-800': hasFocus
|
||||
})}
|
||||
>
|
||||
Quality
|
||||
</div>
|
||||
</AnimateScale>
|
||||
</Container>
|
||||
<th />
|
||||
</Container>
|
||||
</thead>
|
||||
<Container focusOnMount tag="tbody" class="">
|
||||
{#each $filteredReleases?.filter((r) => r.guid && r.indexerId) || [] as release, index}
|
||||
<MMReleaseListRow {release} />
|
||||
{/each}
|
||||
</Container>
|
||||
<h1 class="text-2xl font-semibold mb-4 mt-8 mx-8">All Releases</h1>
|
||||
<tbody class="divide-y divide-zinc-500">
|
||||
{#each $releases?.filter((r) => r.guid && r.indexerId) || [] as release, index}
|
||||
<MMReleaseListRow {release} />
|
||||
{/each}
|
||||
</tbody>
|
||||
{/if}
|
||||
</Container>
|
||||
</table>
|
||||
<!--{#if !showAll && $releases?.length}-->
|
||||
<!-- <div class="my-1 w-full">-->
|
||||
<!-- <Button on:clickOrSelect={() => (showAll = true)}>Show all {$releases?.length} releases</Button>-->
|
||||
<!-- </div>-->
|
||||
<!--{:else if showAll}-->
|
||||
<!-- <div class="my-1 w-full">-->
|
||||
<!-- <Button on:clickOrSelect={() => (showAll = false)}>Show less</Button>-->
|
||||
<!-- </div>-->
|
||||
<!--{/if}-->
|
||||
|
||||
@@ -1,31 +1,78 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import Container from '../../../Container.svelte';
|
||||
import classNames from 'classnames';
|
||||
|
||||
let activeTab: 'releases' | 'local-files' = 'releases';
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-16">
|
||||
<div class="text-4xl font-semibold">
|
||||
<slot name="title" />
|
||||
<div class="flex flex-col h-screen">
|
||||
<div class="flex items-center pb-8 mb-8 pt-16 px-20">
|
||||
<div class="flex-1">
|
||||
<div class="text-4xl font-semibold">
|
||||
<slot name="title" />
|
||||
</div>
|
||||
<div class="text-zinc-300 font-medium text-lg mt-2">
|
||||
<slot name="subtitle" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-zinc-300 font-medium text-lg mt-2">
|
||||
<slot name="subtitle" />
|
||||
<div class="mx-20">
|
||||
<h1 class="mb-2">Downloads</h1>
|
||||
<slot name="downloads" />
|
||||
</div>
|
||||
</div>
|
||||
<Container direction="horizontal" class="grid grid-cols-2 gap-16">
|
||||
<div class="flex flex-col">
|
||||
<h1 class="text-2xl font-semibold mb-4">Releases</h1>
|
||||
<div class="flex mb-8 mx-20">
|
||||
<h1
|
||||
class={classNames('text-2xl font-semibold mr-8 transition-opacity', {
|
||||
'opacity-40': activeTab !== 'releases'
|
||||
})}
|
||||
>
|
||||
Releases
|
||||
</h1>
|
||||
<h1
|
||||
class={classNames('text-2xl font-semibold mr-8 transition-opacity', {
|
||||
'opacity-40': activeTab !== 'local-files'
|
||||
})}
|
||||
>
|
||||
Local Files
|
||||
</h1>
|
||||
</div>
|
||||
<Container
|
||||
focusOnMount
|
||||
direction="horizontal"
|
||||
class="flex-1 grid grid-cols-1 overflow-y-auto overflow-x-hidden px-20 pb-16 scrollbar-hide"
|
||||
>
|
||||
<Container
|
||||
on:enter={() => (activeTab = 'releases')}
|
||||
class={classNames('transition-all row-start-1 col-start-1 px-6 -mx-6', {
|
||||
'opacity-50 -translate-x-full': activeTab !== 'releases'
|
||||
})}
|
||||
>
|
||||
<slot name="releases" />
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col mb-8">
|
||||
<h1 class="text-2xl font-semibold mb-4">Local Files</h1>
|
||||
<slot name="local-files" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col mb-8">
|
||||
<h1 class="text-2xl font-semibold mb-4">Downloads</h1>
|
||||
<slot name="downloads" />
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
<Container
|
||||
on:enter={() => (activeTab = 'local-files')}
|
||||
class={classNames('transition-all row-start-1 col-start-1 px-6 -mx-6', {
|
||||
'opacity-50 translate-x-full': activeTab !== 'local-files'
|
||||
})}
|
||||
>
|
||||
<slot name="local-files" />
|
||||
</Container>
|
||||
</Container>
|
||||
<!-- <Container direction="horizontal" class="grid grid-cols-1 gap-16">-->
|
||||
<!-- <div class="flex flex-col">-->
|
||||
<!-- <h1 class="text-2xl font-semibold mb-4">Releases</h1>-->
|
||||
<!-- <slot name="releases" />-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="flex flex-col">-->
|
||||
<!-- <div class="flex flex-col mb-8">-->
|
||||
<!-- <h1 class="text-2xl font-semibold mb-4">Local Files</h1>-->
|
||||
<!-- <slot name="local-files" />-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- <div class="flex flex-col mb-8">-->
|
||||
<!-- <h1 class="text-2xl font-semibold mb-4">Downloads</h1>-->
|
||||
<!-- <slot name="downloads" />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </Container>-->
|
||||
</div>
|
||||
|
||||
103
src/lib/components/MediaManagerModal/MMReleaseListRow.svelte
Normal file
103
src/lib/components/MediaManagerModal/MMReleaseListRow.svelte
Normal file
@@ -0,0 +1,103 @@
|
||||
<script lang="ts">
|
||||
import { formatMinutesToTime, formatSize } from '../../utils.js';
|
||||
import type { RadarrRelease } from '../../apis/radarr/radarr-api';
|
||||
import type { SonarrRelease } from '../../apis/sonarr/sonarr-api';
|
||||
import Container from '../../../Container.svelte';
|
||||
import classNames from 'classnames';
|
||||
import { scrollIntoView } from '../../selectable';
|
||||
import { Download } from 'radix-icons-svelte';
|
||||
import type { Readable } from 'svelte/store';
|
||||
export let release: RadarrRelease | SonarrRelease;
|
||||
|
||||
let hasFocusWithin: Readable<boolean>;
|
||||
</script>
|
||||
|
||||
<Container
|
||||
tag="tr"
|
||||
class={classNames('h-20 font-medium transition-transform px-4 py-2 rounded-lg relative', {
|
||||
// 'scale-[102%] bg-primary-500/10': $hasFocusWithin
|
||||
})}
|
||||
bind:hasFocusWithin
|
||||
on:enter={scrollIntoView({ vertical: 64 })}
|
||||
>
|
||||
<td class="pl-8">
|
||||
<!-- Background, has to be inside a td to not create another column -->
|
||||
<div
|
||||
class={classNames('absolute inset-0 -z-10 rounded-xl transition-colors', {
|
||||
'bg-secondary-800 border-primary-500 shadow-xl shadow-secondary-900': $hasFocusWithin,
|
||||
'bg-transparent border-transparent': !$hasFocusWithin
|
||||
})}
|
||||
/>
|
||||
|
||||
<h2 class="text-sm font-medium text-zinc-300 mb-1">
|
||||
{formatMinutesToTime(release.ageMinutes || 0)} ago
|
||||
</h2>
|
||||
<h1 class="font-medium text-lg">{release.title}</h1></td
|
||||
>
|
||||
<td class="text-zinc-300">
|
||||
{formatSize(release.size || 0)}
|
||||
</td>
|
||||
<td class="text-zinc-300">
|
||||
<div
|
||||
class="px-3 py-1 rounded bg-secondary-700 flex items-center justify-center float-left text-sm"
|
||||
>
|
||||
{release.seeders} / {release.leechers}
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-zinc-300">
|
||||
<div
|
||||
class="px-3 py-1 rounded bg-secondary-700 flex items-center justify-center float-left text-sm"
|
||||
>
|
||||
{release.quality?.quality?.name}
|
||||
</div>
|
||||
</td>
|
||||
<td class="">
|
||||
<!-- <Container let:hasFocus on:enter={scrollIntoView({ vertical: 64 })}>-->
|
||||
<!-- <div-->
|
||||
<!-- class={classNames(-->
|
||||
<!-- 'border-2 rounded-2xl p-1 cursor-pointer font-medium tracking-wide transition-colors',-->
|
||||
<!-- {-->
|
||||
<!-- 'border-zinc-300': !hasFocus,-->
|
||||
<!-- 'border-primary-500': hasFocus-->
|
||||
<!-- }-->
|
||||
<!-- )}-->
|
||||
<!-- >-->
|
||||
<!-- <div-->
|
||||
<!-- class={classNames(-->
|
||||
<!-- 'px-4 py-2 rounded-xl flex items-center justify-center transition-colors',-->
|
||||
<!-- {-->
|
||||
<!-- 'bg-primary-500 text-secondary-800': hasFocus,-->
|
||||
<!-- 'bg-transparent': !hasFocus-->
|
||||
<!-- }-->
|
||||
<!-- )}-->
|
||||
<!-- >-->
|
||||
<!-- Download-->
|
||||
<!-- <Download class="ml-2" size={19} />-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </Container>-->
|
||||
<Container let:hasFocus class="pr-8">
|
||||
<div
|
||||
class={classNames(
|
||||
'border-2 rounded-2xl p-1 cursor-pointer font-medium tracking-wide transition-colors',
|
||||
{
|
||||
'border-zinc-400': !hasFocus,
|
||||
'border-primary-500': hasFocus
|
||||
}
|
||||
)}
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'px-2 py-2 rounded-xl flex items-center justify-center transition-colors',
|
||||
{
|
||||
'bg-primary-500 text-secondary-800': hasFocus,
|
||||
'bg-transparent': !hasFocus
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Download size={19} />
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</td>
|
||||
</Container>
|
||||
@@ -17,7 +17,7 @@
|
||||
<AnimateScale hasFocus={$hasFocus}>
|
||||
<Container
|
||||
class={classNames(
|
||||
'flex flex-col justify-start rounded-xl overflow-hidden relative shadow-lg shrink-0 selectable hover:text-inherit hover:bg-stone-800 focus-visible:bg-stone-800 bg-stone-900 group text-left',
|
||||
'flex flex-col justify-start rounded-xl overflow-hidden relative shadow-lg shrink-0 selectable hover:text-inherit hover:bg-stone-800 focus-visible:bg-stone-800 bg-secondary-800 group text-left',
|
||||
{
|
||||
'w-56 h-80': size === 'md',
|
||||
'h-52': size === 'lg',
|
||||
|
||||
@@ -44,15 +44,13 @@
|
||||
($items || []).find((i) => i.UserData?.Played === false)
|
||||
);
|
||||
|
||||
const { send: addSeriesToSonarr, isFetching: addSeriesToSonarrFetching } = useActionRequest(
|
||||
sonarrApi.addSeriesToSonarr
|
||||
);
|
||||
|
||||
let selectedTmdbEpisode: TmdbSeasonEpisode | undefined;
|
||||
let hideInterface = false;
|
||||
const episodeCards = useRegistrar();
|
||||
|
||||
let scrollTop: number;
|
||||
$: showEpisodeInfo = false; // scrollTop > 140;
|
||||
|
||||
modalStack.top.subscribe((modal) => {
|
||||
hideInterface = !!modal;
|
||||
});
|
||||
</script>
|
||||
|
||||
<DetachedPage let:handleGoBack let:registrar>
|
||||
@@ -76,52 +74,22 @@
|
||||
?.map((i) => TMDB_IMAGES_ORIGINAL + i.file_path)
|
||||
.slice(0, 5) || []
|
||||
)}
|
||||
{hideInterface}
|
||||
>
|
||||
<Container />
|
||||
<div class="h-full flex-1 flex flex-col justify-end">
|
||||
{#await $tmdbSeries then series}
|
||||
{#if showEpisodeInfo && selectedTmdbEpisode}
|
||||
{@const episode = selectedTmdbEpisode}
|
||||
<div
|
||||
class={classNames(
|
||||
'text-left font-medium tracking-wider text-stone-200 hover:text-amber-200 mt-2',
|
||||
{
|
||||
'text-4xl sm:text-5xl 2xl:text-6xl': episode.name?.length || 0 < 15,
|
||||
'text-3xl sm:text-4xl 2xl:text-5xl': episode?.name?.length || 0 >= 15
|
||||
}
|
||||
)}
|
||||
>
|
||||
{episode.name}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-1 uppercase text-zinc-300 font-semibold tracking-wider mt-2 text-lg"
|
||||
>
|
||||
<p class="flex-shrink-0">
|
||||
{episode.runtime} Minutes
|
||||
</p>
|
||||
<!-- <DotFilled />
|
||||
<p class="flex-shrink-0">{movie.runtime}</p> -->
|
||||
<DotFilled />
|
||||
<p class="flex-shrink-0">
|
||||
<a href={`https://www.themoviedb.org/movie/${series?.id}/episode/${episode.id}`}
|
||||
>{episode.vote_average?.toFixed(1)} TMDB</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-stone-300 font-medium line-clamp-3 opacity-75 max-w-4xl mt-4">
|
||||
{episode.overview}
|
||||
</div>
|
||||
{:else if series}
|
||||
{#if series}
|
||||
<div
|
||||
class={classNames(
|
||||
'text-left font-medium tracking-wider text-stone-200 hover:text-amber-200 mt-2',
|
||||
{
|
||||
'text-4xl sm:text-5xl 2xl:text-6xl': series.name?.length || 0 < 15,
|
||||
'text-3xl sm:text-4xl 2xl:text-5xl': series?.name?.length || 0 >= 15
|
||||
'text-3xl sm:text-4xl 2xl:text-5xl': series.name?.length || 0 >= 15
|
||||
}
|
||||
)}
|
||||
>
|
||||
{series?.name}
|
||||
{series.name}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-1 uppercase text-zinc-300 font-semibold tracking-wider mt-2 text-lg"
|
||||
@@ -195,64 +163,70 @@
|
||||
</div>
|
||||
</HeroCarousel>
|
||||
</Container>
|
||||
<EpisodeGrid
|
||||
on:enter={scrollIntoView({ top: 32 })}
|
||||
id={Number(id)}
|
||||
tmdbSeries={tmdbSeriesData}
|
||||
{jellyfinEpisodes}
|
||||
currentJellyfinEpisode={nextJellyfinEpisode}
|
||||
on:mount={episodeCards.registrar}
|
||||
/>
|
||||
<Container on:enter={scrollIntoView({ top: 0 })} class="pt-8">
|
||||
{#await $tmdbSeries then series}
|
||||
<Carousel scrollClass="px-20" class="mb-8">
|
||||
<div slot="header">Show Cast</div>
|
||||
{#each series?.aggregate_credits?.cast?.slice(0, 15) || [] as credit}
|
||||
<TmdbPersonCard
|
||||
on:enter={scrollIntoView({ horizontal: 64 + 30 })}
|
||||
tmdbCredit={credit}
|
||||
/>
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
{#await $recommendations then recommendations}
|
||||
<Carousel scrollClass="px-20" class="mb-8">
|
||||
<div slot="header">Recommendations</div>
|
||||
{#each recommendations || [] as recommendation}
|
||||
<TmdbCard item={recommendation} on:enter={scrollIntoView({ horizontal: 64 + 30 })} />
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
</Container>
|
||||
{#await $tmdbSeries then series}
|
||||
<Container class="flex-1 bg-secondary-950 pt-8 px-20" on:enter={scrollIntoView({ top: 0 })}>
|
||||
<h1 class="font-medium tracking-wide text-2xl text-zinc-300 mb-8">More Information</h1>
|
||||
<div class="text-zinc-300 font-medium text-lg flex flex-wrap">
|
||||
<div class="flex-1">
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Created By</h2>
|
||||
{#each series?.created_by || [] as creator}
|
||||
<div>{creator.name}</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Network</h2>
|
||||
<div>{series?.networks?.[0]?.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Language</h2>
|
||||
<div>{series?.spoken_languages?.[0]?.name}</div>
|
||||
</div>
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Last Air Date</h2>
|
||||
<div>{series?.last_air_date}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class={classNames('transition-opacity', {
|
||||
'opacity-0': hideInterface
|
||||
})}
|
||||
>
|
||||
<EpisodeGrid
|
||||
on:enter={scrollIntoView({ top: 32 })}
|
||||
id={Number(id)}
|
||||
tmdbSeries={tmdbSeriesData}
|
||||
{jellyfinEpisodes}
|
||||
currentJellyfinEpisode={nextJellyfinEpisode}
|
||||
on:mount={episodeCards.registrar}
|
||||
/>
|
||||
<Container on:enter={scrollIntoView({ top: 0 })} class="pt-8">
|
||||
{#await $tmdbSeries then series}
|
||||
<Carousel scrollClass="px-20" class="mb-8">
|
||||
<div slot="header">Show Cast</div>
|
||||
{#each series?.aggregate_credits?.cast?.slice(0, 15) || [] as credit}
|
||||
<TmdbPersonCard
|
||||
on:enter={scrollIntoView({ horizontal: 64 + 30 })}
|
||||
tmdbCredit={credit}
|
||||
/>
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
{#await $recommendations then recommendations}
|
||||
<Carousel scrollClass="px-20" class="mb-8">
|
||||
<div slot="header">Recommendations</div>
|
||||
{#each recommendations || [] as recommendation}
|
||||
<TmdbCard item={recommendation} on:enter={scrollIntoView({ horizontal: 64 + 30 })} />
|
||||
{/each}
|
||||
</Carousel>
|
||||
{/await}
|
||||
</Container>
|
||||
{/await}
|
||||
{#await $tmdbSeries then series}
|
||||
<Container class="flex-1 bg-secondary-950 pt-8 px-20" on:enter={scrollIntoView({ top: 0 })}>
|
||||
<h1 class="font-medium tracking-wide text-2xl text-zinc-300 mb-8">More Information</h1>
|
||||
<div class="text-zinc-300 font-medium text-lg flex flex-wrap">
|
||||
<div class="flex-1">
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Created By</h2>
|
||||
{#each series?.created_by || [] as creator}
|
||||
<div>{creator.name}</div>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Network</h2>
|
||||
<div>{series?.networks?.[0]?.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Language</h2>
|
||||
<div>{series?.spoken_languages?.[0]?.name}</div>
|
||||
</div>
|
||||
<div class="border-l-2 border-zinc-300 pl-4 mb-8">
|
||||
<h2 class="uppercase text-sm font-semibold text-zinc-500 mb-0.5">Last Air Date</h2>
|
||||
<div>{series?.last_air_date}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
</DetachedPage>
|
||||
|
||||
|
||||
@@ -20,30 +20,30 @@ export default {
|
||||
'highlight-foreground': '#f6c304',
|
||||
'highlight-background': '#161517',
|
||||
primary: {
|
||||
50: '#FDF8EC',
|
||||
100: '#FBEED5',
|
||||
200: '#F7DEAB',
|
||||
300: '#F3CD81',
|
||||
400: '#EFBC57',
|
||||
500: '#EBAB2E',
|
||||
600: '#CD8F14',
|
||||
700: '#9A6B0F',
|
||||
800: '#66480A',
|
||||
900: '#332405',
|
||||
950: '#1C1403'
|
||||
50: 'hsl(40, 80%, 95%)', //''#fcf9ea',
|
||||
100: 'hsl(40, 80%, 90%)', //''#faefc7',
|
||||
200: 'hsl(40, 80%, 80%)', //''#f6dc92',
|
||||
300: 'hsl(40, 80%, 70%)', //''#f0c254',
|
||||
400: 'hsl(40, 80%, 65%)', //''#ebab2e',
|
||||
500: 'hsl(40, 80%, 55%)', //'#da9018',
|
||||
600: 'hsl(40, 80%, 24%)', //'#bc6e12',
|
||||
700: 'hsl(40, 80%, 18%)', //'#964e12',
|
||||
800: 'hsl(40, 80%, 12%)', //'#7d3f16',
|
||||
900: 'hsl(40, 80%, 7%)', //'#6a3419',
|
||||
950: 'hsl(40, 80%, 4%)' //'#3e1a0a'
|
||||
},
|
||||
secondary: {
|
||||
50: '#E6EAEA',
|
||||
100: '#CCD6D6',
|
||||
200: '#99ADAD',
|
||||
300: '#698282',
|
||||
400: '#3E4C4C',
|
||||
500: '#0a0807',
|
||||
600: '#101414',
|
||||
700: '#211a17',
|
||||
800: '#171310',
|
||||
900: '#0a0807',
|
||||
950: '#020303'
|
||||
50: 'hsl(40, 12%, 95%)',
|
||||
100: 'hsl(40, 12%, 90%)',
|
||||
200: 'hsl(40, 12%, 80%)',
|
||||
300: 'hsl(40, 12%, 70%)',
|
||||
400: 'hsl(40, 12%, 65%)',
|
||||
500: 'hsl(40, 12%, 55%)', // #0a0807
|
||||
600: 'hsl(40, 8%, 30%)',
|
||||
700: 'hsl(40, 8%, 20%)',
|
||||
800: 'hsl(40, 8%, 12%)', //'#1a1814', //'#171310',
|
||||
900: 'hsl(40, 8%, 7%)', //'#14130f',
|
||||
950: 'hsl(40, 8%, 4%)' //'#020303'
|
||||
}
|
||||
},
|
||||
keyframes: {
|
||||
|
||||
Reference in New Issue
Block a user