Integrate offline support and improve error handling across app

- Add `OfflineContext` to manage offline state and interactions within components.
- Refactor session logic in `ScribeControllerBar` and `page.tsx` to handle offline scenarios (e.g., check connectivity before enabling GPT features).
- Enhance offline PIN setup and verification with better flow and error messaging.
- Optimize database IPC handlers to initialize and sync data in offline mode.
- Refactor code to clean up redundant logs and ensure stricter typings.
- Improve consistency and structure in handling online and offline operations for smoother user experience.
This commit is contained in:
natreex
2025-11-26 15:25:53 -05:00
parent 5cceceaea9
commit ac95e00127
10 changed files with 95 additions and 159 deletions

View File

@@ -17,6 +17,7 @@ import {useTranslations} from "next-intl";
import {LangContext, LangContextProps} from "@/context/LangContext";
import CreditCounter from "@/components/CreditMeters";
import QuillSense from "@/lib/models/QuillSense";
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";
export default function ScribeControllerBar() {
const {chapter, setChapter} = useContext(ChapterContext);
@@ -24,12 +25,13 @@ export default function ScribeControllerBar() {
const {errorMessage} = useContext(AlertContext)
const {session} = useContext(SessionContext);
const t = useTranslations();
const {lang, setLang} = useContext<LangContextProps>(LangContext)
const {lang, setLang} = useContext<LangContextProps>(LangContext);
const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext)
const isGPTEnabled: boolean = QuillSense.isOpenAIEnabled(session);
const isGemini: boolean = QuillSense.isOpenAIEnabled(session);
const isAnthropic: boolean = QuillSense.isOpenAIEnabled(session);
const isSubTierTwo: boolean = QuillSense.getSubLevel(session) >= 2;
const isGPTEnabled: boolean = !isCurrentlyOffline() && QuillSense.isOpenAIEnabled(session);
const isGemini: boolean = !isCurrentlyOffline() && QuillSense.isOpenAIEnabled(session);
const isAnthropic: boolean = !isCurrentlyOffline() && QuillSense.isOpenAIEnabled(session);
const isSubTierTwo: boolean = !isCurrentlyOffline() && QuillSense.getSubLevel(session) >= 2;
const hasAccess: boolean = (isGPTEnabled || isAnthropic || isGemini) || isSubTierTwo;
const [showSettingPanel, setShowSettingPanel] = useState<boolean>(false);

View File

@@ -146,13 +146,14 @@ export default function AddNewBookForm({setCloseForm}: { setCloseForm: Dispatch<
publicationDate: publicationDate,
desiredWordCount: wordCount,
}, token, lang);
if (!bookId) {
throw new Error(t('addNewBookForm.error.addingBook'));
}
} else {
// Offline - call local database
bookId = await window.electron.invoke<string>('db:book:create', bookData);
}
if (!bookId) {
errorMessage(t('addNewBookForm.error.addingBook'))
return;
}
const book: BookProps = {
bookId: bookId,

View File

@@ -172,12 +172,14 @@ export default function BookList() {
async function getBook(bookId: string): Promise<void> {
try {
const bookResponse: BookListProps = await System.authGetQueryToServer<BookListProps>(
`book/basic-information`,
accessToken,
lang,
{id: bookId}
);
let bookResponse: BookListProps|null = null;
if (isCurrentlyOffline()){
bookResponse = await window.electron.invoke('db:book:bookBasicInformation', bookId)
} else {
bookResponse = await System.authGetQueryToServer<BookListProps>(`book/basic-information`, accessToken, lang, {
id: bookId
});
}
if (!bookResponse) {
errorMessage(t("bookList.errorBookDetails"));
return;

View File

@@ -398,7 +398,6 @@ export default function TextEditor() {
const parsedContent = JSON.parse(chapter.chapterContent.content);
editor.commands.setContent(parsedContent);
} catch (error) {
console.error('Erreur lors du parsing du contenu:', error);
editor.commands.setContent({
type: "doc",
content: [{type: "paragraph", content: []}]