pass state from list navigation

This commit is contained in:
jeffvli
2025-11-20 00:18:19 -08:00
parent eb8dcfa053
commit ece82d813c
11 changed files with 81 additions and 17 deletions
@@ -280,6 +280,7 @@ const CompactItemCard = ({
onDragStart={handleLinkDragStart}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
state={{ item: data }}
to={navigationPath}
>
{imageContainerContent}
@@ -466,6 +467,7 @@ const DefaultItemCard = ({
onDragStart={handleLinkDragStart}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
state={{ item: data }}
to={navigationPath}
>
{imageContainerContent}
@@ -716,6 +718,7 @@ const PosterItemCard = ({
onDragStart={handleLinkDragStart}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
state={{ item: data }}
to={navigationPath}
>
{imageContainerContent}
@@ -789,6 +792,7 @@ export const getDataRows = (): DataRow[] => {
case LibraryItem.ALBUM:
return (
<Link
state={{ item: data }}
to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
albumId: data.id,
})}
@@ -799,6 +803,7 @@ export const getDataRows = (): DataRow[] => {
case LibraryItem.ALBUM_ARTIST:
return (
<Link
state={{ item: data }}
to={generatePath(
AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL,
{
@@ -812,6 +817,7 @@ export const getDataRows = (): DataRow[] => {
case LibraryItem.PLAYLIST:
return (
<Link
state={{ item: data }}
to={generatePath(AppRoute.PLAYLISTS_DETAIL_SONGS, {
playlistId: data.id,
})}
@@ -836,6 +842,7 @@ export const getDataRows = (): DataRow[] => {
return (data as Album | Song).albumArtists.map((artist, index) => (
<Fragment key={artist.id}>
<Link
state={{ item: artist }}
to={generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, {
albumArtistId: artist.id,
})}
@@ -859,6 +866,7 @@ export const getDataRows = (): DataRow[] => {
return (data as Album | Song).artists.map((artist, index) => (
<Fragment key={artist.id}>
<Link
state={{ item: artist }}
to={generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL, {
albumArtistId: artist.id,
})}
@@ -945,8 +953,14 @@ export const getDataRows = (): DataRow[] => {
if ('album' in data && data.album) {
const song = data as Song;
if ('albumId' in song && song.albumId) {
const albumData = {
id: song.albumId,
imageUrl: song.imageUrl,
name: song.album,
};
return (
<Link
state={{ item: albumData }}
to={generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
albumId: song.albumId,
})}
@@ -1024,7 +1038,6 @@ const getItemNavigationPath = (
return null;
}
// Check if data has _itemType (like in title row logic)
const effectiveItemType = '_itemType' in data && data._itemType ? data._itemType : itemType;
return getTitlePath(effectiveItemType, data.id);
@@ -201,7 +201,7 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs
) {
const path = getTitlePath(itemType, item.id);
if (path) {
navigate(path);
navigate(path, { state: { item } });
return;
}
}
@@ -40,7 +40,14 @@ const AlbumArtistsColumn = (props: ItemTableListInnerColumn) => {
>
{albumArtists.map((albumArtist, index) => (
<Fragment key={albumArtist.id}>
<Text component={Link} isLink isMuted isNoSelect to={albumArtist.path}>
<Text
component={Link}
isLink
isMuted
isNoSelect
state={{ item: albumArtist }}
to={albumArtist.path}
>
{albumArtist.name}
</Text>
{index < albumArtists.length - 1 && ', '}
@@ -40,7 +40,14 @@ const ArtistsColumn = (props: ItemTableListInnerColumn) => {
>
{artists.map((artist, index) => (
<Fragment key={artist.id}>
<Text component={Link} isLink isMuted isNoSelect to={artist.path}>
<Text
component={Link}
isLink
isMuted
isNoSelect
state={{ item: artist }}
to={artist.path}
>
{artist.name}
</Text>
{index < artists.length - 1 && ', '}
@@ -39,6 +39,7 @@ const GenreBadgeColumn = (props: ItemTableListInnerColumn) => {
<Badge
component={Link}
key={genre.id}
state={{ item: genre }}
style={{
backgroundColor: genre.color,
color: genre.isLight ? 'black' : 'white',
@@ -40,7 +40,14 @@ const GenreColumn = (props: ItemTableListInnerColumn) => {
>
{genres.map((genre, index) => (
<Fragment key={genre.id}>
<Text component={Link} isLink isMuted isNoSelect to={genre.path}>
<Text
component={Link}
isLink
isMuted
isNoSelect
state={{ item: genre }}
to={genre.path}
>
{genre.name}
</Text>
{index < genres.length - 1 && ', '}
@@ -31,11 +31,13 @@ function DefaultTitleColumn(props: ItemTableListInnerColumn) {
if (typeof row === 'string') {
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const titleLinkProps = path
? {
component: Link,
isLink: true,
state: { item },
to: path,
}
: {};
@@ -74,6 +76,7 @@ function QueueSongTitleColumn(props: ItemTableListInnerColumn) {
if (typeof row === 'string') {
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const textStyles = isActive ? { color: 'var(--theme-colors-primary)' } : {};
@@ -81,6 +84,7 @@ function QueueSongTitleColumn(props: ItemTableListInnerColumn) {
? {
component: Link,
isLink: true,
state: { item },
to: path,
}
: {};
@@ -34,10 +34,12 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
const rowHeight = props.getRowHeight(props.rowIndex, props);
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const titleLinkProps = path
? {
component: Link,
isLink: true,
state: { item },
to: path,
}
: {};
@@ -56,7 +58,14 @@ export const DefaultTitleCombinedColumn = (props: ItemTableListInnerColumn) => {
<div className={styles.artists}>
{artists.map((artist, index) => (
<span key={artist.id}>
<Text component={Link} isLink isMuted isNoSelect to={artist.path}>
<Text
component={Link}
isLink
isMuted
isNoSelect
state={{ item: artist }}
to={artist.path}
>
{artist.name}
</Text>
{index < artists.length - 1 && ', '}
@@ -97,12 +106,14 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
const rowHeight = props.getRowHeight(props.rowIndex, props);
const path = getTitlePath(props.itemType, (props.data[props.rowIndex] as any).id as string);
const item = props.data[props.rowIndex] as any;
const textStyles = isActive ? { color: 'var(--theme-colors-primary)' } : {};
const titleLinkProps = path
? {
component: Link,
isLink: true,
state: { item },
to: path,
}
: {};
@@ -126,7 +137,14 @@ export const QueueSongTitleCombinedColumn = (props: ItemTableListInnerColumn) =>
<div className={styles.artists}>
{artists.map((artist, index) => (
<span key={artist.id}>
<Text component={Link} isLink isMuted isNoSelect to={artist.path}>
<Text
component={Link}
isLink
isMuted
isNoSelect
state={{ item: artist }}
to={artist.path}
>
{artist.name}
</Text>
{index < artists.length - 1 && ', '}
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { useRef } from 'react';
import { useParams } from 'react-router';
import { useLocation, useParams } from 'react-router';
import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area';
import { albumQueries } from '/@/renderer/features/albums/api/album-api';
@@ -20,9 +20,13 @@ const AlbumDetailRoute = () => {
const { albumId } = useParams() as { albumId: string };
const server = useCurrentServer();
const detailQuery = useQuery(
albumQueries.detail({ query: { id: albumId }, serverId: server?.id }),
);
const location = useLocation();
const detailQuery = useQuery({
...albumQueries.detail({ query: { id: albumId }, serverId: server?.id }),
initialData: location.state?.item,
staleTime: 0,
});
const { background: backgroundColor, colorId } = useFastAverageColor({
id: albumId,
@@ -1,6 +1,6 @@
import { useQuery } from '@tanstack/react-query';
import { useRef } from 'react';
import { useParams } from 'react-router';
import { useLocation, useParams } from 'react-router';
import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
@@ -26,12 +26,16 @@ const AlbumArtistDetailRoute = () => {
const routeId = (artistId || albumArtistId) as string;
const detailQuery = useQuery(
artistsQueries.albumArtistDetail({
const location = useLocation();
const detailQuery = useQuery({
...artistsQueries.albumArtistDetail({
query: { id: routeId },
serverId: server?.id,
}),
);
initialData: location.state?.item,
staleTime: 0,
});
const { background: backgroundColor, colorId } = useFastAverageColor({
id: artistId,
+1 -2
View File
@@ -1,13 +1,12 @@
import { lazy, Suspense } from 'react';
import { HashRouter, Route, Routes } from 'react-router';
import { AppRoute } from './routes';
import { RouterErrorBoundary } from '/@/renderer/components/error-boundary/router-error-boundary';
import { AddToPlaylistContextModal } from '/@/renderer/features/playlists/components/add-to-playlist-context-modal';
import { ShareItemContextModal } from '/@/renderer/features/sharing/components/share-item-context-modal';
import { ResponsiveLayout } from '/@/renderer/layouts/responsive-layout';
import { AppOutlet } from '/@/renderer/router/app-outlet';
import { AppRoute } from '/@/renderer/router/routes';
import { TitlebarOutlet } from '/@/renderer/router/titlebar-outlet';
import { BaseContextModal, ModalsProvider } from '/@/shared/components/modal/modal';