fix(sync): retry sync books for previous failed sync, closes #2441 (#2462)

This commit is contained in:
Huang Xin
2025-11-17 23:22:48 +05:30
committed by GitHub
parent c42fcf9ac4
commit 0fd316d775
7 changed files with 39 additions and 10 deletions
@@ -18,7 +18,10 @@ export const useBooksSync = () => {
if (!user) return {};
const library = useLibraryStore.getState().library;
const newBooks = library.filter(
(book) => lastSyncedAtBooks < book.updatedAt || lastSyncedAtBooks < (book.deletedAt ?? 0),
(book) =>
!book.syncedAt ||
lastSyncedAtBooks < book.updatedAt ||
lastSyncedAtBooks < (book.deletedAt ?? 0),
);
return {
books: newBooks,
@@ -67,7 +70,9 @@ export const useBooksSync = () => {
const pushLibrary = useCallback(async () => {
if (!user) return;
const newBooks = getNewBooks();
await syncBooks(newBooks?.books, 'push');
if (newBooks.lastSyncedAt) {
await syncBooks(newBooks?.books, 'push');
}
}, [user, syncBooks, getNewBooks]);
useEffect(() => {
@@ -95,8 +100,8 @@ export const useBooksSync = () => {
}
const mergedBook =
matchingBook.updatedAt > oldBook.updatedAt
? { ...oldBook, ...matchingBook }
: { ...matchingBook, ...oldBook };
? { ...oldBook, ...matchingBook, syncedAt: Date.now() }
: { ...matchingBook, ...oldBook, syncedAt: Date.now() };
return mergedBook;
}
return oldBook;
@@ -117,6 +122,7 @@ export const useBooksSync = () => {
const processNewBook = async (newBook: Book) => {
newBook.coverImageUrl = await appService?.generateCoverImageUrl(newBook);
newBook.syncedAt = Date.now();
updatedLibrary.push(newBook);
};
@@ -131,9 +131,13 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
clearViewState(bookKey);
};
const navigateBackToLibrary = () => {
navigateToLibrary(router, '', undefined, true);
};
const saveSettingsAndGoToLibrary = () => {
saveSettings(envConfig, settings);
navigateToLibrary(router);
navigateBackToLibrary();
};
const handleCloseBooks = throttle(async () => {
@@ -147,12 +151,12 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
if (isTauriAppPlatform()) {
const currentWindow = getCurrentWindow();
if (currentWindow.label === 'main') {
navigateToLibrary(router);
navigateBackToLibrary();
} else {
currentWindow.close();
}
} else {
navigateToLibrary(router);
navigateBackToLibrary();
}
};
+12 -1
View File
@@ -2,8 +2,9 @@
import '@/utils/polyfill';
import i18n from '@/i18n/i18n';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';
import { IconContext } from 'react-icons';
import { usePathname } from 'next/navigation';
import { AuthProvider } from '@/context/AuthContext';
import { useEnv } from '@/context/EnvContext';
import { CSPostHogProvider } from '@/context/PHContext';
@@ -27,6 +28,16 @@ const Providers = ({ children }: { children: React.ReactNode }) => {
const iconSize = useDefaultIconSize();
useSafeAreaInsets(); // Initialize safe area insets
const pathname = usePathname();
const prevPathnameRef = useRef<string | null>(null);
useEffect(() => {
if (prevPathnameRef.current !== null) {
sessionStorage.setItem('lastPath', prevPathnameRef.current);
}
prevPathnameRef.current = pathname;
}, [pathname]);
useEffect(() => {
const handlerLanguageChanged = (lng: string) => {
document.documentElement.lang = lng;
@@ -65,7 +65,7 @@ export const usePullToRefresh = (ref: React.RefObject<HTMLDivElement>, onTrigger
const headerbar = document.querySelector('.titlebar');
const pullIndicator = document.createElement('div');
const headerBottom = headerbar?.getBoundingClientRect().bottom || 0;
pullIndicator.style.top = `${headerBottom + 20}px`;
pullIndicator.style.top = `${headerBottom + 30}px`;
pullIndicator.className = 'pull-indicator text-gray-500';
pullIndicator.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
+1 -1
View File
@@ -75,7 +75,7 @@ export const useBookDataStore = create<BookDataState>((set, get) => ({
book.updatedAt = Date.now();
book.downloadedAt = book.downloadedAt || Date.now();
library.unshift(book);
setLibrary(library);
setLibrary([...library]);
config.updatedAt = Date.now();
await appService.saveBookConfig(book, config, settings);
await appService.saveLibraryBooks(library);
+1
View File
@@ -34,6 +34,7 @@ export interface Book {
uploadedAt?: number | null;
downloadedAt?: number | null;
coverDownloadedAt?: number | null;
syncedAt?: number | null;
lastUpdated?: number; // deprecated in favor of updatedAt
progress?: [number, number]; // Add progress field: [current, total], 1-based page number
+7
View File
@@ -80,7 +80,14 @@ export const navigateToLibrary = (
router: ReturnType<typeof useRouter>,
queryParams?: string,
navOptions?: { scroll?: boolean },
navBack?: boolean,
) => {
const lastPath = typeof window !== 'undefined' ? sessionStorage.getItem('lastPath') : null;
if (navBack && lastPath === '/library') {
router.back();
return;
}
router.replace(`/library${queryParams ? `?${queryParams}` : ''}`, navOptions);
};