fix(sync): 丢弃缺少 videoId 的同步记录,避免整页崩溃

服务端同步恢复回来的记录不保证结构完整(旧结构或半截写入)。缺少 videoId
的记录会让 HistoryItem.tsx:24 与 FavoritesItem.tsx:21 在渲染期拼播放地址
时对 undefined 调用 toString(),抛出未捕获异常。由于 getVideoUrl() 是在
渲染 href 时调用的,React 会直接卸载整棵树,首页白屏且刷新无效——该账号
只能靠直接改库才能恢复。

新增 lib/utils/sync-records.ts 做可渲染性判定(要求 videoId、source、
title 齐备),在云端拉取入口 useCloudSync 与 HistoryList / FavoritesList
各过滤一次:脏数据进不来,已经落库的也渲染不出来。
This commit is contained in:
can4hou6joeng4
2026-07-31 18:28:35 +08:00
parent 0675c28413
commit b63f94fed4
4 changed files with 44 additions and 6 deletions
+2 -1
View File
@@ -5,6 +5,7 @@
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[];
@@ -19,7 +20,7 @@ export function FavoritesList({ favorites, onRemove, isPremium = false }: Favori
return (
<div className="flex-1 overflow-y-auto -mx-2 px-2 space-y-2 scroll-smooth">
{favorites.map((item) => (
{keepRenderableFavorites(favorites).map((item) => (
<FavoritesItem
key={`${item.source}:${item.videoId}`}
item={item}
+2 -1
View File
@@ -1,6 +1,7 @@
import { HistoryItem } from './HistoryItem';
import { HistoryEmptyState } from './HistoryEmptyState';
import type { VideoHistoryItem } from '@/lib/types';
import { keepRenderableHistory } from '@/lib/utils/sync-records';
interface HistoryListProps {
history: VideoHistoryItem[];
@@ -18,7 +19,7 @@ export function HistoryList({ history, onRemove, isPremium = false }: HistoryLis
<HistoryEmptyState />
) : (
<div className="space-y-3">
{history.map((item) => (
{keepRenderableHistory(history).map((item) => (
<HistoryItem
key={item.showIdentifier}
item={item}