fix tv navigation
This commit is contained in:
@@ -36,6 +36,7 @@ export default function TvView({ libraryId }: Props) {
|
||||
() => typeof window !== 'undefined' && window.innerWidth >= 768
|
||||
)
|
||||
const [selectedSeriesIndex, setSelectedSeriesIndex] = useState<number | null>(null)
|
||||
const [selectedSeasonIndex, setSelectedSeasonIndex] = useState<number | null>(null)
|
||||
const [tagPanel, setTagPanel] = useState<{ itemKey: string; title: string } | null>(null)
|
||||
const [menuOpen, setMenuOpen] = useState(false)
|
||||
const [confirming, setConfirming] = useState(false)
|
||||
@@ -106,16 +107,12 @@ export default function TvView({ libraryId }: Props) {
|
||||
.then((data: TvSeason[]) => {
|
||||
setSeasons(data)
|
||||
setLoading(false)
|
||||
// Flat series: a single synthetic season (id='.') means episodes live
|
||||
// directly in the series folder — skip the seasons screen automatically.
|
||||
if (data.length === 1 && data[0].id === '.') {
|
||||
openSeason(data[0])
|
||||
}
|
||||
})
|
||||
.catch(() => { setError('Failed to load seasons'); setLoading(false) })
|
||||
}
|
||||
|
||||
const openSeason = (season: TvSeason) => {
|
||||
const openSeason = (season: TvSeason, index?: number) => {
|
||||
setSelectedSeasonIndex(index ?? seasons.indexOf(season))
|
||||
setSelectedSeason(season)
|
||||
setView('episodes')
|
||||
if (showTagPanel) {
|
||||
@@ -148,6 +145,7 @@ export default function TvView({ libraryId }: Props) {
|
||||
setSelectedSeries(null)
|
||||
setSelectedSeason(null)
|
||||
setSelectedSeriesIndex(null)
|
||||
setSelectedSeasonIndex(null)
|
||||
setMenuOpen(false)
|
||||
setConfirming(false)
|
||||
setShowTagPanel(false)
|
||||
@@ -158,6 +156,7 @@ export default function TvView({ libraryId }: Props) {
|
||||
const goToSeasons = () => {
|
||||
setView('seasons')
|
||||
setSelectedSeason(null)
|
||||
setSelectedSeasonIndex(null)
|
||||
setConfirming(false)
|
||||
if (showTagPanel && selectedSeries?.item_key) {
|
||||
setTagPanelItemKey(selectedSeries.item_key)
|
||||
@@ -637,28 +636,8 @@ 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-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>
|
||||
)}
|
||||
<div className="flex items-start gap-2">
|
||||
<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
|
||||
@@ -903,7 +882,7 @@ export default function TvView({ libraryId }: Props) {
|
||||
{seasons.map((season) => (
|
||||
<button
|
||||
key={season.id}
|
||||
onClick={() => openSeason(season)}
|
||||
onClick={() => openSeason(season, seasons.indexOf(season))}
|
||||
className="group text-left rounded-xl overflow-hidden border transition-all focus:outline-none focus-visible:ring-2"
|
||||
style={{ borderColor: 'var(--border)', backgroundColor: 'var(--surface)' }}
|
||||
onMouseEnter={(e) => {
|
||||
@@ -1015,6 +994,42 @@ export default function TvView({ libraryId }: Props) {
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Prev — series in seasons view, season in episodes view */}
|
||||
{(view === 'seasons'
|
||||
? selectedSeriesIndex !== null && selectedSeriesIndex > 0
|
||||
: selectedSeasonIndex !== null && selectedSeasonIndex > 0) && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
if (view === 'seasons') openSeries(filteredSeries[selectedSeriesIndex! - 1])
|
||||
else openSeason(seasons[selectedSeasonIndex! - 1], selectedSeasonIndex! - 1)
|
||||
}}
|
||||
className="absolute left-2 top-1/2 -translate-y-1/2 z-10 w-12 h-12 rounded-full flex items-center justify-center text-lg transition-opacity hover:opacity-100 opacity-70"
|
||||
style={{ backgroundColor: 'rgba(0,0,0,0.4)', color: '#fff' }}
|
||||
aria-label="Previous"
|
||||
>
|
||||
‹
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Next — series in seasons view, season in episodes view */}
|
||||
{(view === 'seasons'
|
||||
? selectedSeriesIndex !== null && selectedSeriesIndex < filteredSeries.length - 1
|
||||
: selectedSeasonIndex !== null && selectedSeasonIndex < seasons.length - 1) && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
if (view === 'seasons') openSeries(filteredSeries[selectedSeriesIndex! + 1])
|
||||
else openSeason(seasons[selectedSeasonIndex! + 1], selectedSeasonIndex! + 1)
|
||||
}}
|
||||
className="absolute right-2 top-1/2 -translate-y-1/2 z-10 w-12 h-12 rounded-full flex items-center justify-center text-lg transition-opacity hover:opacity-100 opacity-70"
|
||||
style={{ backgroundColor: 'rgba(0,0,0,0.4)', color: '#fff' }}
|
||||
aria-label="Next"
|
||||
>
|
||||
›
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right tag panel */}
|
||||
|
||||
Reference in New Issue
Block a user