fix four audit bugs - offline playback, audio passthrough, notification dedup, dashboard fixes
This commit is contained in:
@@ -291,6 +291,12 @@ export default function PlayerPage() {
|
||||
// native audioTracks switch isn't possible (transcoded streams, or
|
||||
// single-audio sources where the alternate track isn't in the file).
|
||||
// maxBitrate threads the user-picked quality cap into the same call.
|
||||
// Offline fallback: if this item was downloaded, use the Blob URL
|
||||
// instead of hitting the server. PlaybackInfo and reporting gracefully
|
||||
// no-op when there's no connection.
|
||||
const downloaded = useDownloads(s => s.getByItemId(id || ''))
|
||||
const offlineUrl = downloaded?.status === 'done' ? downloaded.localPath : undefined
|
||||
|
||||
const { data: playbackInfo } = usePlaybackInfo(
|
||||
id,
|
||||
startTimeTicks,
|
||||
@@ -299,6 +305,7 @@ export default function PlayerPage() {
|
||||
)
|
||||
const resolvedSource = playbackInfo?.MediaSources?.[0]
|
||||
const streamUrl = (() => {
|
||||
if (offlineUrl) return offlineUrl
|
||||
if (!resolvedSource || !serverUrl) return ''
|
||||
// Direct play: server-confirmed the browser can decode the source as-is
|
||||
if (resolvedSource.SupportsDirectPlay) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { motion } from 'framer-motion'
|
||||
import { Activity, MonitorPlay, Users, Server as ServerIcon, Clock, Film } from '../../../lib/icons'
|
||||
import { jellyfinClient, getSystemApi, getSessionApi, getActivityLogApi } from '../../../api/jellyfin'
|
||||
import { Activity, MonitorPlay, Users, Server as ServerIcon, Clock } from '../../../lib/icons'
|
||||
import { jellyfinClient, getSystemApi, getSessionApi } from '../../../api/jellyfin'
|
||||
import { Section, SubHeading } from '../_ui'
|
||||
|
||||
function useApi() {
|
||||
@@ -33,17 +33,6 @@ export function ServerDashboardSection() {
|
||||
refetchInterval: 10_000,
|
||||
})
|
||||
|
||||
const activity = useQuery({
|
||||
queryKey: ['jellyfin', 'activity-log'],
|
||||
queryFn: async () => {
|
||||
if (!api) return []
|
||||
const res = await getActivityLogApi(api).getLogEntries({ limit: 20 })
|
||||
return res.data.Items || []
|
||||
},
|
||||
enabled: !!api,
|
||||
refetchInterval: 60_000,
|
||||
})
|
||||
|
||||
const info = serverInfo.data
|
||||
const activeSessions = sessions.data?.filter(s => s.NowPlayingItem) || []
|
||||
const transcodes = activeSessions.filter(s => s.PlayState?.PlayMethod === 'Transcode')
|
||||
@@ -107,28 +96,7 @@ export function ServerDashboardSection() {
|
||||
</>
|
||||
)}
|
||||
|
||||
{activity.data && activity.data.length > 0 && (
|
||||
<>
|
||||
<SubHeading label="Recent activity" />
|
||||
<div className="space-y-1">
|
||||
{activity.data.slice(0, 10).map((entry: any, i: number) => (
|
||||
<motion.div
|
||||
key={entry.Id || i}
|
||||
initial={{ opacity: 0, x: -6 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: Math.min(i * 0.03, 0.3) }}
|
||||
className="flex items-center gap-3 px-2 py-1.5 text-[11.5px]"
|
||||
>
|
||||
<Film size={11} className="text-text-4 shrink-0" />
|
||||
<span className="text-text-3 truncate flex-1">{entry.Name}</span>
|
||||
<span className="text-text-4 tabular-nums shrink-0">
|
||||
{entry.DateCreated ? new Date(entry.DateCreated).toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' }) : ''}
|
||||
</span>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
</Section>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user