Implement local vault service with encryption key management and integrate it into the app. Add settings screen for data management and enhance home screen with new features. Update database connection for encryption support and modify repository to use the new database structure. Improve UI elements across the application for better user experience.

This commit is contained in:
2026-05-13 22:57:23 +02:00
parent 96f8f95924
commit 94fdfe51eb
16 changed files with 875 additions and 87 deletions
+13 -3
View File
@@ -19,7 +19,7 @@ class Notes extends Table {
@DriftDatabase(tables: [Notes])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(_openConnection());
AppDatabase({required String encryptionKey}) : super(_openConnection(encryptionKey));
@override
int get schemaVersion => 1;
@@ -94,11 +94,21 @@ class AppDatabase extends _$AppDatabase {
}
}
LazyDatabase _openConnection() {
LazyDatabase _openConnection(String encryptionKey) {
return LazyDatabase(() async {
final Directory supportDir = await getApplicationSupportDirectory();
final File file = File(p.join(supportDir.path, 'notes.sqlite'));
return NativeDatabase(file);
return NativeDatabase(
file,
setup: (database) {
final String escapedKey = encryptionKey.replaceAll("'", "''");
// sqlite3mc can emulate SQLCipher file format for compatibility.
database.execute("PRAGMA cipher = 'sqlcipher'");
database.execute('PRAGMA legacy = 4');
database.execute("PRAGMA key = '$escapedKey'");
},
);
});
}
+56
View File
@@ -0,0 +1,56 @@
import 'dart:math';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class LocalVaultService {
LocalVaultService._();
static final LocalVaultService instance = LocalVaultService._();
static const String _encryptionKeyStorageKey =
'notes_local_encryption_key_v1';
final FlutterSecureStorage _secureStorage = FlutterSecureStorage();
String? _cachedEncryptionKey;
Future<String?> readEncryptionKey() async {
final String? cachedKey = _cachedEncryptionKey;
if (cachedKey != null) {
return cachedKey;
}
final String? storedKey = await _secureStorage.read(
key: _encryptionKeyStorageKey,
);
_cachedEncryptionKey = storedKey;
return storedKey;
}
Future<String> createEncryptionKey() async {
final String encryptionKey = _generateEncryptionKey();
await _secureStorage.write(
key: _encryptionKeyStorageKey,
value: encryptionKey,
);
_cachedEncryptionKey = encryptionKey;
return encryptionKey;
}
Future<void> clearEncryptionKey() async {
await _secureStorage.delete(key: _encryptionKeyStorageKey);
_cachedEncryptionKey = null;
}
String _generateEncryptionKey() {
final Random random = Random.secure();
final List<int> bytes = List<int>.generate(32, (_) => random.nextInt(256));
return bytes
.map((int byte) => byte.toRadixString(16).padLeft(2, '0'))
.join();
}
}
+1 -3
View File
@@ -2,9 +2,7 @@ import 'package:notas/data/app_database.dart';
import 'package:notas/models/note.dart';
class NoteRepository {
NoteRepository({AppDatabase? database}) : _database = database ?? _sharedDatabase;
static final AppDatabase _sharedDatabase = AppDatabase();
NoteRepository({required AppDatabase database}) : _database = database;
final AppDatabase _database;