chore: expose upload errors to UI (#25566)

This commit is contained in:
Alex
2026-01-27 10:33:44 -06:00
committed by GitHub
parent 212c03ceff
commit 44b4f35019
5 changed files with 34 additions and 1 deletions

View File

@@ -62,6 +62,8 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
final iCloudProgress = ref.watch(driftBackupProvider.select((state) => state.iCloudDownloadProgress));
final errorCount = ref.watch(driftBackupProvider.select((state) => state.errorCount));
final isProcessing = uploadTasks.isNotEmpty || isSyncing || iCloudProgress.isNotEmpty;
return AnimatedBuilder(
@@ -149,6 +151,14 @@ class BackupToggleButtonState extends ConsumerState<BackupToggleButton> with Sin
),
],
),
if (errorCount > 0)
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
"upload_error_with_count".t(context: context, args: {'count': '$errorCount'}),
style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.error),
),
),
],
),
),

View File

@@ -149,6 +149,8 @@ class DriftBackupState {
);
}
int get errorCount => uploadItems.values.where((item) => item.isFailed == true).length;
@override
String toString() {
return 'DriftBackupState(totalCount: $totalCount, backupCount: $backupCount, remainderCount: $remainderCount, processingCount: $processingCount, isSyncing: $isSyncing, error: $error, uploadItems: $uploadItems, cancelToken: $cancelToken, iCloudDownloadProgress: $iCloudDownloadProgress)';

View File

@@ -260,6 +260,7 @@ class BackgroundUploadService {
Future<UploadTask?> getUploadTask(LocalAsset asset, {String group = kBackupGroup, int? priority}) async {
final entity = await _storageRepository.getAssetEntityForAsset(asset);
if (entity == null) {
_logger.warning("Asset entity not found for ${asset.id} - ${asset.name}");
return null;
}
@@ -282,6 +283,7 @@ class BackgroundUploadService {
}
if (file == null) {
_logger.warning("Failed to get file for asset ${asset.id} - ${asset.name}");
return null;
}

View File

@@ -10,6 +10,7 @@ import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/extensions/network_capability_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
import 'package:immich_mobile/platform/connectivity_api.g.dart';
@@ -266,6 +267,10 @@ class ForegroundUploadService {
try {
final entity = await _storageRepository.getAssetEntityForAsset(asset);
if (entity == null) {
callbacks.onError?.call(
asset.localId!,
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
);
return;
}
@@ -298,6 +303,11 @@ class ForegroundUploadService {
// Get files locally
file = await _storageRepository.getFileForAsset(asset.id);
if (file == null) {
_logger.warning("Failed to get file ${asset.id} - ${asset.name}");
callbacks.onError?.call(
asset.localId!,
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
);
return;
}
@@ -306,12 +316,17 @@ class ForegroundUploadService {
livePhotoFile = await _storageRepository.getMotionFileForAsset(asset);
if (livePhotoFile == null) {
_logger.warning("Failed to obtain motion part of the livePhoto - ${asset.name}");
callbacks.onError?.call(
asset.localId!,
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
);
}
}
}
if (file == null) {
_logger.warning("Failed to obtain file for asset ${asset.id} - ${asset.name}");
_logger.warning("Failed to obtain file from iCloud for asset ${asset.id} - ${asset.name}");
callbacks.onError?.call(asset.localId!, "asset_not_found_on_icloud".t());
return;
}