feat: Add color and icon properties to categories, enhance category management in UI
This commit is contained in:
@@ -12,6 +12,7 @@ import 'package:notas/models/category.dart';
|
||||
|
||||
import 'package:notas/data/note_encryption.dart';
|
||||
import 'package:notas/widgets/sync_status.dart';
|
||||
import 'package:flutter/foundation.dart' show debugPrint;
|
||||
|
||||
class NoteRepository {
|
||||
NoteRepository({
|
||||
@@ -34,6 +35,56 @@ class NoteRepository {
|
||||
return _loadDeletedNotesFromDatabase();
|
||||
}
|
||||
|
||||
Future<List<Category>> loadCategories() async {
|
||||
final List<DbCategory> dbCategories = await _database.getAllCategories();
|
||||
final List<Category> categories = [];
|
||||
for (final DbCategory row in dbCategories) {
|
||||
try {
|
||||
final String decryptedName = await NoteEncryption.decryptNote(
|
||||
row.encryptedName,
|
||||
_masterKey,
|
||||
);
|
||||
categories.add(
|
||||
Category(
|
||||
id: row.id,
|
||||
name: decryptedName,
|
||||
serverVersion: row.serverVersion,
|
||||
isDeleted: row.isDeleted,
|
||||
updatedAt: row.updatedAt,
|
||||
isDirty: row.isDirty,
|
||||
colorValue: row.colorValue,
|
||||
iconCodePoint: row.iconCodePoint,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error al desencriptar categoría: $e');
|
||||
}
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
Future<void> createCategory(Category category) async {
|
||||
debugPrint('createCategory called with: ${category.name}');
|
||||
final String encryptedName = await NoteEncryption.encryptNote(
|
||||
category.name,
|
||||
_masterKey,
|
||||
);
|
||||
debugPrint('Category name encrypted');
|
||||
await _database.upsertCategory(
|
||||
CategoriesCompanion.insert(
|
||||
id: category.id,
|
||||
encryptedName: encryptedName,
|
||||
updatedAt: category.updatedAt,
|
||||
serverVersion: const Value(0),
|
||||
isDeleted: const Value(false),
|
||||
isDirty: const Value(true),
|
||||
colorValue: Value<int?>(category.colorValue),
|
||||
iconCodePoint: Value<int?>(category.iconCodePoint),
|
||||
),
|
||||
);
|
||||
debugPrint('Category inserted to database');
|
||||
}
|
||||
|
||||
Future<Note> createNote(Note note) async {
|
||||
await _database.insertNoteAtTop(
|
||||
NotesCompanion.insert(
|
||||
@@ -60,7 +111,7 @@ class NoteRepository {
|
||||
|
||||
final DbNote row =
|
||||
existingNote ??
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
|
||||
await _database.updateNoteRow(
|
||||
DbNote(
|
||||
@@ -92,7 +143,7 @@ class NoteRepository {
|
||||
|
||||
final DbNote row =
|
||||
existingNote ??
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
|
||||
if (row.isDeleted || note.isDeleted || note.isPermanentlyDeleted) {
|
||||
await _database.permanentlyDeleteNote(row.id);
|
||||
@@ -111,7 +162,7 @@ class NoteRepository {
|
||||
|
||||
final DbNote row =
|
||||
existingNote ??
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
(throw ArgumentError('Note not found for id ${note.id}.'));
|
||||
|
||||
await _database.moveNote(
|
||||
id: row.id,
|
||||
@@ -212,10 +263,7 @@ class NoteRepository {
|
||||
details.add('StackTrace: ${stackTrace.toString()}');
|
||||
}
|
||||
|
||||
return {
|
||||
'error': true,
|
||||
'message': details.join('\n\n'),
|
||||
};
|
||||
return {'error': true, 'message': details.join('\n\n')};
|
||||
}
|
||||
|
||||
final SyncResponse response = syncResult['data'] as SyncResponse;
|
||||
@@ -249,10 +297,7 @@ class NoteRepository {
|
||||
'categoriesCount': response.changes.categories.length,
|
||||
};
|
||||
} catch (e, st) {
|
||||
return {
|
||||
'error': true,
|
||||
'message': '$e\n\nStackTrace: $st',
|
||||
};
|
||||
return {'error': true, 'message': '$e\n\nStackTrace: $st'};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,21 +308,18 @@ class NoteRepository {
|
||||
// Apply categories from server
|
||||
for (final SyncCategoryResponse catResponse
|
||||
in response.changes.categories) {
|
||||
final String categoryName =
|
||||
catResponse.isDeleted || catResponse.encryptedName.isEmpty
|
||||
? ''
|
||||
: await NoteEncryption.decryptNote(
|
||||
catResponse.encryptedName,
|
||||
_masterKey,
|
||||
);
|
||||
|
||||
// Store the encrypted blob received from the server directly in the DB.
|
||||
// Decryption is only performed when loading categories for display.
|
||||
final String encryptedBlob = catResponse.encryptedName;
|
||||
|
||||
await _database.upsertCategory(
|
||||
CategoriesCompanion(
|
||||
id: Value(catResponse.id),
|
||||
encryptedName: Value(categoryName),
|
||||
encryptedName: Value(encryptedBlob),
|
||||
serverVersion: Value(catResponse.serverVersion),
|
||||
isDeleted: Value(catResponse.isDeleted),
|
||||
colorValue: Value<int?>(catResponse.colorValue),
|
||||
iconCodePoint: Value<int?>(catResponse.iconCodePoint),
|
||||
updatedAt: Value(catResponse.updatedAt),
|
||||
isDirty: const Value(false),
|
||||
),
|
||||
@@ -439,9 +481,10 @@ Future<List<SyncCategoryPayload>> _encryptCategories(
|
||||
final List<SyncCategoryPayload> payloads = [];
|
||||
|
||||
for (final DbCategory row in categories) {
|
||||
final String encryptedName = row.encryptedName.isEmpty
|
||||
? ''
|
||||
: await NoteEncryption.encryptNote(row.encryptedName, masterKey);
|
||||
// The DB already stores the encrypted name blob in `encryptedName`.
|
||||
// Use it directly when building the sync payload and preserve
|
||||
// color/icon values from the DB row so they are sent to the server.
|
||||
final String encryptedName = row.encryptedName;
|
||||
|
||||
payloads.add(
|
||||
SyncCategoryPayload.fromCategory(
|
||||
@@ -452,6 +495,8 @@ Future<List<SyncCategoryPayload>> _encryptCategories(
|
||||
isDeleted: row.isDeleted,
|
||||
updatedAt: row.updatedAt,
|
||||
isDirty: row.isDirty,
|
||||
colorValue: row.colorValue,
|
||||
iconCodePoint: row.iconCodePoint,
|
||||
),
|
||||
encryptedName: encryptedName,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user