From 126ab38475ce8e5bfd71f869e590fc95a7afbe32 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Thu, 25 Sep 2025 21:30:21 -0700 Subject: [PATCH] add placeholder expanded list item --- .../item-list/expanded-list-item.module.css | 12 +++ .../item-list/expanded-list-item.tsx | 44 +++++++++++ .../item-list/item-grid/item-grid.tsx | 3 +- .../expanded-album-list-item.module.css | 14 ++++ .../components/expanded-album-list-item.tsx | 77 +++++++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/renderer/components/item-list/expanded-list-item.module.css create mode 100644 src/renderer/components/item-list/expanded-list-item.tsx create mode 100644 src/renderer/features/albums/components/expanded-album-list-item.module.css create mode 100644 src/renderer/features/albums/components/expanded-album-list-item.tsx diff --git a/src/renderer/components/item-list/expanded-list-item.module.css b/src/renderer/components/item-list/expanded-list-item.module.css new file mode 100644 index 000000000..bfe342bbf --- /dev/null +++ b/src/renderer/components/item-list/expanded-list-item.module.css @@ -0,0 +1,12 @@ +.container { + width: 100%; + height: 100%; + padding: var(--theme-spacing-lg); +} + +.inner { + width: 100%; + height: 100%; + background-color: var(--theme-colors-surface); + border-radius: var(--theme-radius-md); +} diff --git a/src/renderer/components/item-list/expanded-list-item.tsx b/src/renderer/components/item-list/expanded-list-item.tsx new file mode 100644 index 000000000..d03b01815 --- /dev/null +++ b/src/renderer/components/item-list/expanded-list-item.tsx @@ -0,0 +1,44 @@ +import styles from './expanded-list-item.module.css'; + +import { + ItemListItem, + ItemListStateActions, +} from '/@/renderer/components/item-list/helpers/item-list-state'; +import { ExpandedAlbumListItem } from '/@/renderer/features/albums/components/expanded-album-list-item'; +import { LibraryItem } from '/@/shared/types/domain-types'; + +interface ExpandedListItemProps { + internalState: ItemListStateActions; + itemType: LibraryItem; +} + +export const ExpandedListItem = ({ internalState, itemType }: ExpandedListItemProps) => { + const expandedItems = internalState.getExpanded(); + const currentItem = expandedItems[0]; + + if (!currentItem) { + return null; + } + + return ( +
+
+ +
+
+ ); +}; + +interface SelectedItemProps { + item: ItemListItem; + itemType: LibraryItem; +} + +const SelectedItem = ({ item, itemType }: SelectedItemProps) => { + switch (itemType) { + case LibraryItem.ALBUM: + return ; + default: + return null; + } +}; diff --git a/src/renderer/components/item-list/item-grid/item-grid.tsx b/src/renderer/components/item-list/item-grid/item-grid.tsx index bdf016813..2b8101fbe 100644 --- a/src/renderer/components/item-list/item-grid/item-grid.tsx +++ b/src/renderer/components/item-list/item-grid/item-grid.tsx @@ -24,6 +24,7 @@ import { ItemListItem, ItemListStateActions, useItemListState } from '../helpers import styles from './item-grid.module.css'; import { ItemCard } from '/@/renderer/components/item-card/item-card'; +import { ExpandedListItem } from '/@/renderer/components/item-list/expanded-list-item'; import { LibraryItem } from '/@/shared/types/domain-types'; const gridComponents: GridComponents = { @@ -223,7 +224,7 @@ export const ItemGrid = ({ initial="hidden" variants={expandedAnimationVariants} > - Hello World + )} diff --git a/src/renderer/features/albums/components/expanded-album-list-item.module.css b/src/renderer/features/albums/components/expanded-album-list-item.module.css new file mode 100644 index 000000000..2e0a1ff17 --- /dev/null +++ b/src/renderer/features/albums/components/expanded-album-list-item.module.css @@ -0,0 +1,14 @@ +.container { + position: relative; + width: 100%; + height: 100%; + background-color: var(--theme-colors-surface); + border-radius: var(--theme-radius-md); +} + +.loading { + position: absolute; + right: 0; + bottom: 0; + padding: var(--theme-spacing-sm); +} diff --git a/src/renderer/features/albums/components/expanded-album-list-item.tsx b/src/renderer/features/albums/components/expanded-album-list-item.tsx new file mode 100644 index 000000000..9a694dee9 --- /dev/null +++ b/src/renderer/features/albums/components/expanded-album-list-item.tsx @@ -0,0 +1,77 @@ +import { useQuery } from '@tanstack/react-query'; +import { motion } from 'motion/react'; +import { useEffect, useRef, useTransition } from 'react'; + +import styles from './expanded-album-list-item.module.css'; + +import { ItemListItem } from '/@/renderer/components/item-list/helpers/item-list-state'; +import { albumQueries } from '/@/renderer/features/albums/api/album-api'; +import { useFastAverageColor } from '/@/renderer/hooks'; +import { Spinner } from '/@/shared/components/spinner/spinner'; + +interface ExpandedAlbumListItemProps { + item: ItemListItem; + previousItem?: ItemListItem | null; +} + +export const ExpandedAlbumListItem = ({ item, previousItem }: ExpandedAlbumListItemProps) => { + const [, startTransition] = useTransition(); + const previousDataRef = useRef(null); + + const { data, isLoading } = useQuery( + albumQueries.detail({ + options: {}, + query: { id: item.id }, + serverId: item.serverId, + }), + ); + + // Store the previous data when we have new data + useEffect(() => { + if (data && !isLoading) { + previousDataRef.current = data; + } + }, [data, isLoading]); + + // Use current data if available, otherwise use previous data for smooth transition + const displayData = data || previousDataRef.current; + const isDataTransitioning = isLoading && previousDataRef.current; + + const color = useFastAverageColor({ + id: item.id, + src: displayData?.imageUrl, + srcLoaded: !isDataTransitioning, + }); + + // Start transition when item changes + useEffect(() => { + if (previousItem && previousItem.id !== item.id) { + startTransition(() => {}); + } + }, [item.id, previousItem, startTransition]); + + return ( + + {isDataTransitioning && ( +
+ +
+ )} +
+ ExpandedAlbumListItem - {displayData?.name || 'Loading...'} +
+
+ ); +};