Add offline mode logic for book, story, and world operations

- Integrate `OfflineContext` into book, story settings, and related components.
- Add conditional logic to toggle between server API requests and offline IPC handlers (`db:book:delete`, `db:book:story:get`, `db:location:all`, etc.).
- Refactor and update IPC handlers to accept structured data arguments for improved consistency (`data: object`).
- Ensure stricter typings in IPC handlers and frontend functions.
- Improve error handling and user feedback in both online and offline modes.
This commit is contained in:
natreex
2025-11-26 22:52:34 -05:00
parent e1abcd9490
commit 23f1592c22
15 changed files with 518 additions and 201 deletions

View File

@@ -111,10 +111,13 @@ ipcMain.handle('db:book:updateBasicInformation', createHandler<UpdateBookBasicDa
);
// GET /book/guide-line - Get guideline
interface GetGuidelineData {
id: string;
}
ipcMain.handle(
'db:book:guideline:get',
createHandler<string, GuideLine | null>(async function(userId: string, bookId: string, lang: 'fr' | 'en') {
return await Book.getGuideLine(userId, bookId, lang);
createHandler<GetGuidelineData, GuideLine | null>(async function(userId: string, data: GetGuidelineData, lang: 'fr' | 'en') {
return await Book.getGuideLine(userId, data.id, lang);
}
)
);
@@ -142,10 +145,13 @@ ipcMain.handle('db:book:guideline:update', createHandler<UpdateGuideLineData, bo
);
// GET /book/story - Get story data (acts + issues)
ipcMain.handle('db:book:story:get', createHandler<string, StoryData>(
async function(userId: string, bookId: string, lang: 'fr' | 'en'):Promise<StoryData> {
const acts:Act[] = await Book.getActsData(userId, bookId, lang);
const issues:Issue[] = await Book.getIssuesFromBook(userId, bookId, lang);
interface GetStoryData {
bookid: string;
}
ipcMain.handle('db:book:story:get', createHandler<GetStoryData, StoryData>(
async function(userId: string, data: GetStoryData, lang: 'fr' | 'en'):Promise<StoryData> {
const acts:Act[] = await Book.getActsData(userId, data.bookid, lang);
const issues:Issue[] = await Book.getIssuesFromBook(userId, data.bookid, lang);
return {
acts,
issues
@@ -220,11 +226,14 @@ ipcMain.handle('db:book:plot:add', createHandler<AddPlotPointData, string>(
);
// DELETE /book/plot/remove - Remove plot point
interface RemovePlotData {
plotId: string;
}
ipcMain.handle(
'db:book:plot:remove',
createHandler<string, boolean>(
function(userId: string, plotPointId: string, lang: 'fr' | 'en') {
return Book.removePlotPoint(userId, plotPointId, lang);
createHandler<RemovePlotData, boolean>(
function(userId: string, data: RemovePlotData, lang: 'fr' | 'en') {
return Book.removePlotPoint(userId, data.plotId, lang);
}
)
);
@@ -238,17 +247,24 @@ ipcMain.handle('db:book:issue:add', createHandler<AddIssueData, string>(
);
// DELETE /book/issue/remove - Remove issue
ipcMain.handle('db:book:issue:remove', createHandler<string, boolean>(
function(userId: string, issueId: string, lang: 'fr' | 'en') {
return Book.removeIssue(userId, issueId, lang);
interface RemoveIssueData {
bookId: string;
issueId: string;
}
ipcMain.handle('db:book:issue:remove', createHandler<RemoveIssueData, boolean>(
function(userId: string, data: RemoveIssueData, lang: 'fr' | 'en') {
return Book.removeIssue(userId, data.issueId, lang);
}
)
);
// GET /book/worlds - Get worlds for book
ipcMain.handle('db:book:worlds:get', createHandler<string, WorldProps[]>(
function(userId: string, bookId: string, lang: 'fr' | 'en') {
return Book.getWorlds(userId, bookId, lang);
interface GetWorldsData {
bookid: string;
}
ipcMain.handle('db:book:worlds:get', createHandler<GetWorldsData, WorldProps[]>(
function(userId: string, data: GetWorldsData, lang: 'fr' | 'en') {
return Book.getWorlds(userId, data.bookid, lang);
}
)
);
@@ -275,25 +291,34 @@ ipcMain.handle('db:book:world:element:add', createHandler<AddWorldElementData, s
)
);
// DELETE /book/world/element/delete - Remove element from world
ipcMain.handle('db:book:world:element:remove', createHandler<string, boolean>(
function(userId: string, elementId: string, lang: 'fr' | 'en') {
return Book.removeElementFromWorld(userId, elementId, lang);
interface RemoveWorldElementData {
elementId: string;
}
ipcMain.handle('db:book:world:element:remove', createHandler<RemoveWorldElementData, boolean>(
function(userId: string, data: RemoveWorldElementData, lang: 'fr' | 'en') {
return Book.removeElementFromWorld(userId, data.elementId, lang);
}
)
);
// DELETE /book/delete - Delete book
ipcMain.handle('db:book:delete', createHandler<string, boolean>(
function(userId: string, bookId: string, lang: 'fr' | 'en') {
return Book.removeBook(userId, bookId, lang);
interface DeleteBookData {
id: string;
}
ipcMain.handle('db:book:delete', createHandler<DeleteBookData, boolean>(
function(userId: string, data: DeleteBookData, lang: 'fr' | 'en') {
return Book.removeBook(userId, data.id, lang);
}
)
);
// GET /book/ai/guideline - Get AI guideline
ipcMain.handle('db:book:guideline:ai:get', createHandler<string, GuideLineAI>(
function(userId: string, bookId: string, lang: 'fr' | 'en') {
return Book.getGuideLineAI(userId, bookId, lang);
interface GetAIGuidelineData {
id: string;
}
ipcMain.handle('db:book:guideline:ai:get', createHandler<GetAIGuidelineData, GuideLineAI>(
function(userId: string, data: GetAIGuidelineData, lang: 'fr' | 'en') {
return Book.getGuideLineAI(userId, data.id, lang);
}
)
);