import 'dart:io'; import 'package:flutter/material.dart'; import 'package:notas/data/app_database.dart'; import 'package:notas/data/local_vault_service.dart'; import 'package:notas/data/note_repository.dart'; import 'package:notas/platform/app_platform.dart'; import 'package:notas/platform/window_state.dart'; import 'package:notas/screens/home_screen.dart'; import 'package:notas/screens/vault_access_screen.dart'; import 'package:notas/theme/app_theme.dart'; import 'package:notas/widgets/app_title_bar.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import 'package:window_manager/window_manager.dart'; class NotesApp extends StatefulWidget { const NotesApp({super.key}); @override State createState() => _NotesAppState(); } class _NotesAppState extends State with WindowListener { final LocalVaultService _vaultService = LocalVaultService.instance; final GlobalKey _scaffoldMessengerKey = GlobalKey(); AppDatabase? _database; NoteRepository? _repository; bool _isBootstrapping = true; bool _isUnlocking = false; @override void initState() { super.initState(); if (isDesktop) { windowManager.addListener(this); } _bootstrapVault(); } @override void dispose() { if (isDesktop) { windowManager.removeListener(this); } _database?.close(); super.dispose(); } Future _bootstrapVault() async { try { final String? encryptionKey = await _vaultService.readEncryptionKey(); if (encryptionKey != null) { await _openVault(encryptionKey); } } finally { if (mounted) { setState(() { _isBootstrapping = false; }); } } } Future _openVault(String encryptionKey) async { await _database?.close(); final AppDatabase database = AppDatabase(encryptionKey: encryptionKey); if (!mounted) { await database.close(); return; } setState(() { _database = database; _repository = NoteRepository(database: database); }); } Future _resetLocalVaultData() async { final AppDatabase? database = _database; setState(() { _repository = null; _database = null; _isBootstrapping = true; }); await database?.close(); await _vaultService.clearEncryptionKey(); final Directory supportDir = await getApplicationSupportDirectory(); final String dbPath = p.join(supportDir.path, 'notes.sqlite'); final List filesToDelete = [ dbPath, '$dbPath-wal', '$dbPath-shm', '$dbPath-journal', ]; for (final String filePath in filesToDelete) { final File file = File(filePath); if (await file.exists()) { await file.delete(); } } if (!mounted) { return; } setState(() { _isBootstrapping = false; _isUnlocking = false; }); } Future _enterWithoutAccount() async { if (_isUnlocking) { return; } setState(() { _isUnlocking = true; }); try { final String encryptionKey = await _vaultService.createEncryptionKey(); await _openVault(encryptionKey); } catch (error) { _scaffoldMessengerKey.currentState?.showSnackBar( SnackBar(content: Text('No se pudo crear el vault local: $error')), ); } finally { if (mounted) { setState(() { _isUnlocking = false; _isBootstrapping = false; }); } } } void _showAccountPlaceholder(String actionLabel) { _scaffoldMessengerKey.currentState?.showSnackBar( SnackBar( content: Text( '$actionLabel todavía no está conectado con la API. Usa "Entrar sin cuenta" para empezar en local.', ), ), ); } Future _saveWindowSize() async { if (await windowManager.isFullScreen()) { return; } if (await windowManager.isMaximized()) { return; } final Size currentSize = await windowManager.getSize(); await WindowStateStore.instance.saveWindowSize(currentSize); } Widget _buildLoadingScreen() { return MaterialApp( title: 'Mis Notas', debugShowCheckedModeBanner: false, theme: AppTheme.theme, home: const Scaffold( body: SafeArea( child: Column( children: [ AppTitleBar(), Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(height: 16), Text('Preparando el vault local...'), ], ), ), ), ], ), ), ), ); } Widget _buildAppShell({required Widget home}) { return MaterialApp( title: 'Mis Notas', debugShowCheckedModeBanner: false, scaffoldMessengerKey: _scaffoldMessengerKey, theme: AppTheme.theme, home: home, ); } @override void onWindowResize() { _saveWindowSize(); } @override void onWindowResized() { _saveWindowSize(); } @override Widget build(BuildContext context) { if (_isBootstrapping) { return _buildLoadingScreen(); } final NoteRepository? repository = _repository; if (repository != null) { return _buildAppShell( home: HomeScreen( repository: repository, onDeleteAllData: _resetLocalVaultData, ), ); } return _buildAppShell( home: VaultAccessScreen( isBusy: _isUnlocking, onCreateAccountPressed: (String email, String password) async { _showAccountPlaceholder('Crear cuenta'); }, onSignInPressed: (String email, String password) async { _showAccountPlaceholder('Iniciar sesión'); }, onContinueWithoutAccount: _enterWithoutAccount, ), ); } }