mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
Add headers using custom component
This commit is contained in:
@@ -1,22 +1,15 @@
|
|||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { Group, Slider } from '@mantine/core';
|
import { Group, Slider } from '@mantine/core';
|
||||||
import { motion } from 'framer-motion';
|
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import { RiArrowDownSLine } from 'react-icons/ri';
|
import { RiArrowDownSLine } from 'react-icons/ri';
|
||||||
import { JFAlbumListSort } from '/@/api/jellyfin.types';
|
import { JFAlbumListSort } from '/@/api/jellyfin.types';
|
||||||
import { NDAlbumListSort } from '/@/api/navidrome.types';
|
import { NDAlbumListSort } from '/@/api/navidrome.types';
|
||||||
import type { AlbumListSort } from '/@/api/types';
|
import type { AlbumListSort } from '/@/api/types';
|
||||||
import { SortOrder } from '/@/api/types';
|
import { SortOrder } from '/@/api/types';
|
||||||
import { Button, DropdownMenu } from '/@/components';
|
import { Button, DropdownMenu, PageHeader } from '/@/components';
|
||||||
import {
|
import { useCurrentServer, useAppStoreActions, useAlbumRouteStore } from '/@/store';
|
||||||
useCurrentServer,
|
|
||||||
useAppStoreActions,
|
|
||||||
useAlbumRouteStore,
|
|
||||||
useSidebarRightExpanded,
|
|
||||||
} from '/@/store';
|
|
||||||
import { CardDisplayType } from '/@/types';
|
import { CardDisplayType } from '/@/types';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const FILTERS = {
|
const FILTERS = {
|
||||||
jellyfin: [
|
jellyfin: [
|
||||||
@@ -48,29 +41,18 @@ const ORDER = [
|
|||||||
{ name: 'Descending', value: SortOrder.DESC },
|
{ name: 'Descending', value: SortOrder.DESC },
|
||||||
];
|
];
|
||||||
|
|
||||||
const AlbumListHeaderContainer = styled(motion.div)<{ $padRight?: boolean }>`
|
|
||||||
padding: 0.8rem 1rem;
|
|
||||||
|
|
||||||
padding: ${(props) => (props.$padRight ? '0.8rem 1rem' : '0.8rem 170px 0.8rem 1rem')};
|
|
||||||
|
|
||||||
button {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const AlbumListHeader = () => {
|
export const AlbumListHeader = () => {
|
||||||
const server = useCurrentServer();
|
const server = useCurrentServer();
|
||||||
const { setPage } = useAppStoreActions();
|
const { setPage } = useAppStoreActions();
|
||||||
const page = useAlbumRouteStore();
|
const page = useAlbumRouteStore();
|
||||||
const filters = page.list.filter;
|
const filters = page.list.filter;
|
||||||
|
|
||||||
const sortByLabel = server?.type
|
const sortByLabel = server?.type
|
||||||
? (FILTERS[server.type as keyof typeof FILTERS] as { name: string; value: string }[]).find(
|
? (FILTERS[server.type as keyof typeof FILTERS] as { name: string; value: string }[]).find(
|
||||||
(f) => f.value === filters.sortBy,
|
(f) => f.value === filters.sortBy,
|
||||||
)?.name
|
)?.name
|
||||||
: 'Unknown';
|
: 'Unknown';
|
||||||
|
|
||||||
const isRightSidebarExpanded = useSidebarRightExpanded();
|
|
||||||
|
|
||||||
const sortOrderLabel = ORDER.find((s) => s.value === filters.sortOrder)?.name;
|
const sortOrderLabel = ORDER.find((s) => s.value === filters.sortOrder)?.name;
|
||||||
|
|
||||||
const setSize = throttle(
|
const setSize = throttle(
|
||||||
@@ -150,7 +132,7 @@ export const AlbumListHeader = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AlbumListHeaderContainer $padRight={isRightSidebarExpanded}>
|
<PageHeader>
|
||||||
<Group>
|
<Group>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
position="bottom-end"
|
position="bottom-end"
|
||||||
@@ -271,6 +253,6 @@ export const AlbumListHeader = () => {
|
|||||||
</DropdownMenu.Dropdown> */}
|
</DropdownMenu.Dropdown> */}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Group>
|
</Group>
|
||||||
</AlbumListHeaderContainer>
|
</PageHeader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Group } from '@mantine/core';
|
||||||
|
import { FastAverageColor } from 'fast-average-color';
|
||||||
|
import { PageHeader, Text } from '/@/components';
|
||||||
|
import { useCurrentSong } from '/@/store';
|
||||||
|
import { getHeaderColor } from '/@/utils';
|
||||||
|
import { useTheme } from '/@/hooks';
|
||||||
|
|
||||||
|
export const NowPlayingHeader = () => {
|
||||||
|
const [headerColor, setHeaderColor] = useState({ isDark: false, value: 'transparent' });
|
||||||
|
const currentSong = useCurrentSong();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fac = new FastAverageColor();
|
||||||
|
const url = currentSong?.imageUrl;
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
fac
|
||||||
|
.getColorAsync(currentSong?.imageUrl, {
|
||||||
|
algorithm: 'simple',
|
||||||
|
ignoredColor: [
|
||||||
|
[255, 255, 255, 255], // White
|
||||||
|
[0, 0, 0, 255], // Black
|
||||||
|
],
|
||||||
|
mode: 'precision',
|
||||||
|
})
|
||||||
|
.then((color) => {
|
||||||
|
const isDark = color.isDark;
|
||||||
|
setHeaderColor({ isDark, value: getHeaderColor(color.rgb, theme === 'dark' ? 0.3 : 1) });
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
fac.destroy();
|
||||||
|
};
|
||||||
|
}, [currentSong?.imageUrl, theme]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageHeader backgroundColor={headerColor.value}>
|
||||||
|
<Group>
|
||||||
|
<Text size="xl">Queue</Text>
|
||||||
|
</Group>
|
||||||
|
</PageHeader>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user