Add foundational components and logic for migration, UI design, and input handling

- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design.
- Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri.
- Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling.
- Updated `ScribeShell` with migration popup logic to prompt users for data migration.
- Integrated `AlertStack` for better alert handling and notification management.
- Enhanced Rust/Tauri services with migration command implementations.
- Added translations and styles for new components.
This commit is contained in:
natreex
2026-04-05 12:52:54 -04:00
parent 2b6d4cc48b
commit d4765e6576
49 changed files with 3115 additions and 2 deletions

View File

@@ -450,6 +450,79 @@ ipcMain.on('logout', ():void => {
createLoginWindow();
});
// ========== MIGRATION EXPORT (Electron → Tauri) ==========
ipcMain.handle('export-migration', async ():Promise<{success: boolean; path?: string; error?: string}> => {
const storage:SecureStorage = getSecureStorage();
const userId:string | null = storage.get<string>('userId', null);
const lastUserId:string | null = storage.get<string>('lastUserId', null);
const targetUserId:string | null = userId || lastUserId;
if (!targetUserId) {
return { success: false, error: 'No user found in storage' };
}
let encryptionKey:string | null = null;
try {
encryptionKey = getUserEncryptionKey(targetUserId);
} catch {
return { success: false, error: 'Encryption key not found for this user' };
}
const pinHash:string | null = storage.get<string>(`pin-${targetUserId}`, null);
const userDataPath:string = app.getPath('userData');
const dbPath:string = path.join(userDataPath, 'eritors-local.db');
if (!fs.existsSync(dbPath)) {
return { success: false, error: 'No local database found' };
}
const { filePath } = await dialog.showSaveDialog({
title: 'Export migration data',
defaultPath: path.join(app.getPath('desktop'), 'eritors-migration.json'),
filters: [{ name: 'Migration', extensions: ['json'] }],
});
if (!filePath) {
return { success: false, error: 'Export cancelled' };
}
const migrationData = {
version: 1,
exported_at: Date.now(),
user_id: targetUserId,
encryption_key: encryptionKey,
pin_hash: pinHash,
db_source: dbPath,
};
try {
fs.writeFileSync(filePath, JSON.stringify(migrationData, null, 2), 'utf-8');
// Copier aussi la DB à côté du fichier de migration
const dbDestination:string = path.join(path.dirname(filePath), `eritors-local-${targetUserId}.db`);
fs.copyFileSync(dbPath, dbDestination);
// Copier WAL et SHM si existants
const walPath:string = dbPath + '-wal';
const shmPath:string = dbPath + '-shm';
if (fs.existsSync(walPath)) {
fs.copyFileSync(walPath, dbDestination + '-wal');
}
if (fs.existsSync(shmPath)) {
fs.copyFileSync(shmPath, dbDestination + '-shm');
}
return { success: true, path: filePath };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Export failed',
};
}
});
// ========== USER SYNC (PRE-AUTHENTICATION) ==========
interface SyncUserData {