add gameview navigation

This commit is contained in:
Garret Patti
2026-04-17 23:55:33 -04:00
parent b774cba046
commit b2e9df8ab8
7 changed files with 108 additions and 28 deletions

View File

@@ -32,7 +32,10 @@ export default function TvView({ libraryId }: Props) {
const [assignments, setAssignments] = useState<Record<string, string[]>>({})
const [seriesEpisodeTags, setSeriesEpisodeTags] = useState<Record<string, string[]>>({})
const [filterRefreshKey, setFilterRefreshKey] = useState(0)
const [showFilters, setShowFilters] = useState(true)
const [showFilters, setShowFilters] = useState(
() => typeof window !== 'undefined' && window.innerWidth >= 768
)
const [selectedSeriesIndex, setSelectedSeriesIndex] = useState<number | null>(null)
const [tagPanel, setTagPanel] = useState<{ itemKey: string; title: string } | null>(null)
const [menuOpen, setMenuOpen] = useState(false)
const [confirming, setConfirming] = useState(false)
@@ -93,6 +96,7 @@ export default function TvView({ libraryId }: Props) {
useEffect(() => { fetchSeriesEpisodeTags() }, [fetchSeriesEpisodeTags])
const openSeries = (s: TvSeries) => {
setSelectedSeriesIndex(filteredSeries.indexOf(s))
setSelectedSeries(s)
setView('seasons')
setLoading(true)
@@ -143,6 +147,7 @@ export default function TvView({ libraryId }: Props) {
setView('series')
setSelectedSeries(null)
setSelectedSeason(null)
setSelectedSeriesIndex(null)
setMenuOpen(false)
setConfirming(false)
setShowTagPanel(false)
@@ -601,7 +606,7 @@ export default function TvView({ libraryId }: Props) {
>
<div className={`flex h-full w-full ${showTagPanel ? 'flex-col md:flex-row' : ''}`}>
<div className="flex-1 min-h-0 min-w-0 relative" onClick={goToSeries}>
<div className="h-full overflow-y-auto flex items-start justify-center p-4">
<div className="h-full overflow-y-auto flex items-center justify-center p-4">
<div
className="w-full max-w-3xl rounded-2xl overflow-hidden shadow-2xl"
style={{ backgroundColor: 'var(--surface)', border: '1px solid var(--border)' }}
@@ -632,8 +637,28 @@ export default function TvView({ libraryId }: Props) {
<img src={selectedSeries.posterUrl} alt={selectedSeries.title} className="w-16 rounded-lg object-cover flex-shrink-0" style={{ aspectRatio: '2/3' }} />
)}
<div className="flex-1 min-w-0">
<div className="flex items-start gap-2">
<div className="flex items-center gap-2">
{selectedSeriesIndex !== null && selectedSeriesIndex > 0 && (
<button
onClick={() => openSeries(filteredSeries[selectedSeriesIndex - 1])}
className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 transition-colors"
style={{ backgroundColor: 'var(--border)', color: 'var(--text-primary)' }}
onMouseEnter={(e) => (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface-hover)'}
onMouseLeave={(e) => (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--border)'}
aria-label="Previous series"
></button>
)}
<h2 className="text-lg font-semibold flex-1 min-w-0" style={{ color: 'var(--text-primary)' }}>{selectedSeries.title}</h2>
{selectedSeriesIndex !== null && selectedSeriesIndex < filteredSeries.length - 1 && (
<button
onClick={() => openSeries(filteredSeries[selectedSeriesIndex + 1])}
className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 transition-colors"
style={{ backgroundColor: 'var(--border)', color: 'var(--text-primary)' }}
onMouseEnter={(e) => (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface-hover)'}
onMouseLeave={(e) => (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--border)'}
aria-label="Next series"
></button>
)}
{/* Kebab menu */}
<div className="relative flex-shrink-0" ref={menuRef}>
<button