import 'package:omi/backend/schema/conversation.dart';
import 'package:omi/services/wals.dart';
enum SyncStatus { idle, syncing, fetchingConversations, completed, error }
enum SyncPhase { idle, downloadingFromDevice, waitingForInternet, uploadingToCloud, processingOnServer }
extension SyncMethodExtension on SyncMethod {
String get displayName {
switch (this) {
case SyncMethod.ble:
return 'Bluetooth';
}
}
String get shortName {
switch (this) {
case SyncMethod.ble:
return 'BLE';
}
}
String get description {
switch (this) {
case SyncMethod.ble:
return 'Syncing via Bluetooth';
}
}
}
class SyncState {
final SyncStatus status;
final SyncPhase phase;
final double progress;
final String? errorMessage;
final Wal? failedWal;
final List<SyncedConversationPointer> syncedConversations;
final double? speedKBps;
final SyncMethod? syncMethod;
final int? currentFile;
final int? totalFiles;
final int? uploadedBytes;
final int? totalBytesToUpload;
const SyncState({
this.status = SyncStatus.idle,
this.phase = SyncPhase.idle,
this.progress = 0.0,
this.errorMessage,
this.failedWal,
this.syncedConversations = const [],
this.speedKBps,
this.syncMethod,
this.currentFile,
this.totalFiles,
this.uploadedBytes,
this.totalBytesToUpload,
});
SyncState copyWith({
SyncStatus? status,
SyncPhase? phase,
double? progress,
String? errorMessage,
Wal? failedWal,
List<SyncedConversationPointer>? syncedConversations,
double? speedKBps,
SyncMethod? syncMethod,
bool clearSyncMethod = false,
int? currentFile,
int? totalFiles,
int? uploadedBytes,
int? totalBytesToUpload,
}) {
return SyncState(
status: status ?? this.status,
phase: phase ?? this.phase,
progress: progress ?? this.progress,
errorMessage: errorMessage,
failedWal: failedWal,
syncedConversations: syncedConversations ?? this.syncedConversations,
speedKBps: speedKBps,
syncMethod: clearSyncMethod ? null : (syncMethod ?? this.syncMethod),
currentFile: currentFile ?? this.currentFile,
totalFiles: totalFiles ?? this.totalFiles,
uploadedBytes: uploadedBytes,
totalBytesToUpload: totalBytesToUpload,
);
}
bool get isIdle => status == SyncStatus.idle;
bool get isSyncing => status == SyncStatus.syncing;
bool get isFetchingConversations => status == SyncStatus.fetchingConversations;
bool get isCompleted => status == SyncStatus.completed;
bool get hasError => status == SyncStatus.error;
bool get isProcessing => isSyncing || isFetchingConversations;
SyncState toIdle() => copyWith(
status: SyncStatus.idle,
phase: SyncPhase.idle,
progress: 0.0,
errorMessage: null,
failedWal: null,
syncedConversations: [],
clearSyncMethod: true,
);
SyncState toSyncing({
double progress = 0.0,
double? speedKBps,
SyncMethod? syncMethod,
SyncPhase? phase,
int? currentFile,
int? totalFiles,
int? uploadedBytes,
int? totalBytesToUpload,
}) =>
copyWith(
status: SyncStatus.syncing,
phase: phase,
progress: progress,
errorMessage: null,
speedKBps: speedKBps,
syncMethod: syncMethod,
currentFile: currentFile,
totalFiles: totalFiles,
uploadedBytes: uploadedBytes,
totalBytesToUpload: totalBytesToUpload,
);
SyncState toFetchingConversations() => copyWith(status: SyncStatus.fetchingConversations);
SyncState toCompleted({required List<SyncedConversationPointer> conversations}) =>
copyWith(status: SyncStatus.completed, syncedConversations: conversations);
SyncState toError({required String message, Wal? failedWal}) =>
copyWith(status: SyncStatus.error, errorMessage: message, failedWal: failedWal, progress: 0.0);
}