Files
natreex 5c7e71ce9e Bump app version to 0.5.1 and add auto-update support
- Implemented auto-update logic in `ScribeTopBar` with update notification and user interaction.
- Integrated `@tauri-apps/plugin-updater` and `@tauri-apps/plugin-process` for updater functionality.
- Added automatic migration feature with `autoMigrateElectron` support and UI feedback.
- Refactored app architecture with new routing, components, and layout for better modularity.
- Enhanced JSON response handling in API client for robust data parsing.
- Updated locales to include new translations for update and migration-related UI.
2026-04-07 16:09:35 -04:00

87 lines
3.9 KiB
TypeScript

'use client';
import React, {ReactNode, useContext, useEffect} from 'react';
import {useParams} from '@/lib/navigation';
import {BookContext, BookContextProps} from '@/context/BookContext';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import {apiGet} from '@/lib/api/client';
import {isDesktop} from '@/lib/configs';
import * as tauri from '@/lib/tauri';
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
import {BookProps} from '@/lib/types/book';
import {useTranslations} from '@/lib/i18n';
import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext';
import {SyncedBook} from '@/lib/types/synced-book';
export default function BookLayout({children}: { children: ReactNode }) {
const params: { bookId: string } = useParams<{ bookId: string }>();
const {book, setBook}: BookContextProps = useContext<BookContextProps>(BookContext);
const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
const {errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
const {isCurrentlyOffline}: OfflineContextType = useContext<OfflineContextType>(OfflineContext);
const {localOnlyBooks}: BooksSyncContextProps = useContext<BooksSyncContextProps>(BooksSyncContext);
const t = useTranslations();
useEffect((): void => {
if (session.accessToken && params.bookId) {
if (!book || book.bookId !== params.bookId) {
fetchBook().then();
}
}
}, [params.bookId, session.accessToken]);
async function fetchBook(): Promise<void> {
try {
let localBookOnly: boolean = false;
let bookResponse: BookProps | null = null;
if (isCurrentlyOffline()) {
bookResponse = await tauri.getBookBasicInformation(params.bookId);
if (bookResponse) localBookOnly = true;
} else {
const isOfflineBook = localOnlyBooks.find((b: SyncedBook): boolean => b.id === params.bookId);
if (isOfflineBook) {
bookResponse = await tauri.getBookBasicInformation(params.bookId);
localBookOnly = true;
}
if (!bookResponse) {
bookResponse = await apiGet<BookProps>(
'book/basic-information', session.accessToken, lang, {id: params.bookId}
);
}
}
if (!bookResponse) {
errorMessage(t('controllerBar.bookNotFound'));
return;
}
setBook({
bookId: bookResponse.bookId,
type: bookResponse.type,
title: bookResponse.title,
subTitle: bookResponse.subTitle,
summary: bookResponse.summary,
publicationDate: bookResponse.publicationDate,
desiredWordCount: bookResponse.desiredWordCount,
totalWordCount: bookResponse.totalWordCount ?? 0,
quillsenseEnabled: bookResponse.quillsenseEnabled,
tools: bookResponse.tools,
seriesId: bookResponse.seriesId,
serie: bookResponse.serie,
coverImage: bookResponse.coverImage ? 'data:image/jpeg;base64,' + bookResponse.coverImage : '',
localBook: localBookOnly,
});
} catch (e: unknown) {
if (e instanceof Error) {
errorMessage(e.message);
} else {
errorMessage(t('controllerBar.unknownBookError'));
}
}
}
return <>{children}</>;
}