feat: Refactor sync status handling and improve synchronization feedback in the app
This commit is contained in:
@@ -6,6 +6,7 @@ import 'package:notas/models/note.dart';
|
||||
import 'package:notas/models/category.dart';
|
||||
|
||||
import 'package:notas/data/note_encryption.dart';
|
||||
import 'package:notas/widgets/sync_status.dart';
|
||||
|
||||
class NoteRepository {
|
||||
NoteRepository({
|
||||
@@ -89,8 +90,17 @@ class NoteRepository {
|
||||
|
||||
/// Sincroniza notas con el servidor.
|
||||
/// Requiere que el usuario esté autenticado (token válido).
|
||||
Future<Map<String, dynamic>> performSync({bool forceFull = false}) async {
|
||||
Future<Map<String, dynamic>> performSync({
|
||||
bool forceFull = false,
|
||||
void Function(SyncStatus status, {double? progress, String? message})?
|
||||
onProgress,
|
||||
}) async {
|
||||
try {
|
||||
onProgress?.call(
|
||||
SyncStatus.preparing,
|
||||
message: 'Preparando sincronización...',
|
||||
);
|
||||
|
||||
// Get last sync timestamp
|
||||
final DateTime? lastSync = await _authApi.getLastSyncAt();
|
||||
final DateTime? lastSyncForRequest = forceFull
|
||||
@@ -113,10 +123,21 @@ class NoteRepository {
|
||||
);
|
||||
}
|
||||
|
||||
final int totalNotesToEncrypt = unsyncedNotes.length;
|
||||
|
||||
// Build sync request (note: we send encrypted data, but locally we have plaintext)
|
||||
// Encrypt all notes before sending
|
||||
final List<SyncNotePayload> encryptedNotesPayload = [];
|
||||
for (final dbNote in unsyncedNotes) {
|
||||
if (totalNotesToEncrypt == 0) {
|
||||
onProgress?.call(
|
||||
SyncStatus.encrypting,
|
||||
progress: 1.0,
|
||||
message: 'No hay notas pendientes de encriptar.',
|
||||
);
|
||||
}
|
||||
|
||||
for (var index = 0; index < unsyncedNotes.length; index += 1) {
|
||||
final DbNote dbNote = unsyncedNotes[index];
|
||||
final note = _fromDbNote(dbNote);
|
||||
final encryptedTitle = await NoteEncryption.encryptNote(
|
||||
note.title,
|
||||
@@ -133,6 +154,13 @@ class NoteRepository {
|
||||
encryptedBody: encryptedBody,
|
||||
),
|
||||
);
|
||||
|
||||
onProgress?.call(
|
||||
SyncStatus.encrypting,
|
||||
progress: (index + 1) / totalNotesToEncrypt,
|
||||
message:
|
||||
'Encriptando notas para subir: ${index + 1} de $totalNotesToEncrypt',
|
||||
);
|
||||
}
|
||||
|
||||
final List<SyncCategoryPayload> categoriesPayload = unsyncedCategories
|
||||
@@ -148,6 +176,10 @@ class NoteRepository {
|
||||
);
|
||||
|
||||
// Call sync API
|
||||
onProgress?.call(
|
||||
SyncStatus.uploading,
|
||||
message: 'Subiendo datos al servidor...',
|
||||
);
|
||||
final Map<String, dynamic> syncResult = await _authApi.sync(syncRequest);
|
||||
|
||||
if (syncResult['error'] == true) {
|
||||
@@ -157,7 +189,23 @@ class NoteRepository {
|
||||
final SyncResponse response = syncResult['data'] as SyncResponse;
|
||||
|
||||
// Apply server changes to local database
|
||||
await _applySyncResponse(response);
|
||||
onProgress?.call(
|
||||
SyncStatus.waitingResponse,
|
||||
message: 'Esperando respuesta del servidor...',
|
||||
);
|
||||
|
||||
await _applySyncResponse(
|
||||
response,
|
||||
onDecryptProgress: (int processed, int total) {
|
||||
onProgress?.call(
|
||||
SyncStatus.decrypting,
|
||||
progress: total == 0 ? 1.0 : processed / total,
|
||||
message: total == 0
|
||||
? 'Desencriptando datos recibidos...'
|
||||
: 'Desencriptando respuesta: $processed de $total',
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Update lastSyncAt
|
||||
await _authApi.setLastSyncAt(response.serverTimestamp);
|
||||
@@ -173,7 +221,10 @@ class NoteRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _applySyncResponse(SyncResponse response) async {
|
||||
Future<void> _applySyncResponse(
|
||||
SyncResponse response, {
|
||||
void Function(int processed, int total)? onDecryptProgress,
|
||||
}) async {
|
||||
// Apply categories from server
|
||||
for (final SyncCategoryResponse catResponse
|
||||
in response.changes.categories) {
|
||||
@@ -189,7 +240,9 @@ class NoteRepository {
|
||||
}
|
||||
|
||||
// Apply notes from server
|
||||
for (final SyncNoteResponse noteResponse in response.changes.notes) {
|
||||
final int totalNotesToDecrypt = response.changes.notes.length;
|
||||
for (var index = 0; index < response.changes.notes.length; index += 1) {
|
||||
final SyncNoteResponse noteResponse = response.changes.notes[index];
|
||||
final existingNote = await (_database.select(
|
||||
_database.notes,
|
||||
)..where((n) => n.uuid.equals(noteResponse.id))).getSingleOrNull();
|
||||
@@ -245,6 +298,8 @@ class NoteRepository {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
onDecryptProgress?.call(index + 1, totalNotesToDecrypt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user