Add offline mode logic for chapter operations and refactor IPC handlers
- Integrate `OfflineContext` into `TextEditor` and `ScribeChapterComponent` to handle offline scenarios for chapter CRUD operations. - Add conditional logic to switch between server API requests and offline IPC handlers (`db:chapter:add`, `db:chapter:remove`, `db:chapter:content:save`, `db:chapter:update`). - Refactor and rename IPC handlers (`db:chapter:create` to `db:chapter:add`, `db:chapter:delete` to `db:chapter:remove`) for consistency. - Update UI to disable certain actions when offline (e.g., GhostWriter button).
This commit is contained in:
@@ -30,6 +30,7 @@ import {IconDefinition} from "@fortawesome/fontawesome-svg-core";
|
||||
import UserEditorSettings, {EditorDisplaySettings} from "@/components/editor/UserEditorSetting";
|
||||
import {useTranslations} from "next-intl";
|
||||
import {LangContext, LangContextProps} from "@/context/LangContext";
|
||||
import OfflineContext, {OfflineContextType} from "@/context/OfflineContext";
|
||||
|
||||
interface ToolbarButton {
|
||||
action: () => void;
|
||||
@@ -136,6 +137,7 @@ export default function TextEditor() {
|
||||
const {chapter} = useContext(ChapterContext);
|
||||
const {errorMessage, successMessage} = useContext(AlertContext);
|
||||
const {session} = useContext(SessionContext);
|
||||
const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
|
||||
|
||||
const [mainTimer, setMainTimer] = useState<number>(0);
|
||||
const [showDraftCompanion, setShowDraftCompanion] = useState<boolean>(false);
|
||||
@@ -282,13 +284,24 @@ export default function TextEditor() {
|
||||
const version: number = chapter.chapterContent.version || 0;
|
||||
|
||||
try {
|
||||
const response: boolean = await System.authPostToServer<boolean>(`chapter/content`, {
|
||||
chapterId,
|
||||
version,
|
||||
content,
|
||||
totalWordCount: editor.getText().length,
|
||||
currentTime: mainTimer
|
||||
}, session?.accessToken ?? '');
|
||||
let response: boolean;
|
||||
if (isCurrentlyOffline()){
|
||||
response = await window.electron.invoke<boolean>('db:chapter:content:save',{
|
||||
chapterId,
|
||||
version,
|
||||
content,
|
||||
totalWordCount: editor.getText().length,
|
||||
currentTime: mainTimer
|
||||
})
|
||||
} else {
|
||||
response = await System.authPostToServer<boolean>(`chapter/content`, {
|
||||
chapterId,
|
||||
version,
|
||||
content,
|
||||
totalWordCount: editor.getText().length,
|
||||
currentTime: mainTimer
|
||||
}, session?.accessToken ?? '');
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t('editor.error.savedFailed'));
|
||||
setIsSaving(false);
|
||||
@@ -437,8 +450,7 @@ export default function TextEditor() {
|
||||
onClick={button.action}
|
||||
className={`group flex items-center px-3 py-2 rounded-lg transition-all duration-200 ${button.isActive ? 'bg-primary text-text-primary shadow-md shadow-primary/30 scale-105' : 'text-muted hover:text-text-primary hover:bg-secondary/50 hover:shadow-sm hover:scale-105'}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={button.icon}
|
||||
className={'w-4 h-4 transition-transform duration-200 group-hover:scale-110'}/>
|
||||
<FontAwesomeIcon icon={button.icon} className={'w-4 h-4 transition-transform duration-200 group-hover:scale-110'}/>
|
||||
{
|
||||
button.label &&
|
||||
<span className="ml-2 text-sm font-medium">
|
||||
@@ -455,7 +467,7 @@ export default function TextEditor() {
|
||||
onClick={handleShowUserSettings}
|
||||
icon={faCog}
|
||||
/>
|
||||
{chapter?.chapterContent.version === 2 && (
|
||||
{chapter?.chapterContent.version === 2 && !isCurrentlyOffline() && (
|
||||
<CollapsableButton
|
||||
showCollapsable={showGhostWriter}
|
||||
text={t("textEditor.ghostWriter")}
|
||||
|
||||
@@ -123,11 +123,20 @@ export default function ScribeChapterComponent() {
|
||||
|
||||
async function handleChapterUpdate(chapterId: string, title: string, chapterOrder: number): Promise<void> {
|
||||
try {
|
||||
const response: boolean = await System.authPostToServer<boolean>('chapter/update', {
|
||||
chapterId: chapterId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: title,
|
||||
}, userToken, lang);
|
||||
let response: boolean;
|
||||
if (isCurrentlyOffline()) {
|
||||
response = await window.electron.invoke<boolean>('db:chapter:update',{
|
||||
chapterId: chapterId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: title,
|
||||
})
|
||||
} else {
|
||||
response = await System.authPostToServer<boolean>('chapter/update', {
|
||||
chapterId: chapterId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: title,
|
||||
}, userToken, lang);
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterUpdate"));
|
||||
return;
|
||||
@@ -159,10 +168,14 @@ export default function ScribeChapterComponent() {
|
||||
async function handleDeleteChapter(): Promise<void> {
|
||||
try {
|
||||
setDeleteConfirmationMessage(false);
|
||||
const response: boolean = await System.authDeleteToServer<boolean>('chapter/remove', {
|
||||
bookId: book?.bookId,
|
||||
chapterId: removeChapterId,
|
||||
}, userToken, lang);
|
||||
let response:boolean = false;
|
||||
if (isCurrentlyOffline()) {
|
||||
response = await window.electron.invoke<boolean>('db:chapter:remove', removeChapterId)
|
||||
} else {
|
||||
response = await System.authDeleteToServer<boolean>('chapter/remove', {
|
||||
chapterId: removeChapterId,
|
||||
}, userToken, lang);
|
||||
}
|
||||
if (!response) {
|
||||
errorMessage(t("scribeChapterComponent.errorChapterDelete"));
|
||||
return;
|
||||
@@ -189,7 +202,7 @@ export default function ScribeChapterComponent() {
|
||||
try {
|
||||
let chapterId:string|null = null;
|
||||
if (isCurrentlyOffline()){
|
||||
chapterId = await window.electron.invoke<string>('db:chapter:create', {
|
||||
chapterId = await window.electron.invoke<string>('db:chapter:add', {
|
||||
bookId: book?.bookId,
|
||||
chapterOrder: chapterOrder,
|
||||
title: chapterTitle
|
||||
|
||||
@@ -107,7 +107,7 @@ ipcMain.handle('db:chapter:last', createHandler<string, ChapterProps | null>(
|
||||
);
|
||||
|
||||
// POST /chapter/add - Add new chapter
|
||||
ipcMain.handle('db:chapter:create', createHandler<AddChapterData, string>(
|
||||
ipcMain.handle('db:chapter:add', createHandler<AddChapterData, string>(
|
||||
function(userId: string, data: AddChapterData, lang: 'fr' | 'en'): string {
|
||||
return Chapter.addChapter(userId, data.bookId, data.title, 0, data.chapterOrder, lang);
|
||||
}
|
||||
@@ -115,8 +115,9 @@ ipcMain.handle('db:chapter:create', createHandler<AddChapterData, string>(
|
||||
);
|
||||
|
||||
// DELETE /chapter/remove - Remove chapter
|
||||
ipcMain.handle('db:chapter:delete', createHandler<string, boolean>(
|
||||
ipcMain.handle('db:chapter:remove', createHandler<string, boolean>(
|
||||
function(userId: string, chapterId: string, lang: 'fr' | 'en'): boolean {
|
||||
console.log(userId,chapterId,lang)
|
||||
return Chapter.removeChapter(userId, chapterId, lang);
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user