chore: show error message in upload details route (#22472)

* chore: show error message in upload details route

* pretty format exception

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong 2025-09-29 23:01:09 +05:30 committed by GitHub
parent ee3c07d049
commit 75b9bd163e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 8 deletions

View File

@ -1,3 +1,5 @@
import 'dart:convert';
extension StringExtension on String {
String capitalize() {
return split(" ").map((str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1)).join(" ");
@ -23,3 +25,11 @@ extension DurationExtension on String {
return int.parse(this);
}
}
Map<String, dynamic>? tryJsonDecode(dynamic json) {
try {
return jsonDecode(json) as Map<String, dynamic>;
} catch (e) {
return null;
}
}

View File

@ -1,12 +1,12 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
import 'package:immich_mobile/utils/bytes_units.dart';
import 'package:path/path.dart' as path;
@ -82,6 +82,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4,
children: [
Text(
path.basename(item.filename),
@ -89,7 +90,13 @@ class DriftUploadDetailPage extends ConsumerWidget {
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
if (item.error != null)
Text(
item.error!,
style: context.textTheme.bodySmall?.copyWith(
color: context.colorScheme.onErrorContainer.withValues(alpha: 0.6),
),
),
Text(
'Tap for more details',
style: context.textTheme.bodySmall?.copyWith(

View File

@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/string_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
@ -35,6 +36,7 @@ class DriftUploadStatus {
final int fileSize;
final String networkSpeedAsString;
final bool? isFailed;
final String? error;
const DriftUploadStatus({
required this.taskId,
@ -43,6 +45,7 @@ class DriftUploadStatus {
required this.fileSize,
required this.networkSpeedAsString,
this.isFailed,
this.error,
});
DriftUploadStatus copyWith({
@ -52,6 +55,7 @@ class DriftUploadStatus {
int? fileSize,
String? networkSpeedAsString,
bool? isFailed,
String? error,
}) {
return DriftUploadStatus(
taskId: taskId ?? this.taskId,
@ -60,12 +64,13 @@ class DriftUploadStatus {
fileSize: fileSize ?? this.fileSize,
networkSpeedAsString: networkSpeedAsString ?? this.networkSpeedAsString,
isFailed: isFailed ?? this.isFailed,
error: error ?? this.error,
);
}
@override
String toString() {
return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString, isFailed: $isFailed)';
return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString, isFailed: $isFailed, error: $error)';
}
@override
@ -77,7 +82,8 @@ class DriftUploadStatus {
other.progress == progress &&
other.fileSize == fileSize &&
other.networkSpeedAsString == networkSpeedAsString &&
other.isFailed == isFailed;
other.isFailed == isFailed &&
other.error == error;
}
@override
@ -87,7 +93,8 @@ class DriftUploadStatus {
progress.hashCode ^
fileSize.hashCode ^
networkSpeedAsString.hashCode ^
isFailed.hashCode;
isFailed.hashCode ^
error.hashCode;
}
}
@ -247,7 +254,23 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
return;
}
state = state.copyWith(uploadItems: {...state.uploadItems, taskId: currentItem.copyWith(isFailed: true)});
String? error;
final exception = update.exception;
if (exception != null && exception is TaskHttpException) {
final message = tryJsonDecode(exception.description)?['message'] as String?;
if (message != null) {
final responseCode = exception.httpResponseCode;
error = "${exception.exceptionType}, response code $responseCode: $message";
}
}
error ??= update.exception?.toString();
state = state.copyWith(
uploadItems: {
...state.uploadItems,
taskId: currentItem.copyWith(isFailed: true, error: error),
},
);
_logger.fine("Upload failed for taskId: $taskId, exception: ${update.exception}");
break;