Files
can4hou6joeng4 b63f94fed4 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
各过滤一次:脏数据进不来,已经落库的也渲染不出来。
2026-07-31 18:28:35 +08:00

68 lines
2.2 KiB
TypeScript

import { useState, useCallback } from 'react';
import { useHistoryStore, usePremiumHistoryStore } from '@/lib/store/history-store';
import { useFavoritesStore, usePremiumFavoritesStore } from '@/lib/store/favorites-store';
import { keepRenderableFavorites, keepRenderableHistory } from '@/lib/utils/sync-records';
import { getProfileId } from '@/lib/store/auth-store';
export function useCloudSync(isPremium = false) {
const [isSyncing, setIsSyncing] = useState(false);
const historyStore = isPremium ? usePremiumHistoryStore : useHistoryStore;
const favoritesStore = isPremium ? usePremiumFavoritesStore : useFavoritesStore;
const pullFromCloud = useCallback(async () => {
const profileId = getProfileId();
if (!profileId) return;
setIsSyncing(true);
try {
const response = await fetch('/api/user/sync');
const result = await response.json();
if (result.success && result.data) {
const history = keepRenderableHistory(result.data.history);
const favorites = keepRenderableFavorites(result.data.favorites);
if (history.length > 0) {
historyStore.getState().importHistory(history);
}
if (favorites.length > 0) {
favoritesStore.getState().importFavorites(favorites);
}
}
} catch (error) {
console.error('Failed to pull from cloud:', error);
} finally {
setIsSyncing(false);
}
}, [historyStore, favoritesStore]);
const pushToCloud = useCallback(async () => {
const profileId = getProfileId();
if (!profileId) return;
setIsSyncing(true);
try {
const currentHistory = historyStore.getState().viewingHistory;
const currentFavorites = favoritesStore.getState().favorites;
await fetch('/api/user/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
history: currentHistory,
favorites: currentFavorites
})
});
} catch (error) {
console.error('Failed to push to cloud:', error);
} finally {
setIsSyncing(false);
}
}, [historyStore, favoritesStore]);
return { pushToCloud, pullFromCloud, isSyncing };
}