mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-14 09:06:37 +08:00
优化,bug处理
This commit is contained in:
@@ -20,7 +20,7 @@ import { useAuthStore } from '../stores/auth'
|
||||
import type { Media, PlaybackInfo, PlaybackQuality, PlaybackSegment, PlaybackSegmentKind } from '../types'
|
||||
import { getSeriesKey, seriesTitleFromPath } from '../utils/groupSeries'
|
||||
import { formatEpisodeLabel } from '../utils/episodeNumber'
|
||||
import { mediaVersionMatches, mediaVersionsOf } from '../utils/mediaVersion'
|
||||
import { autoPlayEpisodeFor, mediaVersionMatches, mediaVersionsOf } from '../utils/mediaVersion'
|
||||
import { DEFAULT_PLAYBACK_RATE, normalizePlaybackRate } from '../utils/playbackRate'
|
||||
import { resolveActiveSkip, skippedNoticeText, toSkipSegments, type SkipPrompt } from '../utils/skipSegments'
|
||||
import { isRemoteEmbyID } from '../utils/remoteEmby'
|
||||
@@ -1681,6 +1681,17 @@ export function PlayerPage() {
|
||||
return playlistEpisodes.findIndex((e) => mediaVersionMatches(e, media.id))
|
||||
}, [media, playlistEpisodes])
|
||||
|
||||
// 用剧集 ID 打开播放器时(首页轮播、剧集库卡片、剧集详情页的播放按钮),先落到第一集:
|
||||
// 这类条目没有可播文件,直接请求 /api/stream/<剧集ID> 会被远程 Emby 以 500 打回。
|
||||
useEffect(() => {
|
||||
const target = autoPlayEpisodeFor(media, id, playlistEpisodes)
|
||||
if (!target) return
|
||||
navigate(
|
||||
{ pathname: `/play/${target.id}`, search: location.search },
|
||||
{ replace: true, state: location.state },
|
||||
)
|
||||
}, [media, id, playlistEpisodes, navigate, location.search, location.state])
|
||||
|
||||
const prevEpisode = useMemo(() => {
|
||||
if (currentEpisodeIndex > 0) {
|
||||
return playlistEpisodes[currentEpisodeIndex - 1]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
autoPlayEpisodeFor,
|
||||
isStrmMedia,
|
||||
mediaVersionFileName,
|
||||
mediaVersionLabel,
|
||||
@@ -64,4 +65,25 @@ check('strm filename drops outer extension', mediaVersionFileName(cloudRow) ===
|
||||
check('missing path has no filename', mediaVersionFileName(media({ path: '' })) === '')
|
||||
check('isStrmMedia detects strm url', isStrmMedia(cloudRow))
|
||||
|
||||
// 首页轮播/剧集卡片交给播放器的是「整部剧」ID:选集列表里没有它自己,
|
||||
// 播放器要自动落到第一集,否则 /api/stream/<剧集ID> 会被远程 Emby 打回 500。
|
||||
const series = media({ id: 'embyremote~mount-1~222679', title: '某部新番', path: '/anime/某部新番', size_bytes: 0 })
|
||||
const ep1 = media({ id: 'embyremote~mount-1~222681', path: '/anime/某部新番/Season 1/S1E01.mp4', size_bytes: 299580311 })
|
||||
const ep2 = media({ id: 'embyremote~mount-1~222683', path: '/anime/某部新番/Season 1/S1E02.mp4', size_bytes: 299580312 })
|
||||
|
||||
check('series falls back to its first episode', autoPlayEpisodeFor(series, series.id, [ep1, ep2])?.id === ep1.id)
|
||||
check('playable episode stays untouched', autoPlayEpisodeFor(ep1, ep1.id, [ep1, ep2]) === null)
|
||||
check('single-item movie list stays untouched', autoPlayEpisodeFor(ep1, ep1.id, [{ ...ep1 }]) === null)
|
||||
check('waits until the requested item is loaded', autoPlayEpisodeFor(null, series.id, [ep1]) === null)
|
||||
check('ignores a response for another id', autoPlayEpisodeFor(ep2, series.id, [ep1]) === null)
|
||||
check('empty episode list has no fallback', autoPlayEpisodeFor(series, series.id, []) === null)
|
||||
check(
|
||||
'entry present as another version stays untouched',
|
||||
autoPlayEpisodeFor(
|
||||
media({ id: 'v-4k' }),
|
||||
'v-4k',
|
||||
[media({ id: 'v-4k', versions: [local4k, local1080] })],
|
||||
) === null,
|
||||
)
|
||||
|
||||
console.log('mediaVersion.test.ts: ok')
|
||||
|
||||
@@ -195,6 +195,32 @@ export function mediaVersionSourceLabel(media: Media): string {
|
||||
return isStrmMedia(media) ? '云端直链' : '本地文件'
|
||||
}
|
||||
|
||||
/**
|
||||
* 挑出「播放器该自动跳转到的那一集」。
|
||||
*
|
||||
* 传给 /play/:id 的可能是「整部剧」这类自身没有可播文件的条目——首页轮播、远程 Emby
|
||||
* 剧集库的卡片、剧集详情页的播放按钮都会把剧集 ID 直接交给播放器。这种条目的选集接口
|
||||
* 返回的是它下面的剧集,列表里没有它自己;若直接拿剧集 ID 去请求
|
||||
* /api/stream/<剧集ID>,远程 Emby 会返回 HTTP 500(Unable to cast object of type
|
||||
* 'Series' to type 'IHasMediaSources'),用户看到的就是「播放失败」。此时换成第一集,
|
||||
* 播放、进度、上下集都落在真正可播的条目上。
|
||||
*
|
||||
* 返回 null 表示无需跳转:条目还没加载完、条目本身可播(含以其它版本形式出现在列表里)、
|
||||
* 或该条目下没有任何可选剧集。
|
||||
*/
|
||||
export function autoPlayEpisodeFor(
|
||||
media: Media | null | undefined,
|
||||
requestedId: string,
|
||||
episodes: Media[],
|
||||
): Media | null {
|
||||
if (!media || !requestedId || media.id !== requestedId) return null
|
||||
if (episodes.length === 0) return null
|
||||
if (episodes.some((episode) => mediaVersionMatches(episode, media.id))) return null
|
||||
const first = episodes[0]
|
||||
if (!first?.id || first.id === media.id) return null
|
||||
return first
|
||||
}
|
||||
|
||||
/** 版本文件名(去掉目录,并剥掉 .strm 外层扩展名),用作版本选项的次要说明。 */
|
||||
export function mediaVersionFileName(media: Media): string {
|
||||
const path = (media.path || '').replace(/\\/g, '/').trim()
|
||||
|
||||
Reference in New Issue
Block a user