Add information for uploading asset and error indication with error message for each failed upload. ()

* Added info box

* Fixed upload endpoint doesn't report error status code

* Added chip to show update error

* Added chip to show failed upload

* Add duplication check for upload

* Better duplication-checking placement

* Remove check for duplicated asset

* Added failed backup status route

* added page

* Display error card with thumbnail

* Improved styling

* Set thumbnail with better quality

* Remove force upload error
This commit is contained in:
Alex 2022-07-06 16:12:55 -05:00 committed by GitHub
parent 357f7d1c31
commit 58ec7553ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 706 additions and 87 deletions
mobile/lib/modules/backup/views

View file

@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/backup/providers/error_backup_list.provider.dart';
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
import 'package:immich_mobile/modules/backup/models/backup_state.model.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
@ -9,6 +10,7 @@ import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
import 'package:immich_mobile/modules/backup/ui/backup_info_card.dart';
import 'package:intl/intl.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
class BackupControllerPage extends HookConsumerWidget {
@ -42,7 +44,7 @@ class BackupControllerPage extends HookConsumerWidget {
color: Theme.of(context).primaryColor,
),
title: const Text(
"Server Storage",
"Server storage",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
subtitle: Padding(
@ -56,7 +58,7 @@ class BackupControllerPage extends HookConsumerWidget {
padding:
const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
barRadius: const Radius.circular(2),
lineHeight: 6.0,
lineHeight: 10.0,
percent: backupState.serverInfo.diskUsagePercentage / 100.0,
backgroundColor: Colors.grey,
progressColor: Theme.of(context).primaryColor,
@ -246,6 +248,141 @@ class BackupControllerPage extends HookConsumerWidget {
);
}
_buildCurrentBackupAssetInfoCard() {
return ListTile(
leading: Icon(
Icons.info_outline_rounded,
color: Theme.of(context).primaryColor,
),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Uploading file info",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
if (ref.watch(errorBackupListProvider).isNotEmpty)
ActionChip(
avatar: Icon(
Icons.info,
size: 24,
color: Colors.red[400],
),
elevation: 1,
visualDensity: VisualDensity.compact,
label: Text(
"Failed (${ref.watch(errorBackupListProvider).length})",
style: TextStyle(
color: Colors.red[400],
fontWeight: FontWeight.bold,
fontSize: 11,
),
),
backgroundColor: Colors.white,
onPressed: () {
AutoRouter.of(context).push(const FailedBackupStatusRoute());
},
),
],
),
subtitle: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: LinearPercentIndicator(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
barRadius: const Radius.circular(2),
lineHeight: 10.0,
trailing: Text(
" ${backupState.progressInPercentage.toStringAsFixed(0)}%",
style: const TextStyle(fontSize: 12),
),
percent: backupState.progressInPercentage / 100.0,
backgroundColor: Colors.grey,
progressColor: Theme.of(context).primaryColor,
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Table(
border: TableBorder.all(
color: Colors.black12,
width: 1,
),
children: [
TableRow(
decoration: BoxDecoration(
color: Colors.grey[100],
),
children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
'File name: ${backupState.currentUploadAsset.fileName} [${backupState.currentUploadAsset.fileType.toLowerCase()}]',
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 10.0),
),
),
),
],
),
TableRow(
decoration: BoxDecoration(
color: Colors.grey[200],
),
children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"Created on: ${DateFormat.yMMMMd('en_US').format(
DateTime.parse(
backupState.currentUploadAsset.createdAt
.toString(),
),
)}",
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 10.0),
),
),
),
],
),
TableRow(
decoration: BoxDecoration(
color: Colors.grey[100],
),
children: [
TableCell(
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"ID: ${backupState.currentUploadAsset.id}",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10.0,
),
),
),
),
],
),
],
),
),
],
),
);
}
void startBackup() {
ref.watch(errorBackupListProvider.notifier).empty();
ref.watch(backupProvider.notifier).startBackupProcess();
}
return Scaffold(
appBar: AppBar(
elevation: 0,
@ -264,7 +401,7 @@ class BackupControllerPage extends HookConsumerWidget {
)),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32),
child: ListView(
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -297,23 +434,11 @@ class BackupControllerPage extends HookConsumerWidget {
const Divider(),
_buildStorageInformation(),
const Divider(),
_buildCurrentBackupAssetInfoCard(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Asset that were being backup: ${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Row(children: [
const Text("Backup Progress:"),
const Padding(padding: EdgeInsets.symmetric(horizontal: 2)),
backupState.backupProgress == BackUpProgressEnum.inProgress
? const CircularProgressIndicator.adaptive()
: const Text("Done"),
]),
),
Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.only(
top: 24,
),
child: Container(
child:
backupState.backupProgress == BackUpProgressEnum.inProgress
@ -321,25 +446,33 @@ class BackupControllerPage extends HookConsumerWidget {
style: ElevatedButton.styleFrom(
primary: Colors.red[300],
onPrimary: Colors.grey[50],
padding: const EdgeInsets.all(14),
),
onPressed: () {
ref.read(backupProvider.notifier).cancelBackup();
},
child: const Text("Cancel"),
child: const Text(
"CANCEL",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
)
: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Theme.of(context).primaryColor,
onPrimary: Colors.grey[50],
padding: const EdgeInsets.all(14),
),
onPressed: shouldBackup ? startBackup : null,
child: const Text(
"START BACKUP",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
onPressed: shouldBackup
? () {
ref
.read(backupProvider.notifier)
.startBackupProcess();
}
: null,
child: const Text("Start Backup"),
),
),
)