more-ui-adjustments #29

Merged
gpatti merged 4 commits from more-ui-adjustments into main 2026-04-18 04:38:34 +00:00
Showing only changes of commit 0de839393a - Show all commits

View File

@@ -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 */}