mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 11:36:36 +08:00
38b85bb487
* feat(strm): 同名多版本择优/keep_ext,并支持合并展示与播放切换 默认对同名不同扩展(如 .mkv/.mp4)按体积→mtime→扩展名优先级择优生成一条 strm,冲突打日志;开启 keep_ext 则分别生成 name.ext.strm。媒体详情与播放器可切换版本,列表继续合并同片多版本,Emby MediaSources 名称区分容器/分辨率。 Co-authored-by: truewhile <truewhile@users.noreply.github.com> * fix(meta): 边车匹配忽略 .mkv.strm 中间扩展,同片共享 NFO/海报/字幕 NFO、海报、字幕与刮削写出统一使用 mediaSidecarBase 词干,使竞女01.mkv.strm 与竞女01.mp4.strm 配对同一套 竞女01.nfo / 竞女01-poster / 竞女01.srt; 仍兼容历史上的 name.mkv.nfo 命名。 Co-authored-by: truewhile <truewhile@users.noreply.github.com> * fix(emby): People NFO 按共享词干匹配 keep_ext strm resolveMediaPeople 改为查找竞女01.nfo(并兼容旧的竞女01.mkv.nfo), 同时修正把 decodeNFOFile 的 partial 误当 ok 导致完整 NFO 被跳过的问题。 Co-authored-by: truewhile <truewhile@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import { Layers } from 'lucide-react'
|
||
import { Link } from 'react-router-dom'
|
||
|
||
import type { Media } from '../types'
|
||
import { mediaVersionLabel, mediaVersionsOf } from '../utils/mediaVersion'
|
||
|
||
type MediaVersionSwitcherProps = {
|
||
media: Media
|
||
/** 详情页:用 Link 跳转播放;播放页:回调切换 */
|
||
mode?: 'detail' | 'player'
|
||
onSelect?: (version: Media) => void
|
||
className?: string
|
||
}
|
||
|
||
export function MediaVersionSwitcher({
|
||
media,
|
||
mode = 'detail',
|
||
onSelect,
|
||
className = '',
|
||
}: MediaVersionSwitcherProps) {
|
||
const versions = mediaVersionsOf(media)
|
||
if (versions.length <= 1) return null
|
||
const dark = mode === 'player'
|
||
|
||
return (
|
||
<div className={`space-y-2 ${className}`.trim()}>
|
||
<div className={`flex items-center gap-2 text-sm font-semibold ${dark ? 'text-white/90' : 'text-ink-600'}`}>
|
||
<Layers size={14} className={dark ? 'text-white/60' : 'text-sand-500'} />
|
||
<span>版本({versions.length})</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-2">
|
||
{versions.map((version) => {
|
||
const active = version.id === media.id
|
||
const label = mediaVersionLabel(version)
|
||
const className = dark
|
||
? active
|
||
? 'border-white/40 bg-white/20 text-white'
|
||
: 'border-white/15 bg-white/5 text-white/80 hover:bg-white/15'
|
||
: active
|
||
? 'border-brand-500/40 bg-brand-50 text-[#b07d35]'
|
||
: 'border-gray-200 bg-white text-ink-100 hover:border-brand-500/30 hover:bg-brand-50/40'
|
||
if (mode === 'player') {
|
||
return (
|
||
<button
|
||
key={version.id}
|
||
type="button"
|
||
disabled={active}
|
||
onClick={() => onSelect?.(version)}
|
||
className={`rounded-xl border px-3 py-1.5 text-xs font-semibold transition disabled:cursor-default ${className}`}
|
||
title={version.path}
|
||
>
|
||
{label}
|
||
</button>
|
||
)
|
||
}
|
||
return (
|
||
<Link
|
||
key={version.id}
|
||
to={`/play/${version.id}`}
|
||
state={{ from: `/media/${media.id}` }}
|
||
className={`rounded-xl border px-3 py-1.5 text-xs font-semibold transition ${className}`}
|
||
title={version.path}
|
||
>
|
||
{label}
|
||
{active ? ' · 当前' : ''}
|
||
</Link>
|
||
)
|
||
})}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|