Add multi-language support and new repository methods for book synchronization

- Extend repository methods to handle API requests for fetching books, chapters, characters, and other entities with multilingual support (`lang: 'fr' | 'en'`).
- Add `uploadBookForSync` logic to consolidate and decrypt book data for synchronization.
- Refactor schema migration logic to remove console logs and streamline table recreation.
- Enhance error handling across database repositories and IPC methods.
This commit is contained in:
natreex
2025-12-22 16:44:12 -05:00
parent ff530f3442
commit 515d469ba7
17 changed files with 666 additions and 113 deletions

View File

@@ -117,7 +117,15 @@ ipcMain.handle('db:book:syncSave', createHandler<CompleteBook, boolean>(
// 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);
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);
}
)
);

View File

@@ -160,5 +160,3 @@ ipcMain.handle('db:chapter:information:remove', createHandler<RemoveChapterInfoD
}
)
);
console.log('[IPC] Chapter handlers registered');

View File

@@ -102,5 +102,3 @@ ipcMain.handle('db:location:subelement:delete', createHandler<DeleteLocationSubE
}
)
);
console.log('[IPC] Location handlers registered');

View File

@@ -1,7 +1,7 @@
import { ipcMain } from 'electron';
import { createHandler } from '../database/LocalSystem.js';
import * as bcrypt from 'bcrypt';
import { getSecureStorage } from '../storage/SecureStorage.js';
import SecureStorage, { getSecureStorage } from '../storage/SecureStorage.js';
import { getDatabaseService } from '../database/database.service.js';
interface SetPinData {
@@ -19,21 +19,18 @@ interface OfflineModeData {
ipcMain.handle('offline:pin:set', async (_event, data: SetPinData) => {
try {
const storage = getSecureStorage();
const userId = storage.get<string>('userId');
const storage: SecureStorage = getSecureStorage();
const userId: string | null = storage.get<string>('userId');
if (!userId) {
return { success: false, error: 'No user logged in' };
}
// Hash the PIN
const hashedPin = await bcrypt.hash(data.pin, 10);
const hashedPin: string = await bcrypt.hash(data.pin, 10);
// Store hashed PIN
storage.set(`pin-${userId}`, hashedPin);
storage.save();
console.log('[Offline] PIN set for user');
return { success: true };
} catch (error) {
console.error('[Offline] Error setting PIN:', error);
@@ -73,8 +70,7 @@ ipcMain.handle('offline:pin:verify', async (_event, data: VerifyPinData) => {
console.error('[Offline] No encryption key found for user');
return { success: false, error: 'No encryption key found' };
}
console.log('[Offline] PIN verified, user authenticated locally');
return {
success: true,
userId: lastUserId
@@ -99,7 +95,6 @@ ipcMain.handle('offline:mode:set', (_event, data: OfflineModeData) => {
}
storage.save();
console.log('[Offline] Mode set to:', data.enabled);
return { success: true };
} catch (error) {
@@ -157,6 +152,4 @@ ipcMain.handle('offline:sync:check', () => {
console.error('[Offline] Error checking sync:', error);
return { shouldSync: false };
}
});
console.log('[IPC] Offline handlers registered');
});