import 'dart:async'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/models/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/backup.dart'; import 'package:selfprivacy/logic/api_maps/server.dart'; import 'package:selfprivacy/logic/api_maps/backblaze.dart'; import 'package:easy_localization/easy_localization.dart'; part 'backups_state.dart'; class BackupsCubit extends AppConfigDependendCubit { BackupsCubit(AppConfigCubit appConfigCubit) : super(appConfigCubit, BackupsState(preventActions: true)); final api = ServerApi(); final backblaze = BackblazeApi(); Future load() async { if (appConfigCubit.state is AppConfigFinished) { final bucket = getIt().backblazeBucket; if (bucket == null) { emit(BackupsState( isInitialized: false, preventActions: false, refreshing: false)); } else { final status = await api.getBackupStatus(); switch (status.status) { case BackupStatusEnum.noKey: case BackupStatusEnum.notInitialized: emit(BackupsState( backups: [], isInitialized: true, preventActions: false, progress: 0, status: status.status, refreshing: false, )); break; case BackupStatusEnum.initializing: emit(BackupsState( backups: [], isInitialized: true, preventActions: false, progress: 0, status: status.status, refreshTimer: Duration(seconds: 10), refreshing: false, )); break; case BackupStatusEnum.initialized: case BackupStatusEnum.error: final backups = await api.getBackups(); emit(BackupsState( backups: backups, isInitialized: true, preventActions: false, progress: status.progress, status: status.status, error: status.errorMessage ?? '', refreshing: false, )); break; case BackupStatusEnum.backingUp: case BackupStatusEnum.restoring: final backups = await api.getBackups(); emit(BackupsState( backups: backups, isInitialized: true, preventActions: true, progress: status.progress, status: status.status, error: status.errorMessage ?? '', refreshTimer: Duration(seconds: 5), refreshing: false, )); break; default: emit(BackupsState()); } Timer(state.refreshTimer, () => updateBackups(useTimer: true)); } } } Future createBucket() async { emit(state.copyWith(preventActions: true)); final domain = appConfigCubit.state.cloudFlareDomain!.domainName.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-'); final serverId = appConfigCubit.state.hetznerServer!.id; var bucketName = 'selfprivacy-$domain-$serverId'; // If bucket name is too long, shorten it if (bucketName.length > 49) { bucketName = bucketName.substring(0, 49); } final bucketId = await backblaze.createBucket(bucketName); final key = await backblaze.createKey(bucketId); final bucket = BackblazeBucket( bucketId: bucketId, bucketName: bucketName, applicationKey: key.applicationKey, applicationKeyId: key.applicationKeyId); await getIt().storeBackblazeBucket(bucket); await api.uploadBackblazeConfig(bucket); await updateBackups(); emit(state.copyWith(isInitialized: true, preventActions: false)); } Future reuploadKey() async { emit(state.copyWith(preventActions: true)); final bucket = getIt().backblazeBucket; if (bucket == null) { emit(state.copyWith(isInitialized: false)); } else { await api.uploadBackblazeConfig(bucket); emit(state.copyWith(isInitialized: true, preventActions: false)); getIt().showSnackBar('providers.backup.reuploadedKey'); } } Duration refreshTimeFromState(BackupStatusEnum status) { switch (status) { case BackupStatusEnum.backingUp: case BackupStatusEnum.restoring: return Duration(seconds: 5); case BackupStatusEnum.initializing: return Duration(seconds: 10); default: return Duration(seconds: 60); } } Future updateBackups({bool useTimer = false}) async { emit(state.copyWith(refreshing: true)); final backups = await api.getBackups(); final status = await api.getBackupStatus(); emit(state.copyWith( backups: backups, progress: status.progress, status: status.status, error: status.errorMessage, refreshTimer: refreshTimeFromState(status.status), refreshing: false, )); if (useTimer) Timer(state.refreshTimer, () => updateBackups(useTimer: true)); } Future forceUpdateBackups() async { emit(state.copyWith(preventActions: true)); await api.forceBackupListReload(); getIt() .showSnackBar('providers.backup.refetchingList'.tr()); emit(state.copyWith(preventActions: false)); } Future createBackup() async { emit(state.copyWith(preventActions: true)); await api.startBackup(); await updateBackups(); emit(state.copyWith(preventActions: false)); } Future restoreBackup(String backupId) async { emit(state.copyWith(preventActions: true)); await api.restoreBackup(backupId); emit(state.copyWith(preventActions: false)); } @override void clear() async { emit(BackupsState()); } }