2026-08-05 12:00:49 -07:00
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
2025-07-18 08:39:28 -05:00
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
2026-08-11 14:41:11 +05:30
|
|
|
import 'package:immich_mobile/generated/translations.g.dart';
|
2025-07-18 08:39:28 -05:00
|
|
|
|
2026-08-05 12:00:49 -07:00
|
|
|
part 'sync_status.provider.freezed.dart';
|
|
|
|
|
|
2025-07-18 08:39:28 -05:00
|
|
|
enum SyncStatus {
|
|
|
|
|
idle,
|
|
|
|
|
syncing,
|
|
|
|
|
success,
|
2025-07-22 11:24:32 -05:00
|
|
|
error;
|
|
|
|
|
|
2026-07-30 01:56:46 -07:00
|
|
|
String localized() {
|
2026-08-11 14:41:11 +05:30
|
|
|
final t = StaticTranslations.instance;
|
2025-07-22 11:24:32 -05:00
|
|
|
return switch (this) {
|
2026-08-11 14:41:11 +05:30
|
|
|
SyncStatus.idle => t.idle,
|
|
|
|
|
SyncStatus.syncing => t.running,
|
|
|
|
|
SyncStatus.success => t.success,
|
|
|
|
|
SyncStatus.error => t.error,
|
2025-07-22 11:24:32 -05:00
|
|
|
};
|
|
|
|
|
}
|
2025-07-18 08:39:28 -05:00
|
|
|
}
|
|
|
|
|
|
2026-08-05 12:00:49 -07:00
|
|
|
@freezed
|
|
|
|
|
abstract class SyncStatusState with _$SyncStatusState {
|
|
|
|
|
const SyncStatusState._();
|
|
|
|
|
|
|
|
|
|
const factory SyncStatusState({
|
|
|
|
|
@Default(SyncStatus.idle) SyncStatus remoteSyncStatus,
|
|
|
|
|
@Default(SyncStatus.idle) SyncStatus localSyncStatus,
|
|
|
|
|
@Default(SyncStatus.idle) SyncStatus hashJobStatus,
|
|
|
|
|
@Default(SyncStatus.idle) SyncStatus cloudIdSyncStatus,
|
2025-07-18 08:39:28 -05:00
|
|
|
String? errorMessage,
|
2026-08-05 12:00:49 -07:00
|
|
|
}) = _SyncStatusState;
|
2025-07-18 08:39:28 -05:00
|
|
|
|
|
|
|
|
bool get isRemoteSyncing => remoteSyncStatus == SyncStatus.syncing;
|
2025-07-22 11:24:32 -05:00
|
|
|
bool get isLocalSyncing => localSyncStatus == SyncStatus.syncing;
|
|
|
|
|
bool get isHashing => hashJobStatus == SyncStatus.syncing;
|
2026-01-15 00:04:11 +05:30
|
|
|
bool get isCloudIdSyncing => cloudIdSyncStatus == SyncStatus.syncing;
|
2025-07-18 08:39:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SyncStatusNotifier extends Notifier<SyncStatusState> {
|
|
|
|
|
@override
|
|
|
|
|
SyncStatusState build() {
|
|
|
|
|
return const SyncStatusState(
|
|
|
|
|
errorMessage: null,
|
|
|
|
|
remoteSyncStatus: SyncStatus.idle,
|
2025-07-22 11:24:32 -05:00
|
|
|
localSyncStatus: SyncStatus.idle,
|
|
|
|
|
hashJobStatus: SyncStatus.idle,
|
2026-01-15 00:04:11 +05:30
|
|
|
cloudIdSyncStatus: SyncStatus.idle,
|
2025-07-18 08:39:28 -05:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-22 11:24:32 -05:00
|
|
|
///
|
|
|
|
|
/// Remote Sync
|
|
|
|
|
///
|
|
|
|
|
|
2025-07-18 08:39:28 -05:00
|
|
|
void setRemoteSyncStatus(SyncStatus status, [String? errorMessage]) {
|
2026-08-05 12:00:49 -07:00
|
|
|
// TODO(agg23): These error messages probably should be cleared, not preserved on null
|
|
|
|
|
state = state.copyWith(
|
|
|
|
|
remoteSyncStatus: status,
|
|
|
|
|
errorMessage: (status == SyncStatus.error ? errorMessage : null) ?? state.errorMessage,
|
|
|
|
|
);
|
2025-07-18 08:39:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startRemoteSync() => setRemoteSyncStatus(SyncStatus.syncing);
|
|
|
|
|
void completeRemoteSync() => setRemoteSyncStatus(SyncStatus.success);
|
2025-07-25 08:07:22 +05:30
|
|
|
void errorRemoteSync(String error) => setRemoteSyncStatus(SyncStatus.error, error);
|
2025-07-22 11:24:32 -05:00
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// Local Sync
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
void setLocalSyncStatus(SyncStatus status, [String? errorMessage]) {
|
2026-08-05 12:00:49 -07:00
|
|
|
// TODO(agg23): These error messages probably should be cleared, not preserved on null
|
|
|
|
|
state = state.copyWith(
|
|
|
|
|
localSyncStatus: status,
|
|
|
|
|
errorMessage: (status == SyncStatus.error ? errorMessage : null) ?? state.errorMessage,
|
|
|
|
|
);
|
2025-07-22 11:24:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startLocalSync() => setLocalSyncStatus(SyncStatus.syncing);
|
|
|
|
|
void completeLocalSync() => setLocalSyncStatus(SyncStatus.success);
|
2025-07-25 08:07:22 +05:30
|
|
|
void errorLocalSync(String error) => setLocalSyncStatus(SyncStatus.error, error);
|
2025-07-22 11:24:32 -05:00
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// Hash Job
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
void setHashJobStatus(SyncStatus status, [String? errorMessage]) {
|
2026-08-05 12:00:49 -07:00
|
|
|
// TODO(agg23): These error messages probably should be cleared, not preserved on null
|
|
|
|
|
state = state.copyWith(
|
|
|
|
|
hashJobStatus: status,
|
|
|
|
|
errorMessage: (status == SyncStatus.error ? errorMessage : null) ?? state.errorMessage,
|
|
|
|
|
);
|
2025-07-22 11:24:32 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startHashJob() => setHashJobStatus(SyncStatus.syncing);
|
|
|
|
|
void completeHashJob() => setHashJobStatus(SyncStatus.success);
|
|
|
|
|
void errorHashJob(String error) => setHashJobStatus(SyncStatus.error, error);
|
2026-01-15 00:04:11 +05:30
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// Cloud ID Sync Job
|
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
void setCloudIdSyncStatus(SyncStatus status, [String? errorMessage]) {
|
2026-08-05 12:00:49 -07:00
|
|
|
// TODO(agg23): These error messages probably should be cleared, not preserved on null
|
|
|
|
|
state = state.copyWith(
|
|
|
|
|
cloudIdSyncStatus: status,
|
|
|
|
|
errorMessage: (status == SyncStatus.error ? errorMessage : null) ?? state.errorMessage,
|
|
|
|
|
);
|
2026-01-15 00:04:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void startCloudIdSync() => setCloudIdSyncStatus(SyncStatus.syncing);
|
|
|
|
|
void completeCloudIdSync() => setCloudIdSyncStatus(SyncStatus.success);
|
|
|
|
|
void errorCloudIdSync(String error) => setCloudIdSyncStatus(SyncStatus.error, error);
|
2025-07-18 08:39:28 -05:00
|
|
|
}
|
|
|
|
|
|
2025-07-29 00:34:03 +05:30
|
|
|
final syncStatusProvider = NotifierProvider<SyncStatusNotifier, SyncStatusState>(SyncStatusNotifier.new);
|