- Introduce new error messages for syncing and book deletion in `en.json`. - Update `DeleteBook` to support local-only deletion and synced book management. - Refine offline/online behavior with `deleteLocalToo` checkbox and update related state handling. - Extend repository and IPC methods to handle optional IDs for updates. - Add `SyncQueueContext` for queueing offline changes and improving synchronization workflows. - Enhance refined text generation logic in `DraftCompanion` and `GhostWriter` components. - Replace PUT with PATCH for world updates to align with API expectations. - Streamline `AlertBox` by integrating dynamic translation keys for deletion prompts.
406 lines
13 KiB
TypeScript
406 lines
13 KiB
TypeScript
import { ipcMain } from 'electron';
|
|
import { createHandler } from '../database/LocalSystem.js';
|
|
import Book, {BookSyncCompare, CompleteBook, SyncedBook} from '../database/models/Book.js';
|
|
import type { BookProps, GuideLine, GuideLineAI, Act, Issue, WorldProps } from '../database/models/Book.js';
|
|
import Chapter from '../database/models/Chapter.js';
|
|
import type { ChapterProps } from '../database/models/Chapter.js';
|
|
|
|
interface UpdateBookBasicData {
|
|
title: string;
|
|
subTitle: string;
|
|
summary: string;
|
|
publicationDate: string;
|
|
wordCount: number;
|
|
bookId: string;
|
|
}
|
|
|
|
interface UpdateGuideLineData {
|
|
bookId: string;
|
|
tone: string | null;
|
|
atmosphere: string | null;
|
|
writingStyle: string | null;
|
|
themes: string | null;
|
|
symbolism: string | null;
|
|
motifs: string | null;
|
|
narrativeVoice: string | null;
|
|
pacing: string | null;
|
|
keyMessages: string | null;
|
|
intendedAudience: string | null;
|
|
}
|
|
|
|
interface StoryData {
|
|
acts: Act[];
|
|
issues: Issue[];
|
|
mainChapter: ChapterProps[];
|
|
}
|
|
|
|
interface UpdateStoryData {
|
|
bookId: string;
|
|
acts: Act[];
|
|
mainChapters: ChapterProps[];
|
|
}
|
|
|
|
interface CreateBookData {
|
|
title: string;
|
|
subTitle: string | null;
|
|
summary: string | null;
|
|
type: string;
|
|
serieId: number | null;
|
|
desiredReleaseDate: string | null;
|
|
desiredWordCount: number | null;
|
|
}
|
|
|
|
interface AddIncidentData {
|
|
bookId: string;
|
|
name: string;
|
|
incidentId?: string;
|
|
}
|
|
|
|
interface AddPlotPointData {
|
|
bookId: string;
|
|
name: string;
|
|
incidentId: string;
|
|
plotPointId?: string;
|
|
}
|
|
|
|
interface AddIssueData {
|
|
bookId: string;
|
|
name: string;
|
|
issueId?: string;
|
|
}
|
|
|
|
interface AddWorldData {
|
|
bookId: string;
|
|
worldName: string;
|
|
id?: string;
|
|
}
|
|
|
|
interface AddWorldElementData {
|
|
worldId: string;
|
|
elementName: string;
|
|
elementType: number;
|
|
id?: string;
|
|
}
|
|
|
|
interface SetAIGuideLineData {
|
|
bookId: string;
|
|
narrativeType: number;
|
|
dialogueType: number;
|
|
plotSummary: string;
|
|
toneAtmosphere: string;
|
|
verbTense: number;
|
|
language: number;
|
|
themes: string;
|
|
}
|
|
|
|
interface GetGuidelineData {
|
|
id: string;
|
|
}
|
|
|
|
// GET /books - Get all books
|
|
ipcMain.handle('db:book:books', createHandler<void, BookProps[]>(
|
|
async function(userId: string, _body: void, lang: 'fr' | 'en'):Promise<BookProps[]> {
|
|
return await Book.getBooks(userId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET /books/synced - Get all synced books
|
|
ipcMain.handle('db:books:synced', createHandler<void, SyncedBook[]>(
|
|
async function(userId: string, _body: void, lang: 'fr' | 'en'):Promise<SyncedBook[]> {
|
|
return await Book.getSyncedBooks(userId, lang);
|
|
})
|
|
);
|
|
|
|
// POST /book/sync/save - Save complete book
|
|
ipcMain.handle('db:book:syncSave', createHandler<CompleteBook, boolean>(
|
|
async function(userId: string, data: CompleteBook, lang: 'fr' | 'en'):Promise<boolean> {
|
|
return await Book.saveCompleteBook(userId, data, lang);
|
|
})
|
|
);
|
|
|
|
// GET /book/:id - Get single book
|
|
ipcMain.handle('db:book:bookBasicInformation', createHandler<string, BookProps>(
|
|
async function(userId: string, bookId: string, lang: 'fr' | 'en'):Promise<BookProps> {
|
|
return await Book.getBook(userId, bookId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET
|
|
ipcMain.handle('db:book:uploadToServer', createHandler<string, CompleteBook>(
|
|
async function(userId: string, bookId: string, lang: 'fr' | 'en'):Promise<CompleteBook> {
|
|
return await Book.uploadBookForSync(userId, bookId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/basic-information - Update book basic info
|
|
ipcMain.handle('db:book:updateBasicInformation', createHandler<UpdateBookBasicData, boolean>(
|
|
function(userId: string, data: UpdateBookBasicData, lang: 'fr' | 'en') {
|
|
return Book.updateBookBasicInformation(userId, data.title, data.subTitle, data.summary, data.publicationDate, data.wordCount, data.bookId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET /book/sync/to-client - Get book data to sync to client
|
|
ipcMain.handle('db:book:sync:toServer', createHandler<BookSyncCompare, CompleteBook>(
|
|
async function(userId: string, data:BookSyncCompare, lang: 'fr' | 'en'):Promise<CompleteBook> {
|
|
return await Book.getCompleteSyncBook(userId, data, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET /book/sync/from-server - Get book data to sync from server
|
|
ipcMain.handle('db:book:sync:toClient', createHandler<CompleteBook, boolean>(
|
|
async function(userId: string, data:CompleteBook, lang: 'fr' | 'en'):Promise<boolean> {
|
|
return await Book.syncBookFromServerToClient(userId, data, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET /book/guide-line - Get guideline
|
|
ipcMain.handle('db:book:guideline:get',
|
|
createHandler<GetGuidelineData, GuideLine | null>(async function(userId: string, data: GetGuidelineData, lang: 'fr' | 'en') {
|
|
return await Book.getGuideLine(userId, data.id, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/guide-line - Update guideline
|
|
ipcMain.handle('db:book:guideline:update', createHandler<UpdateGuideLineData, boolean>(
|
|
async function(userId: string, data: UpdateGuideLineData, lang: 'fr' | 'en') {
|
|
return await Book.updateGuideLine(
|
|
userId,
|
|
data.bookId,
|
|
data.tone,
|
|
data.atmosphere,
|
|
data.writingStyle,
|
|
data.themes,
|
|
data.symbolism,
|
|
data.motifs,
|
|
data.narrativeVoice,
|
|
data.pacing,
|
|
data.keyMessages,
|
|
data.intendedAudience,
|
|
lang
|
|
);
|
|
}
|
|
)
|
|
);
|
|
|
|
// GET /book/story - Get story data (acts + issues + mainChapter)
|
|
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);
|
|
const mainChapter:ChapterProps[] = Chapter.getAllChaptersFromABook(userId, data.bookid, lang);
|
|
return {
|
|
acts,
|
|
issues,
|
|
mainChapter
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/story - Update story (acts + mainChapters)
|
|
ipcMain.handle('db:book:story:update', createHandler<UpdateStoryData, boolean>(
|
|
function(userId: string, data: UpdateStoryData, lang: 'fr' | 'en'):boolean {
|
|
return Book.updateStory(userId, data.bookId, data.acts, data.mainChapters, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/add - Create new book
|
|
ipcMain.handle('db:book:create', createHandler<CreateBookData, string>(
|
|
function(userId: string, data: CreateBookData, lang: 'fr' | 'en') {
|
|
return Book.addBook(
|
|
null,
|
|
userId,
|
|
data.title,
|
|
data.subTitle || '',
|
|
data.summary || '',
|
|
data.type,
|
|
data.serieId || 0,
|
|
data.desiredReleaseDate || '',
|
|
data.desiredWordCount || 0,
|
|
lang
|
|
);
|
|
}
|
|
)
|
|
);
|
|
|
|
|
|
// POST /book/incident/new - Add incident
|
|
ipcMain.handle(
|
|
'db:book:incident:add',
|
|
createHandler<AddIncidentData, string>(
|
|
function(userId: string, data: AddIncidentData, lang: 'fr' | 'en') {
|
|
return Book.addNewIncident(userId, data.bookId, data.name, lang, data.incidentId);
|
|
}
|
|
)
|
|
);
|
|
|
|
// DELETE /book/incident/remove - Remove incident
|
|
interface RemoveIncidentData {
|
|
bookId: string;
|
|
incidentId: string;
|
|
}
|
|
|
|
ipcMain.handle('db:book:incident:remove', createHandler<RemoveIncidentData, boolean>(
|
|
function(userId: string, data: RemoveIncidentData, lang: 'fr' | 'en') {
|
|
return Book.removeIncident(userId, data.bookId, data.incidentId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/plot/new - Add plot point
|
|
ipcMain.handle('db:book:plot:add', createHandler<AddPlotPointData, string>(
|
|
function(userId: string, data: AddPlotPointData, lang: 'fr' | 'en') {
|
|
return Book.addNewPlotPoint(
|
|
userId,
|
|
data.bookId,
|
|
data.incidentId,
|
|
data.name,
|
|
lang,
|
|
data.plotPointId
|
|
);
|
|
}
|
|
)
|
|
);
|
|
|
|
// DELETE /book/plot/remove - Remove plot point
|
|
interface RemovePlotData {
|
|
plotId: string;
|
|
}
|
|
ipcMain.handle(
|
|
'db:book:plot:remove',
|
|
createHandler<RemovePlotData, boolean>(
|
|
function(userId: string, data: RemovePlotData, lang: 'fr' | 'en') {
|
|
return Book.removePlotPoint(userId, data.plotId, lang);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/issue/add - Add issue
|
|
ipcMain.handle('db:book:issue:add', createHandler<AddIssueData, string>(
|
|
function(userId: string, data: AddIssueData, lang: 'fr' | 'en') {
|
|
return Book.addNewIssue(userId, data.bookId, data.name, lang, data.issueId);
|
|
}
|
|
)
|
|
);
|
|
|
|
// DELETE /book/issue/remove - Remove issue
|
|
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
|
|
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);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/world/add - Add world
|
|
ipcMain.handle('db:book:world:add', createHandler<AddWorldData, string>(
|
|
function(userId: string, data: AddWorldData, lang: 'fr' | 'en') {
|
|
return Book.addNewWorld(userId, data.bookId, data.worldName, lang, data.id);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/world/element/add - Add element to world
|
|
ipcMain.handle('db:book:world:element:add', createHandler<AddWorldElementData, string>(
|
|
function(userId: string, data: AddWorldElementData, lang: 'fr' | 'en') {
|
|
return Book.addNewElementToWorld(
|
|
userId,
|
|
data.worldId,
|
|
data.elementName,
|
|
data.elementType.toString(),
|
|
lang,
|
|
data.id
|
|
);
|
|
}
|
|
)
|
|
);
|
|
// DELETE /book/world/element/delete - Remove element from world
|
|
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
|
|
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
|
|
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);
|
|
}
|
|
)
|
|
);
|
|
|
|
// POST /book/ai/guideline (set) - Set AI guideline
|
|
ipcMain.handle('db:book:guideline:ai:set', createHandler<SetAIGuideLineData, boolean>(
|
|
function(userId: string, data: SetAIGuideLineData, lang: 'fr' | 'en') {
|
|
return Book.setAIGuideLine(
|
|
userId,
|
|
data.bookId,
|
|
data.narrativeType,
|
|
data.dialogueType,
|
|
data.plotSummary,
|
|
data.toneAtmosphere,
|
|
data.verbTense,
|
|
data.language,
|
|
data.themes,
|
|
lang
|
|
);
|
|
}
|
|
)
|
|
);
|
|
|
|
// PUT /book/world/update - Update world
|
|
interface UpdateWorldData {
|
|
bookId: string;
|
|
world: WorldProps;
|
|
}
|
|
|
|
ipcMain.handle('db:book:world:update', createHandler<UpdateWorldData, boolean>(
|
|
function(userId: string, data: UpdateWorldData, lang: 'fr' | 'en') {
|
|
return Book.updateWorld(userId, data.world, lang);
|
|
}
|
|
)
|
|
);
|