forked from akai/readest
This commit is contained in:
@@ -6,11 +6,13 @@ import { useAuth } from '@/context/AuthContext';
|
||||
import { useLibraryStore } from '@/store/libraryStore';
|
||||
import { SYNC_BOOKS_INTERVAL_SEC } from '@/services/constants';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
import { debounce } from '@/utils/debounce';
|
||||
|
||||
export const useBooksSync = () => {
|
||||
const { user } = useAuth();
|
||||
const { appService } = useEnv();
|
||||
const { library, isSyncing, setLibrary, setIsSyncing, setSyncProgress } = useLibraryStore();
|
||||
const { library, isSyncing, libraryLoaded } = useLibraryStore();
|
||||
const { setLibrary, setIsSyncing, setSyncProgress } = useLibraryStore();
|
||||
const { useSyncInited, syncedBooks, syncBooks, lastSyncedAtBooks } = useSync();
|
||||
const isPullingRef = useRef(false);
|
||||
|
||||
@@ -37,11 +39,12 @@ export const useBooksSync = () => {
|
||||
}
|
||||
try {
|
||||
isPullingRef.current = true;
|
||||
await syncBooks([], 'pull');
|
||||
const library = useLibraryStore.getState().library;
|
||||
await syncBooks([], 'pull', libraryLoaded && library.length === 0 ? 0 : undefined);
|
||||
} finally {
|
||||
isPullingRef.current = false;
|
||||
}
|
||||
}, [user, syncBooks]);
|
||||
}, [user, libraryLoaded, syncBooks]);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const handleAutoSync = useCallback(
|
||||
@@ -75,12 +78,11 @@ export const useBooksSync = () => {
|
||||
}, [user, syncBooks, getNewBooks]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user || !useSyncInited) return;
|
||||
if (!user || !useSyncInited || !libraryLoaded) return;
|
||||
pullLibrary();
|
||||
}, [user, useSyncInited, pullLibrary]);
|
||||
}, [user, useSyncInited, libraryLoaded, pullLibrary]);
|
||||
|
||||
const updateLibrary = async () => {
|
||||
if (isSyncing) return;
|
||||
const updateLibrary = useCallback(async () => {
|
||||
if (!syncedBooks?.length) return;
|
||||
|
||||
// Process old books first so that when we update the library the order is preserved
|
||||
@@ -149,12 +151,23 @@ export const useBooksSync = () => {
|
||||
setIsSyncing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updateLibrary();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [syncedBooks]);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const debouncedUpdateLibrary = useCallback(
|
||||
debounce(() => updateLibrary(), 10000),
|
||||
[updateLibrary],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSyncing) {
|
||||
debouncedUpdateLibrary();
|
||||
} else {
|
||||
updateLibrary();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [syncedBooks, updateLibrary, debouncedUpdateLibrary]);
|
||||
|
||||
return { pullLibrary, pushLibrary };
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useSyncContext } from '@/context/SyncContext';
|
||||
import { SyncData, SyncOp, SyncResult, SyncType } from '@/libs/sync';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
@@ -36,7 +37,8 @@ const computeMaxTimestamp = (records: BookDataRecord[]): number => {
|
||||
const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;
|
||||
export function useSync(bookKey?: string) {
|
||||
const router = useRouter();
|
||||
const { settings, setSettings } = useSettingsStore();
|
||||
const { envConfig } = useEnv();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
const { getConfig, setConfig } = useBookDataStore();
|
||||
const { setIsSyncing } = useReaderStore();
|
||||
const config = bookKey ? getConfig(bookKey) : null;
|
||||
@@ -152,6 +154,7 @@ export function useSync(bookKey?: string) {
|
||||
}
|
||||
} finally {
|
||||
setSyncing(false);
|
||||
saveSettings(envConfig, settings);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -175,13 +178,18 @@ export function useSync(bookKey?: string) {
|
||||
};
|
||||
|
||||
const syncBooks = useCallback(
|
||||
async (books?: Book[], op: SyncOp = 'both') => {
|
||||
async (books?: Book[], op: SyncOp = 'both', since?: number) => {
|
||||
if (!lastSyncedAtInited) return;
|
||||
if ((op === 'push' || op === 'both') && books?.length) {
|
||||
await pushChanges({ books });
|
||||
}
|
||||
if (op === 'pull' || op === 'both') {
|
||||
await pullChanges('books', lastSyncedAtBooks + 1, setLastSyncedAtBooks, setSyncingBooks);
|
||||
await pullChanges(
|
||||
'books',
|
||||
since ?? lastSyncedAtBooks + 1,
|
||||
setLastSyncedAtBooks,
|
||||
setSyncingBooks,
|
||||
);
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
@@ -6,6 +6,7 @@ import { md5Fingerprint } from '@/utils/md5';
|
||||
|
||||
interface LibraryState {
|
||||
library: Book[]; // might contain deleted books
|
||||
libraryLoaded: boolean;
|
||||
isSyncing: boolean;
|
||||
syncProgress: number;
|
||||
checkOpenWithBooks: boolean;
|
||||
@@ -36,6 +37,7 @@ interface LibraryState {
|
||||
|
||||
export const useLibraryStore = create<LibraryState>((set, get) => ({
|
||||
library: [],
|
||||
libraryLoaded: false,
|
||||
isSyncing: false,
|
||||
syncProgress: 0,
|
||||
currentBookshelf: [],
|
||||
@@ -56,7 +58,7 @@ export const useLibraryStore = create<LibraryState>((set, get) => ({
|
||||
setCheckLastOpenBooks: (check) => set({ checkLastOpenBooks: check }),
|
||||
setLibrary: (books) => {
|
||||
const { refreshGroups } = get();
|
||||
set({ library: books });
|
||||
set({ library: books, libraryLoaded: true });
|
||||
refreshGroups();
|
||||
},
|
||||
updateBook: async (envConfig: EnvConfigType, book: Book) => {
|
||||
|
||||
Reference in New Issue
Block a user