fix: Issues with grid item sizing

This commit is contained in:
Aleksi Lassila
2024-05-31 19:53:39 +03:00
parent 8acfd0f4d9
commit f6b9ac41ba
6 changed files with 78 additions and 76 deletions

View File

@@ -4,46 +4,49 @@
import classNames from 'classnames';
import { getCardDimensions } from '../utils';
export let direction: 'horizontal' | 'vertical' = 'vertical';
// export let direction: 'horizontal' | 'vertical' = 'vertical';
export let type: 'portrait' | 'landscape' = 'portrait';
let cols = getCardDimensions(window.innerWidth).columns;
let cols = getCardDimensions(window.innerWidth, type).columns;
$: console.log('cols', cols);
// let cols: number = 1;
const calculateRows = () => {
const width = window.innerWidth;
if (direction === 'vertical') {
if (width >= 1536) {
cols = 6;
} else if (width >= 1280) {
cols = 5;
} else if (width >= 768) {
cols = 4;
} else {
cols = 3;
}
} else {
// if (width >= 1920) {
// cols = 4;
// } else
if (width >= 1536) {
cols = 3;
} else if (width >= 1280) {
cols = 2;
} else if (width >= 768) {
cols = 1;
} else {
cols = 1;
}
}
};
// const calculateRows = () => {
// const width = window.innerWidth;
// if (direction === 'vertical') {
// if (width >= 1536) {
// cols = 6;
// } else if (width >= 1280) {
// cols = 5;
// } else if (width >= 768) {
// cols = 4;
// } else {
// cols = 3;
// }
// } else {
// // if (width >= 1920) {
// // cols = 4;
// // } else
// if (width >= 1536) {
// cols = 3;
// } else if (width >= 1280) {
// cols = 2;
// } else if (width >= 768) {
// cols = 1;
// } else {
// cols = 1;
// }
// }
// };
// onMount(() => {
// calculateRows();
// });
</script>
<svelte:window on:resize={(e) => (cols = getCardDimensions(e.currentTarget.innerWidth).columns)} />
<svelte:window
on:resize={(e) => (cols = getCardDimensions(e.currentTarget.innerWidth, type).columns)}
/>
<Container
direction="grid"
@@ -51,8 +54,8 @@
class={classNames(
'grid gap-x-8 gap-y-8',
{
'grid-cols-1 md:grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 3xl:grid-cols-4':
direction === 'horizontal'
// 'grid-cols-1 md:grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 3xl:grid-cols-4':
// direction === 'horizontal'
// 'grid-cols-4 md:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6': direction === 'vertical'
},

View File

@@ -4,6 +4,7 @@
import { ArrowDown, Check, TriangleRight } from 'radix-icons-svelte';
import type { Readable } from 'svelte/store';
import AnimateScale from '../AnimateScale.svelte';
import { getCardDimensions } from '../../utils';
export let episodeNumber: number;
export let episodeName: string;
@@ -16,36 +17,20 @@
let hasFocus: Readable<boolean>;
let dimensions = getDimensions(window.innerWidth);
function getDimensions(viewportWidth: number) {
const minWidth = 240;
const margin = 128;
const gap = 32;
const cols = Math.floor((gap - 2 * margin + viewportWidth) / (minWidth + gap));
const scale = -(gap * (cols - 1) + 2 * margin - viewportWidth) / (cols * minWidth);
const newWidth = minWidth * scale;
const newHeight = (3 / 2) * newWidth;
return {
width: newWidth,
height: newHeight
};
}
let dimensions = getCardDimensions(window.innerWidth, 'landscape');
</script>
<svelte:window on:resize={(e) => (dimensions = getDimensions(e.currentTarget.innerWidth))} />
<svelte:window
on:resize={(e) => (dimensions = getCardDimensions(e.currentTarget.innerWidth, 'landscape'))}
/>
<AnimateScale hasFocus={$hasFocus}>
<Container
class={classNames(
'w-full h-72',
'flex flex-col shrink-0',
'overflow-hidden rounded-2xl cursor-pointer group relative px-4 py-3 selectable transition-opacity'
)}
style={`width: ${dimensions.width}px; height: ${dimensions.height}px`}
on:clickOrSelect
on:enter
on:mount

View File

@@ -111,7 +111,7 @@
</Container>
{/each}
</UICarousel>
<CardGrid direction="horizontal" on:mount>
<CardGrid type="landscape" on:mount>
{#if $tmdbSeasons?.[seasonIndex]?.episodes?.length}
{#each $tmdbSeasons?.[seasonIndex]?.episodes || [] as episode}
{@const jellyfinEpisode = awaitedJellyfinEpisodes?.find(

View File

@@ -4,19 +4,25 @@
import AnimateScale from '../AnimateScale.svelte';
import classNames from 'classnames';
import { Plus, PlusCircled } from 'radix-icons-svelte';
import { getCardDimensions } from '../../utils';
export let backdropUrl: string;
let hasFocus: Readable<boolean>;
let dimensions = getCardDimensions(window.innerWidth, 'landscape');
</script>
<svelte:window
on:resize={(e) => (dimensions = getCardDimensions(e.currentTarget.innerWidth, 'landscape'))}
/>
<AnimateScale hasFocus={$hasFocus}>
<Container
class={classNames(
'w-full h-64',
'flex flex-col shrink-0',
'overflow-hidden rounded-2xl cursor-pointer group relative selectable transition-opacity'
)}
style={`width: ${dimensions.width}px; height: ${dimensions.height}px`}
on:clickOrSelect
on:enter
bind:hasFocus

View File

@@ -11,23 +11,28 @@
import { radarrApi } from '../apis/radarr/radarr-api';
import Card from '../components/Card/Card.svelte';
import type { ComponentProps } from 'svelte';
import TmdbCard from '../components/Card/TmdbCard.svelte';
import { tmdbApi, type TmdbMovie2, type TmdbSeries2 } from '../apis/tmdb/tmdb-api';
const libraryItemsP = jellyfinApi.getLibraryItems();
let sonarrDownloads: Promise<ComponentProps<Card>[]> = sonarrApi.getDownloads().then((items) =>
items
.filter(
(value, index, self) => index === self.findIndex((t) => t.seriesId === value.seriesId)
const sonarrDownloads: Promise<TmdbSeries2[]> = sonarrApi
.getDownloads()
.then((items) =>
Promise.all(
items
.filter(
(value, index, self) => index === self.findIndex((t) => t.seriesId === value.seriesId)
)
.map((i) => tmdbApi.getTmdbSeriesFromTvdbId(String(i.series.tvdbId)))
).then((i) => i.filter((i) => !!i) as TmdbSeries2[])
);
let radarrDownloads: Promise<TmdbMovie2[]> = radarrApi
.getDownloads()
.then((items) =>
Promise.all(items.map((i) => tmdbApi.getTmdbMovie(i.movie.tmdbId || -1))).then(
(i) => i.filter((i) => !!i) as TmdbMovie2[]
)
.map((i) => ({
backdropUrl: i.series.images?.find((i) => i.coverType === 'poster')?.remoteUrl || '',
group: true
}))
);
let radarrDownloads: Promise<ComponentProps<Card>[]> = radarrApi.getDownloads().then((items) =>
items.map((i) => ({
backdropUrl: i.movie.images?.find((i) => i.coverType === 'poster')?.remoteUrl || ''
}))
);
);
settings.update((prev) => ({
...prev,
@@ -46,12 +51,12 @@
{#if sonarrDownloads?.length || radarrDownloads?.length}
<Carousel scrollClass="px-32" on:enter={scrollIntoView({ vertical: 128 })}>
<span slot="header">Downloading</span>
{#each sonarrDownloads as props}
<Card on:enter={scrollIntoView({ horizontal: 128 })} size="lg" {...props} />
{#each sonarrDownloads as item}
<TmdbCard on:enter={scrollIntoView({ horizontal: 128 })} size="lg" {item} group />
{/each}
{#each radarrDownloads as props}
<Card on:enter={scrollIntoView({ horizontal: 128 })} size="lg" {...props} />
{#each radarrDownloads as item}
<TmdbCard on:enter={scrollIntoView({ horizontal: 128 })} size="lg" {item} />
{/each}
</Carousel>
{/if}

View File

@@ -134,8 +134,11 @@ export function subscribeUntil<T>(store: Readable<T>, fn: (value: T) => boolean)
});
}
export function getCardDimensions(viewportWidth: number) {
const minWidth = 240;
export function getCardDimensions(
viewportWidth: number,
type: 'portrait' | 'landscape' = 'portrait'
) {
const minWidth = type === 'portrait' ? 240 : 400;
const margin = 128;
const gap = 32;
@@ -144,7 +147,7 @@ export function getCardDimensions(viewportWidth: number) {
const scale = -(gap * (cols - 1) + 2 * margin - viewportWidth) / (cols * minWidth);
const newWidth = minWidth * scale;
const newHeight = (3 / 2) * newWidth;
const newHeight = (type === 'portrait' ? 3 / 2 : 9 / 16) * newWidth;
return {
width: newWidth,