mirror of
https://github.com/jeffvli/feishin.git
synced 2026-08-03 19:03:31 +02:00
redesign feature carousel
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { Suspense, useMemo, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -28,12 +28,12 @@ const HomeRoute = () => {
|
||||
|
||||
const isJellyfin = server?.type === ServerType.JELLYFIN;
|
||||
|
||||
const feature = useQuery(
|
||||
albumQueries.list({
|
||||
const feature = useSuspenseQuery({
|
||||
...albumQueries.list({
|
||||
options: {
|
||||
enabled: homeFeature,
|
||||
gcTime: 1000 * 60,
|
||||
staleTime: 1000 * 60,
|
||||
gcTime: 1000 * 30,
|
||||
staleTime: 1000 * 30,
|
||||
},
|
||||
query: {
|
||||
limit: 20,
|
||||
@@ -43,7 +43,8 @@ const HomeRoute = () => {
|
||||
},
|
||||
serverId: server?.id,
|
||||
}),
|
||||
);
|
||||
queryKey: ['home', 'feature'],
|
||||
});
|
||||
|
||||
const featureItemsWithImage = useMemo(() => {
|
||||
return feature.data?.items?.filter((item) => item.imageUrl) ?? [];
|
||||
@@ -124,17 +125,13 @@ const HomeRoute = () => {
|
||||
{sortedCarousel.map((carousel) => {
|
||||
if (carousel.itemType === LibraryItem.ALBUM) {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={<Spinner container />}
|
||||
<AlbumInfiniteCarousel
|
||||
key={`carousel-${carousel.uniqueId}`}
|
||||
>
|
||||
<AlbumInfiniteCarousel
|
||||
rowCount={1}
|
||||
sortBy={carousel.sortBy}
|
||||
sortOrder={carousel.sortOrder}
|
||||
title={carousel.title}
|
||||
/>
|
||||
</Suspense>
|
||||
rowCount={1}
|
||||
sortBy={carousel.sortBy}
|
||||
sortOrder={carousel.sortOrder}
|
||||
title={carousel.title}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -151,4 +148,12 @@ const HomeRoute = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default HomeRoute;
|
||||
const SuspensedHomeRoute = () => {
|
||||
return (
|
||||
<Suspense fallback={<Spinner container />}>
|
||||
<HomeRoute />
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export default SuspensedHomeRoute;
|
||||
|
||||
@@ -6,7 +6,28 @@
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
background-image: var(--theme-overlay-subheader);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.background-overlay {
|
||||
--color-from: var(--background-base-min-contrast);
|
||||
--color-to: transparent;
|
||||
--dither: none;
|
||||
--direction-and-possibly-color-interpolation: to bottom;
|
||||
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
background-color: var(--color-from);
|
||||
background-image:
|
||||
linear-gradient(
|
||||
var(--direction-and-possibly-color-interpolation),
|
||||
var(--color-from),
|
||||
var(--color-to)
|
||||
),
|
||||
var(--dither);
|
||||
}
|
||||
|
||||
.background-image {
|
||||
|
||||
@@ -1,28 +1,71 @@
|
||||
import { generateColors } from '@mantine/colors-generator';
|
||||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import styles from './library-background-overlay.module.css';
|
||||
|
||||
import { useAppThemeColors } from '/@/renderer/themes/use-app-theme';
|
||||
|
||||
interface LibraryBackgroundOverlayProps {
|
||||
backgroundColor?: string;
|
||||
headerRef: React.RefObject<HTMLDivElement | null>;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
export const LibraryBackgroundOverlay = ({
|
||||
backgroundColor,
|
||||
headerRef,
|
||||
opacity = 0.7,
|
||||
}: LibraryBackgroundOverlayProps) => {
|
||||
const height = useHeaderHeight(headerRef);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.overlay}
|
||||
style={{
|
||||
backgroundColor,
|
||||
height: height ? `${height + 64}px` : undefined,
|
||||
opacity,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface BackgroundOverlayProps {
|
||||
backgroundColor?: string;
|
||||
direction?: string;
|
||||
height?: number | string;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
export const BackgroundOverlay = ({
|
||||
backgroundColor,
|
||||
direction = 'to bottom',
|
||||
height = '100%',
|
||||
opacity,
|
||||
}: BackgroundOverlayProps) => {
|
||||
const theme = useAppThemeColors();
|
||||
|
||||
const colors = generateColors(backgroundColor || theme.color['--theme-colors-background']);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(styles.backgroundOverlay)}
|
||||
style={
|
||||
{
|
||||
'--color-from': colors[6],
|
||||
'--color-to': colors[9],
|
||||
'--direction-and-possibly-color-interpolation': direction,
|
||||
'--dither': 'none',
|
||||
backgroundColor: backgroundColor,
|
||||
height,
|
||||
opacity,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface LibraryBackgroundProps {
|
||||
blur?: number;
|
||||
headerRef: React.RefObject<HTMLDivElement | null>;
|
||||
|
||||
Reference in New Issue
Block a user