import {useContext} from 'react'; import System from '@/lib/models/System'; import {SessionContext} from '@/context/SessionContext'; import {LangContext} from '@/context/LangContext'; import {AlertContext} from '@/context/AlertContext'; import OfflineContext from '@/context/OfflineContext'; import {BooksSyncContext} from '@/context/BooksSyncContext'; import {CompleteBook} from '@/lib/models/Book'; import {BookSyncCompare, SyncedBook} from '@/lib/models/SyncedBook'; import {useTranslations} from 'next-intl'; export default function useSyncBooks() { const t = useTranslations(); const {session} = useContext(SessionContext); const {lang} = useContext(LangContext); const {errorMessage} = useContext(AlertContext); const {isCurrentlyOffline, offlineMode} = useContext(OfflineContext); const { booksToSyncToServer, booksToSyncFromServer, localOnlyBooks, serverOnlyBooks, setLocalOnlyBooks, setServerOnlyBooks, setServerSyncedBooks, setLocalSyncedBooks } = useContext(BooksSyncContext); async function upload(bookId: string): Promise { if (isCurrentlyOffline()) return false; try { const bookToSync: CompleteBook = await window.electron.invoke('db:book:uploadToServer', bookId); if (!bookToSync) { errorMessage(t('bookCard.uploadError')); return false; } const response: boolean = await System.authPostToServer('book/sync/upload', { book: bookToSync }, session.accessToken, lang); if (!response) { errorMessage(t('bookCard.uploadError')); return false; } const uploadedBook: SyncedBook | undefined = localOnlyBooks.find((book: SyncedBook): boolean => book.id === bookId); setLocalOnlyBooks((prevBooks: SyncedBook[]): SyncedBook[] => { return prevBooks.filter((book: SyncedBook): boolean => book.id !== bookId); }); if (uploadedBook) { setLocalSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, uploadedBook]); setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, uploadedBook]); } return true; } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('bookCard.uploadError')); } return false; } } async function download(bookId: string): Promise { if (isCurrentlyOffline()) return false; try { const response: CompleteBook = await System.authGetQueryToServer('book/sync/download', session.accessToken, lang, {bookId}); if (!response) { errorMessage(t('bookCard.downloadError')); return false; } const syncStatus: boolean = await window.electron.invoke('db:book:syncSave', response); if (!syncStatus) { errorMessage(t('bookCard.downloadError')); return false; } const downloadedBook: SyncedBook | undefined = serverOnlyBooks.find((book: SyncedBook): boolean => book.id === bookId); setServerOnlyBooks((prevBooks: SyncedBook[]): SyncedBook[] => { return prevBooks.filter((book: SyncedBook): boolean => book.id !== bookId); }); if (downloadedBook) { setLocalSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, downloadedBook]); setServerSyncedBooks((prev: SyncedBook[]): SyncedBook[] => [...prev, downloadedBook]); } return true; } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('bookCard.downloadError')); } return false; } } async function syncFromServer(bookId: string): Promise { if (isCurrentlyOffline()) return false; try { const bookToFetch: BookSyncCompare | undefined = booksToSyncFromServer.find((book: BookSyncCompare): boolean => book.id === bookId); if (!bookToFetch) { errorMessage(t('bookCard.syncFromServerError')); return false; } const response: CompleteBook = await System.authPostToServer('book/sync/server-to-client', { bookToSync: bookToFetch }, session.accessToken, lang); if (!response) { errorMessage(t('bookCard.syncFromServerError')); return false; } const syncStatus: boolean = await window.electron.invoke('db:book:sync:toClient', response); if (!syncStatus) { errorMessage(t('bookCard.syncFromServerError')); return false; } return true; } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('bookCard.syncFromServerError')); } return false; } } async function syncToServer(bookId: string): Promise { if (isCurrentlyOffline()) return false; try { const bookToFetch: BookSyncCompare | undefined = booksToSyncToServer.find((book: BookSyncCompare): boolean => book.id === bookId); if (!bookToFetch) { errorMessage(t('bookCard.syncToServerError')); return false; } const bookToSync: CompleteBook = await window.electron.invoke('db:book:sync:toServer', bookToFetch); if (!bookToSync) { errorMessage(t('bookCard.syncToServerError')); return false; } const response: boolean = await System.authPatchToServer('book/sync/client-to-server', { book: bookToSync }, session.accessToken, lang); if (!response) { errorMessage(t('bookCard.syncToServerError')); return false; } return true; } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('bookCard.syncToServerError')); } return false; } } async function syncAllToServer(): Promise { for (const diff of booksToSyncToServer) { await syncToServer(diff.id); } } async function refreshBooks(): Promise { try { let localBooksResponse: SyncedBook[] = []; let serverBooksResponse: SyncedBook[] = []; if (!isCurrentlyOffline()) { if (offlineMode.isDatabaseInitialized) { localBooksResponse = await window.electron.invoke('db:books:synced'); } serverBooksResponse = await System.authGetQueryToServer('books/synced', session.accessToken, lang); } else { if (offlineMode.isDatabaseInitialized) { localBooksResponse = await window.electron.invoke('db:books:synced'); } } setServerSyncedBooks(serverBooksResponse); setLocalSyncedBooks(localBooksResponse); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('bookCard.refreshError')); } } } return { upload, download, syncFromServer, syncToServer, syncAllToServer, refreshBooks, localOnlyBooks, serverOnlyBooks, booksToSyncToServer, booksToSyncFromServer }; }