播放记录显示直链播放的链接
This commit is contained in:
@@ -21,6 +21,7 @@ interface MobileActionSheetProps {
|
|||||||
sources?: string[]; // 播放源信息
|
sources?: string[]; // 播放源信息
|
||||||
isAggregate?: boolean; // 是否为聚合内容
|
isAggregate?: boolean; // 是否为聚合内容
|
||||||
sourceName?: string; // 播放源名称
|
sourceName?: string; // 播放源名称
|
||||||
|
directLinkUrl?: string; // 直链播放完整链接
|
||||||
currentEpisode?: number; // 当前集数
|
currentEpisode?: number; // 当前集数
|
||||||
totalEpisodes?: number; // 总集数
|
totalEpisodes?: number; // 总集数
|
||||||
origin?: 'vod' | 'live';
|
origin?: 'vod' | 'live';
|
||||||
@@ -36,6 +37,7 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
|
|||||||
sources,
|
sources,
|
||||||
isAggregate,
|
isAggregate,
|
||||||
sourceName,
|
sourceName,
|
||||||
|
directLinkUrl,
|
||||||
currentEpisode,
|
currentEpisode,
|
||||||
totalEpisodes,
|
totalEpisodes,
|
||||||
origin = 'vod',
|
origin = 'vod',
|
||||||
@@ -253,6 +255,11 @@ const MobileActionSheet: React.FC<MobileActionSheetProps> = ({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{directLinkUrl && (
|
||||||
|
<p className="mb-2 text-xs text-gray-500 dark:text-gray-400 break-all">
|
||||||
|
{directLinkUrl}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
选择操作
|
选择操作
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
saveFavorite,
|
saveFavorite,
|
||||||
subscribeToDataUpdates,
|
subscribeToDataUpdates,
|
||||||
} from '@/lib/db.client';
|
} from '@/lib/db.client';
|
||||||
import { processImageUrl } from '@/lib/utils';
|
import { processImageUrl, base58Decode } from '@/lib/utils';
|
||||||
import { useLongPress } from '@/hooks/useLongPress';
|
import { useLongPress } from '@/hooks/useLongPress';
|
||||||
|
|
||||||
import AIChatPanel from '@/components/AIChatPanel';
|
import AIChatPanel from '@/components/AIChatPanel';
|
||||||
@@ -172,6 +172,14 @@ const VideoCard = forwardRef<VideoCardHandle, VideoCardProps>(function VideoCard
|
|||||||
const actualQuery = query || '';
|
const actualQuery = query || '';
|
||||||
const actualSearchType = type;
|
const actualSearchType = type;
|
||||||
const isDirectPlaySource = actualSource === 'directplay';
|
const isDirectPlaySource = actualSource === 'directplay';
|
||||||
|
const directLinkUrl = useMemo(() => {
|
||||||
|
if (!isDirectPlaySource || !actualId) return '';
|
||||||
|
try {
|
||||||
|
return base58Decode(actualId);
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}, [isDirectPlaySource, actualId]);
|
||||||
const displayYear = useMemo(() => {
|
const displayYear = useMemo(() => {
|
||||||
if (!actualYear) return '';
|
if (!actualYear) return '';
|
||||||
const normalized = actualYear.trim();
|
const normalized = actualYear.trim();
|
||||||
@@ -938,6 +946,38 @@ const VideoCard = forwardRef<VideoCardHandle, VideoCardProps>(function VideoCard
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 竖向模式:顶部直链地址显示 */}
|
||||||
|
{orientation === 'vertical' && isDirectPlaySource && directLinkUrl && (
|
||||||
|
<div
|
||||||
|
className='absolute top-1 left-1 right-1 sm:top-2 sm:left-2 sm:right-2 pt-1 px-1 sm:pt-2 sm:px-2'
|
||||||
|
style={{
|
||||||
|
WebkitUserSelect: 'none',
|
||||||
|
userSelect: 'none',
|
||||||
|
WebkitTouchCallout: 'none',
|
||||||
|
} as React.CSSProperties}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className='text-[9px] sm:text-[10px] text-yellow-400 line-clamp-2 break-all'
|
||||||
|
style={{
|
||||||
|
WebkitUserSelect: 'none',
|
||||||
|
userSelect: 'none',
|
||||||
|
WebkitTouchCallout: 'none',
|
||||||
|
} as React.CSSProperties}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
title={directLinkUrl}
|
||||||
|
>
|
||||||
|
{directLinkUrl}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{actualEpisodes && actualEpisodes > 1 && orientation === 'vertical' && (
|
{actualEpisodes && actualEpisodes > 1 && orientation === 'vertical' && (
|
||||||
<div
|
<div
|
||||||
className='absolute top-1 right-1 sm:top-2 sm:right-2 flex flex-col gap-0.5 sm:gap-1.5'
|
className='absolute top-1 right-1 sm:top-2 sm:right-2 flex flex-col gap-0.5 sm:gap-1.5'
|
||||||
@@ -1249,6 +1289,25 @@ const VideoCard = forwardRef<VideoCardHandle, VideoCardProps>(function VideoCard
|
|||||||
第{currentEpisode}集 · 共{actualEpisodes}集
|
第{currentEpisode}集 · 共{actualEpisodes}集
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 直链地址 */}
|
||||||
|
{isDirectPlaySource && directLinkUrl && (
|
||||||
|
<div
|
||||||
|
className='text-[10px] text-white/75 truncate'
|
||||||
|
style={{
|
||||||
|
WebkitUserSelect: 'none',
|
||||||
|
userSelect: 'none',
|
||||||
|
WebkitTouchCallout: 'none',
|
||||||
|
} as React.CSSProperties}
|
||||||
|
onContextMenu={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
title={directLinkUrl}
|
||||||
|
>
|
||||||
|
{directLinkUrl}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 底部渐变遮罩 - 用于进度条背景 */}
|
{/* 底部渐变遮罩 - 用于进度条背景 */}
|
||||||
@@ -1487,6 +1546,7 @@ const VideoCard = forwardRef<VideoCardHandle, VideoCardProps>(function VideoCard
|
|||||||
sources={isAggregate && dynamicSourceNames ? Array.from(new Set(dynamicSourceNames)) : undefined}
|
sources={isAggregate && dynamicSourceNames ? Array.from(new Set(dynamicSourceNames)) : undefined}
|
||||||
isAggregate={isAggregate}
|
isAggregate={isAggregate}
|
||||||
sourceName={cmsData ? undefined : source_name}
|
sourceName={cmsData ? undefined : source_name}
|
||||||
|
directLinkUrl={directLinkUrl || undefined}
|
||||||
currentEpisode={currentEpisode}
|
currentEpisode={currentEpisode}
|
||||||
totalEpisodes={actualEpisodes}
|
totalEpisodes={actualEpisodes}
|
||||||
origin={origin}
|
origin={origin}
|
||||||
|
|||||||
Reference in New Issue
Block a user