mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
服务端同步恢复回来的记录不保证结构完整(旧结构或半截写入)。缺少 videoId 的记录会让 HistoryItem.tsx:24 与 FavoritesItem.tsx:21 在渲染期拼播放地址 时对 undefined 调用 toString(),抛出未捕获异常。由于 getVideoUrl() 是在 渲染 href 时调用的,React 会直接卸载整棵树,首页白屏且刷新无效——该账号 只能靠直接改库才能恢复。 新增 lib/utils/sync-records.ts 做可渲染性判定(要求 videoId、source、 title 齐备),在云端拉取入口 useCloudSync 与 HistoryList / FavoritesList 各过滤一次:脏数据进不来,已经落库的也渲染不出来。
34 lines
1.1 KiB
TypeScript
34 lines
1.1 KiB
TypeScript
/**
|
|
* FavoritesList - Scrollable list of favorite items
|
|
*/
|
|
|
|
import type { FavoriteItem } from '@/lib/types';
|
|
import { FavoritesItem } from './FavoritesItem';
|
|
import { FavoritesEmptyState } from './FavoritesEmptyState';
|
|
import { keepRenderableFavorites } from '@/lib/utils/sync-records';
|
|
|
|
interface FavoritesListProps {
|
|
favorites: FavoriteItem[];
|
|
onRemove: (videoId: string | number, source: string) => void;
|
|
isPremium?: boolean;
|
|
}
|
|
|
|
export function FavoritesList({ favorites, onRemove, isPremium = false }: FavoritesListProps) {
|
|
if (favorites.length === 0) {
|
|
return <FavoritesEmptyState />;
|
|
}
|
|
|
|
return (
|
|
<div className="flex-1 overflow-y-auto -mx-2 px-2 space-y-2 scroll-smooth">
|
|
{keepRenderableFavorites(favorites).map((item) => (
|
|
<FavoritesItem
|
|
key={`${item.source}:${item.videoId}`}
|
|
item={item}
|
|
onRemove={() => onRemove(item.videoId, item.source)}
|
|
isPremium={isPremium}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|