feat: Improved poster styles and image loading

This commit is contained in:
Aleksi Lassila
2023-08-30 00:36:31 +03:00
parent 81e3883485
commit bddeab7e35
7 changed files with 74 additions and 35 deletions

View File

@@ -285,11 +285,11 @@ export const getJellyfinUsers = async (
.then((res) => res.data || [])
.catch(() => []);
export const getJellyfinPosterUrl = (item: JellyfinItem, quality = 100) =>
export const getJellyfinPosterUrl = (item: JellyfinItem, quality = 100, original = false) =>
item.ImageTags?.Primary
? `${get(settings).jellyfin.baseUrl}/Items/${item?.Id}/Images/Primary?quality=${quality}&tag=${
item?.ImageTags?.Primary
}`
? `${get(settings).jellyfin.baseUrl}/Items/${item?.Id}/Images/Primary?quality=${quality}${
original ? '' : '&fillWidth=432'
}&tag=${item?.ImageTags?.Primary}`
: '';
export const getJellyfinBackdrop = (item: JellyfinItem, quality = 100) => {

View File

@@ -223,8 +223,11 @@ export const getRadarrQualityProfiles = async (
)
.then((res) => res.data || []);
export function getRadarrPosterUrl(item: RadarrMovie) {
return (
get(settings).radarr.baseUrl + (item.images?.find((i) => i.coverType === 'poster')?.url || '')
);
export function getRadarrPosterUrl(item: RadarrMovie, original = false) {
const url =
get(settings).radarr.baseUrl + (item.images?.find((i) => i.coverType === 'poster')?.url || '');
if (!original) return url.replace('poster.jpg', `poster-${500}.jpg`);
return url;
}

View File

@@ -307,8 +307,11 @@ export const getSonarrLanguageProfiles = async (
)
.then((res) => res.data || []);
export function getSonarrPosterUrl(item: SonarrSeries) {
return (
get(settings).sonarr.baseUrl + (item.images?.find((i) => i.coverType === 'poster')?.url || '')
);
export function getSonarrPosterUrl(item: SonarrSeries, original = false) {
const url =
get(settings).sonarr.baseUrl + (item.images?.find((i) => i.coverType === 'poster')?.url || '');
if (!original) return url.replace('poster.jpg', `poster-${500}.jpg`);
return url;
}

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import classNames from 'classnames';
export let src: string;
export let alt: string = '';
let loaded = false;
function handleLoad() {
loaded = true;
}
</script>
<img
{src}
{alt}
class={classNames(
'transition-opacity',
{
'opacity-0': !loaded,
'opacity-100': loaded
},
$$restProps.class
)}
style="object-fit: cover; width: 100%; height: 100%;"
loading="lazy"
on:load={handleLoad}
/>

View File

@@ -4,6 +4,7 @@
import PlayButton from '../PlayButton.svelte';
import ProgressBar from '../ProgressBar.svelte';
import { playerState } from '../VideoPlayer/VideoPlayer';
import LazyImg from '../LazyImg.svelte';
export let tmdbId: number | undefined = undefined;
export let tvdbId: number | undefined = undefined;
@@ -21,22 +22,20 @@
<a
href={tmdbId || tvdbId ? `/${type}/${tmdbId || tvdbId}` : '#'}
style={"background-image: url('" + backdropUrl + "');"}
class={classNames(
'relative flex shadow-lg rounded-lg aspect-[2/3] bg-center bg-cover w-44 selectable group hover:text-inherit flex-shrink-0',
'relative flex shadow-lg rounded-xl aspect-[2/3] w-44 selectable group hover:text-inherit flex-shrink-0 overflow-hidden',
{
'w-44': size === 'md',
'w-full': size === 'dynamic'
}
)}
>
<LazyImg src={backdropUrl} class="absolute inset-0 group-hover:scale-105 transition-transform" />
<div
class={classNames(
'flex-1 flex flex-col justify-between bg-darken opacity-0 group-hover:opacity-100 transition-opacity',
'flex-1 flex flex-col justify-between bg-darken opacity-0 group-hover:opacity-100 transition-opacity z-[1]',
{
'py-2 px-3': true
// 'pb-4': progress,
// 'pb-2': !progress
}
)}
>
@@ -60,21 +59,23 @@
</slot>
</div>
</div>
<div
class="absolute inset-0 bg-gradient-to-t from-darken group-hover:opacity-0 transition-opacity"
/>
<div class="absolute inset-0 flex items-center justify-center">
<PlayButton
on:click={(e) => {
e.preventDefault();
jellyfinId && playerState.streamJellyfinId(jellyfinId);
}}
class="sm:opacity-0 group-hover:opacity-100 transition-opacity"
/>
</div>
<!-- <div
class="absolute inset-0 bg-gradient-to-t from-darken group-hover:opacity-0 transition-opacity z-[1]"
/> -->
{#if jellyfinId}
<div class="absolute inset-0 flex items-center justify-center z-[1]">
<PlayButton
on:click={(e) => {
e.preventDefault();
jellyfinId && playerState.streamJellyfinId(jellyfinId);
}}
class="sm:opacity-0 group-hover:opacity-100 transition-opacity"
/>
</div>
{/if}
{#if progress}
<div
class="absolute bottom-2 lg:bottom-3 inset-x-2 lg:inset-x-3 group-hover:opacity-0 transition-opacity bg-gradient-to-t ease-in-out"
class="absolute bottom-2 lg:bottom-3 inset-x-2 lg:inset-x-3 group-hover:opacity-0 transition-opacity bg-gradient-to-t ease-in-out z-[1]"
>
<ProgressBar {progress} />
</div>

View File

@@ -16,6 +16,7 @@
import { _ } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import LibraryItems from './LibraryItems.svelte';
import { capitalize } from '$lib/utils';
let openNextUpTab: 'downloading' | 'nextUp' = 'downloading';
let noItems = false;
@@ -38,16 +39,19 @@
$servarrDownloadsStore.sonarrDownloads?.map((item) => ({
tvdbId: item.series.tvdbId,
title: item.series.title || '',
subtitle: item.series.genres?.join(', ') || '',
subtitle:
`S${item.episode?.seasonNumber}E${item.episode?.episodeNumber} • ` +
capitalize(item.status || ''),
type: 'series',
progress: 100 * (((item.size || 0) - (item.sizeleft || 0)) / (item.size || 1)),
backdropUrl: item.series.images?.find((i) => i.coverType === 'poster')?.url || ''
})) || [];
console.log($servarrDownloadsStore.radarrDownloads);
const radarrProps: ComponentProps<Poster>[] =
$servarrDownloadsStore.radarrDownloads?.map((item) => ({
tmdbId: item.movie.tmdbId,
title: item.movie.title || '',
subtitle: item.movie.genres?.join(', ') || '',
subtitle: capitalize(item.status || ''),
type: 'movie',
backdropUrl: item.movie.images?.find((i) => i.coverType === 'poster')?.url || '',
progress: 100 * (((item.size || 0) - (item.sizeleft || 0)) / (item.size || 1))
@@ -104,7 +108,7 @@
type="primary"
on:click={() => showcase?.Id && playerState.streamJellyfinId(showcase?.Id)}
>
Stream<ChevronRight size={20} />
Watch<ChevronRight size={20} />
</Button>
<Button
href={`/${showcase?.Type === 'Movie' ? 'movie' : 'series'}/${

View File

@@ -137,7 +137,7 @@
<div class="flex items-center justify-between gap-2">
<UiCarousel>
<div class="flex gap-6 text-xl font-medium text-zinc-400">
<div class="flex gap-6 text-lg font-medium text-zinc-400">
<button
class={classNames('hover:text-zinc-300 selectable rounded px-1 -mx-1', {
'text-zinc-200': openTab === 'available'