Remove ExportBook component and integrate new export workflows

- Deleted `ExportBook` component and its usage in `BookCard.tsx`.
- Integrated improved book export workflows in `BookSettingOption` for better user experience.
- Updated database models and repositories to support export options with chapter/version selection.
- Added localization support for export-related messages and tooltips.
- Upgraded dependencies to include libraries required for export formats (e.g., DOCX, PDF, EPUB).
- Bumped app version to 0.4.1.
This commit is contained in:
natreex
2026-03-05 16:31:56 -05:00
parent 94cac463fb
commit ceaecb19fc
16 changed files with 780 additions and 245 deletions

View File

@@ -1,9 +1,11 @@
import { ipcMain } from 'electron';
import { ipcMain, dialog, BrowserWindow } from 'electron';
import { writeFile } from 'fs/promises';
import { createHandler } from '../database/LocalSystem.js';
import Book, {BookSyncCompare, CompleteBook, SyncedBook} from '../database/models/Book.js';
import Book, {BookSyncCompare, CompleteBook, CompleteBookData, SyncedBook} from '../database/models/Book.js';
import type { BookProps } from '../database/models/Book.js';
import Chapter from '../database/models/Chapter.js';
import Chapter, {ChapterExportInfo} from '../database/models/Chapter.js';
import type { ChapterProps } from '../database/models/Chapter.js';
import {ChapterSelectionParam} from "../database/repositories/chapter.repository.js";
import Act, {ActProps} from "../database/models/Act.js";
import Issue, {IssueProps} from "../database/models/Issue.js";
import Sync from "../database/models/Sync.js";
@@ -13,6 +15,7 @@ import GuideLine, {GuideLineAI} from "../database/models/GuideLine.js";
import Incident from "../database/models/Incident.js";
import PlotPoint from "../database/models/PlotPoint.js";
import World, {WorldListResponse, WorldProps} from "../database/models/World.js";
import Export, {ExportResult} from "../database/models/Export.js";
interface UpdateBookBasicData {
title: string;
@@ -434,3 +437,65 @@ ipcMain.handle('db:book:tool:update', createHandler<UpdateBookToolData, boolean>
}
)
);
// GET /book/export/info - Get chapters export info (available versions)
interface ExportInfoData {
bookId: string;
}
ipcMain.handle('db:book:export:info', createHandler<ExportInfoData, ChapterExportInfo[]>(
function(userId: string, data: ExportInfoData, lang: 'fr' | 'en'): ChapterExportInfo[] {
return Chapter.getChaptersExportInfo(userId, data.bookId, lang);
}
)
);
// POST /book/export - Export book to file (EPUB/PDF/DOCX)
type ExportFormat = 'epub' | 'pdf' | 'docx';
interface ExportRequestData {
bookId: string;
format: ExportFormat;
selections: ChapterSelectionParam[] | null;
}
const formatExtensions: Record<ExportFormat, {ext: string; filterName: string}> = {
epub: {ext: 'epub', filterName: 'EPUB'},
pdf: {ext: 'pdf', filterName: 'PDF'},
docx: {ext: 'docx', filterName: 'Word Document'}
};
ipcMain.handle('db:book:export', createHandler<ExportRequestData, boolean>(
async function(userId: string, data: ExportRequestData, lang: 'fr' | 'en'): Promise<boolean> {
const bookData: CompleteBookData = Chapter.getCompleteBookDataWithSelections(userId, data.bookId, data.selections, lang);
let result: ExportResult;
switch (data.format) {
case 'epub':
result = await Export.transformToEpub(bookData);
break;
case 'pdf':
result = await Export.transformToPDF(bookData);
break;
case 'docx':
result = await Export.transformToDOCX(bookData);
break;
default:
throw new Error(lang === 'fr' ? 'Format non supporté.' : 'Unsupported format.');
}
const formatInfo = formatExtensions[data.format];
const focusedWindow: BrowserWindow | null = BrowserWindow.getFocusedWindow();
const dialogResult = await dialog.showSaveDialog(focusedWindow!, {
defaultPath: result.fileName,
filters: [{name: formatInfo.filterName, extensions: [formatInfo.ext]}]
});
if (dialogResult.canceled || !dialogResult.filePath) {
return false;
}
await writeFile(dialogResult.filePath, result.buffer);
return true;
}
)
);