Refactor mobile to use OpenApi generated SDK (#336)

This commit is contained in:
Alex 2022-07-13 07:23:48 -05:00 committed by GitHub
parent d69470e207
commit ae7e582ec8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
276 changed files with 14513 additions and 3003 deletions

View file

@ -1,10 +1,10 @@
import 'package:cancellation_token_http/http.dart';
import 'package:collection/collection.dart';
import 'package:openapi/api.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:immich_mobile/modules/backup/models/available_album.model.dart';
import 'package:immich_mobile/modules/backup/models/current_upload_asset.model.dart';
import 'package:immich_mobile/shared/models/server_info.model.dart';
enum BackUpProgressEnum { idle, inProgress, done }
@ -14,7 +14,7 @@ class BackUpState {
final List<String> allAssetsInDatabase;
final double progressInPercentage;
final CancellationToken cancelToken;
final ServerInfo serverInfo;
final ServerInfoResponseDto serverInfo;
/// All available albums on the device
final List<AvailableAlbum> availableAlbums;
@ -49,7 +49,7 @@ class BackUpState {
List<String>? allAssetsInDatabase,
double? progressInPercentage,
CancellationToken? cancelToken,
ServerInfo? serverInfo,
ServerInfoResponseDto? serverInfo,
List<AvailableAlbum>? availableAlbums,
Set<AssetPathEntity>? selectedBackupAlbums,
Set<AssetPathEntity>? excludedBackupAlbums,
@ -93,8 +93,10 @@ class BackUpState {
collectionEquals(other.selectedBackupAlbums, selectedBackupAlbums) &&
collectionEquals(other.excludedBackupAlbums, excludedBackupAlbums) &&
collectionEquals(other.allUniqueAssets, allUniqueAssets) &&
collectionEquals(other.selectedAlbumsBackupAssetsIds,
selectedAlbumsBackupAssetsIds) &&
collectionEquals(
other.selectedAlbumsBackupAssetsIds,
selectedAlbumsBackupAssetsIds,
) &&
other.currentUploadAsset == currentUploadAsset;
}

View file

@ -1,48 +0,0 @@
import 'dart:convert';
class CheckDuplicateAssetResponse {
final bool isExist;
CheckDuplicateAssetResponse({
required this.isExist,
});
CheckDuplicateAssetResponse copyWith({
bool? isExist,
}) {
return CheckDuplicateAssetResponse(
isExist: isExist ?? this.isExist,
);
}
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'isExist': isExist});
return result;
}
factory CheckDuplicateAssetResponse.fromMap(Map<String, dynamic> map) {
return CheckDuplicateAssetResponse(
isExist: map['isExist'] ?? false,
);
}
String toJson() => json.encode(toMap());
factory CheckDuplicateAssetResponse.fromJson(String source) =>
CheckDuplicateAssetResponse.fromMap(json.decode(source));
@override
String toString() => 'CheckDuplicateAssetResponse(isExist: $isExist)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is CheckDuplicateAssetResponse && other.isExist == isExist;
}
@override
int get hashCode => isExist.hashCode;
}

View file

@ -12,8 +12,8 @@ import 'package:immich_mobile/modules/backup/providers/error_backup_list.provide
import 'package:immich_mobile/modules/backup/services/backup.service.dart';
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/shared/models/server_info.model.dart';
import 'package:immich_mobile/shared/services/server_info.service.dart';
import 'package:openapi/api.dart';
import 'package:photo_manager/photo_manager.dart';
class BackupNotifier extends StateNotifier<BackUpState> {
@ -28,12 +28,12 @@ class BackupNotifier extends StateNotifier<BackUpState> {
allAssetsInDatabase: const [],
progressInPercentage: 0,
cancelToken: CancellationToken(),
serverInfo: ServerInfo(
serverInfo: ServerInfoResponseDto(
diskAvailable: "0",
diskAvailableRaw: 0,
diskSize: "0",
diskSizeRaw: 0,
diskUsagePercentage: 0.0,
diskUsagePercentage: 0,
diskUse: "0",
diskUseRaw: 0,
),
@ -113,7 +113,9 @@ class BackupNotifier extends StateNotifier<BackUpState> {
// Get all albums on the device
List<AvailableAlbum> availableAlbums = [];
List<AssetPathEntity> albums = await PhotoManager.getAssetPathList(
hasAll: true, type: RequestType.common);
hasAll: true,
type: RequestType.common,
);
for (AssetPathEntity album in albums) {
AvailableAlbum availableAlbum = AvailableAlbum(albumEntity: album);
@ -156,7 +158,10 @@ class BackupNotifier extends StateNotifier<BackUpState> {
// Get album that contains all assets
var list = await PhotoManager.getAssetPathList(
hasAll: true, onlyAll: true, type: RequestType.common);
hasAll: true,
onlyAll: true,
type: RequestType.common,
);
AssetPathEntity albumHasAllAssets = list.first;
backupAlbumInfoBox.put(
@ -175,13 +180,15 @@ class BackupNotifier extends StateNotifier<BackUpState> {
for (var selectedAlbumId in backupAlbumInfo!.selectedAlbumIds) {
var albumAsset = await AssetPathEntity.fromId(selectedAlbumId);
state = state.copyWith(
selectedBackupAlbums: {...state.selectedBackupAlbums, albumAsset});
selectedBackupAlbums: {...state.selectedBackupAlbums, albumAsset},
);
}
for (var excludedAlbumId in backupAlbumInfo.excludedAlbumsIds) {
var albumAsset = await AssetPathEntity.fromId(excludedAlbumId);
state = state.copyWith(
excludedBackupAlbums: {...state.excludedBackupAlbums, albumAsset});
excludedBackupAlbums: {...state.excludedBackupAlbums, albumAsset},
);
}
} catch (e) {
debugPrint("[ERROR] Failed to generate album from id $e");
@ -211,8 +218,11 @@ class BackupNotifier extends StateNotifier<BackUpState> {
Set<AssetEntity> allUniqueAssets =
assetsFromSelectedAlbums.difference(assetsFromExcludedAlbums);
List<String> allAssetsInDatabase =
await _backupService.getDeviceBackupAsset();
var allAssetsInDatabase = await _backupService.getDeviceBackupAsset();
if (allAssetsInDatabase == null) {
return;
}
// Find asset that were backup from selected albums
Set<String> selectedAlbumsBackupAssets =
@ -328,23 +338,27 @@ class BackupNotifier extends StateNotifier<BackUpState> {
void cancelBackup() {
state.cancelToken.cancel();
state = state.copyWith(
backupProgress: BackUpProgressEnum.idle, progressInPercentage: 0.0);
backupProgress: BackUpProgressEnum.idle,
progressInPercentage: 0.0,
);
}
void _onAssetUploaded(String deviceAssetId, String deviceId) {
state = state.copyWith(selectedAlbumsBackupAssetsIds: {
...state.selectedAlbumsBackupAssetsIds,
deviceAssetId
}, allAssetsInDatabase: [
...state.allAssetsInDatabase,
deviceAssetId
]);
state = state.copyWith(
selectedAlbumsBackupAssetsIds: {
...state.selectedAlbumsBackupAssetsIds,
deviceAssetId
},
allAssetsInDatabase: [...state.allAssetsInDatabase, deviceAssetId],
);
if (state.allUniqueAssets.length -
state.selectedAlbumsBackupAssetsIds.length ==
0) {
state = state.copyWith(
backupProgress: BackUpProgressEnum.done, progressInPercentage: 0.0);
backupProgress: BackUpProgressEnum.done,
progressInPercentage: 0.0,
);
}
_updateServerInfo();
@ -352,24 +366,19 @@ class BackupNotifier extends StateNotifier<BackUpState> {
void _onUploadProgress(int sent, int total) {
state = state.copyWith(
progressInPercentage: (sent.toDouble() / total.toDouble() * 100));
progressInPercentage: (sent.toDouble() / total.toDouble() * 100),
);
}
Future<void> _updateServerInfo() async {
var serverInfo = await _serverInfoService.getServerInfo();
// Update server info
state = state.copyWith(
serverInfo: ServerInfo(
diskSize: serverInfo.diskSize,
diskUse: serverInfo.diskUse,
diskAvailable: serverInfo.diskAvailable,
diskSizeRaw: serverInfo.diskSizeRaw,
diskUseRaw: serverInfo.diskUseRaw,
diskAvailableRaw: serverInfo.diskAvailableRaw,
diskUsagePercentage: serverInfo.diskUsagePercentage,
),
);
if (serverInfo != null) {
state = state.copyWith(
serverInfo: serverInfo,
);
}
}
void resumeBackup() {

View file

@ -2,59 +2,38 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/backup/models/check_duplicate_asset_response.model.dart';
import 'package:immich_mobile/modules/backup/models/current_upload_asset.model.dart';
import 'package:immich_mobile/modules/backup/models/error_upload_asset.model.dart';
import 'package:immich_mobile/shared/services/network.service.dart';
import 'package:immich_mobile/shared/models/device_info.model.dart';
import 'package:immich_mobile/shared/services/api.service.dart';
import 'package:immich_mobile/utils/files_helper.dart';
import 'package:openapi/api.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:http_parser/http_parser.dart';
import 'package:path/path.dart' as p;
import 'package:cancellation_token_http/http.dart' as http;
final backupServiceProvider =
Provider((ref) => BackupService(ref.watch(networkServiceProvider)));
final backupServiceProvider = Provider(
(ref) => BackupService(
ref.watch(apiServiceProvider),
),
);
class BackupService {
final NetworkService _networkService;
final ApiService _apiService;
BackupService(this._apiService);
BackupService(this._networkService);
Future<List<String>> getDeviceBackupAsset() async {
String deviceId = Hive.box(userInfoBox).get(deviceIdKey);
Response response =
await _networkService.getRequest(url: "asset/$deviceId");
List<dynamic> result = jsonDecode(response.toString());
return result.cast<String>();
}
Future<bool> checkDuplicateAsset(String deviceAssetId) async {
Future<List<String>?> getDeviceBackupAsset() async {
String deviceId = Hive.box(userInfoBox).get(deviceIdKey);
try {
Response response =
await _networkService.postRequest(url: "asset/check", data: {
"deviceId": deviceId,
"deviceAssetId": deviceAssetId,
});
if (response.statusCode == 200) {
var result = CheckDuplicateAssetResponse.fromJson(response.toString());
return result.isExist;
} else {
return false;
}
return await _apiService.assetApi.getUserAssetsByDeviceId(deviceId);
} catch (e) {
return false;
debugPrint('Error [getDeviceBackupAsset] ${e.toString()}');
return null;
}
}
@ -99,9 +78,11 @@ class BackupService {
var box = Hive.box(userInfoBox);
var req = MultipartRequest(
'POST', Uri.parse('$savedEndpoint/asset/upload'),
onProgress: ((bytes, totalBytes) =>
uploadProgressCb(bytes, totalBytes)));
'POST',
Uri.parse('$savedEndpoint/asset/upload'),
onProgress: ((bytes, totalBytes) =>
uploadProgressCb(bytes, totalBytes)),
);
req.headers["Authorization"] = "Bearer ${box.get(accessTokenKey)}";
req.fields['deviceAssetId'] = entity.id;
@ -133,16 +114,19 @@ class BackupService {
var error = jsonDecode(data);
debugPrint(
"Error(${error['statusCode']}) uploading ${entity.id} | $originalFileName | Created on ${entity.createDateTime} | ${error['error']}");
"Error(${error['statusCode']}) uploading ${entity.id} | $originalFileName | Created on ${entity.createDateTime} | ${error['error']}",
);
errorCb(ErrorUploadAsset(
asset: entity,
id: entity.id,
createdAt: entity.createDateTime,
fileName: originalFileName,
fileType: _getAssetType(entity.type),
errorMessage: error['error'],
));
errorCb(
ErrorUploadAsset(
asset: entity,
id: entity.id,
createdAt: entity.createDateTime,
fileName: originalFileName,
fileType: _getAssetType(entity.type),
errorMessage: error['error'],
),
);
continue;
}
}
@ -160,8 +144,6 @@ class BackupService {
}
}
void sendBackupRequest(AssetEntity entity) {}
String _getAssetType(AssetType assetType) {
switch (assetType) {
case AssetType.audio:
@ -175,15 +157,29 @@ class BackupService {
}
}
Future<DeviceInfoRemote> setAutoBackup(
bool status, String deviceId, String deviceType) async {
var res = await _networkService.patchRequest(url: 'device-info', data: {
"isAutoBackup": status,
"deviceId": deviceId,
"deviceType": deviceType,
});
Future<DeviceInfoResponseDto> setAutoBackup(
bool status,
String deviceId,
DeviceTypeEnum deviceType,
) async {
try {
var updatedDeviceInfo = await _apiService.deviceInfoApi.updateDeviceInfo(
UpdateDeviceInfoDto(
deviceId: deviceId,
deviceType: deviceType,
isAutoBackup: status,
),
);
return DeviceInfoRemote.fromJson(res.toString());
if (updatedDeviceInfo == null) {
throw Exception("Error updating device info");
}
return updatedDeviceInfo;
} catch (e) {
debugPrint("Error setAutoBackup: ${e.toString()}");
throw Error();
}
}
}

View file

@ -26,7 +26,9 @@ class AlbumInfoCard extends HookConsumerWidget {
ref.watch(backupProvider).excludedBackupAlbums.contains(albumInfo);
ColorFilter selectedFilter = ColorFilter.mode(
Theme.of(context).primaryColor.withAlpha(100), BlendMode.darken);
Theme.of(context).primaryColor.withAlpha(100),
BlendMode.darken,
);
ColorFilter excludedFilter =
ColorFilter.mode(Colors.red.withAlpha(75), BlendMode.darken);
ColorFilter unselectedFilter =
@ -40,7 +42,10 @@ class AlbumInfoCard extends HookConsumerWidget {
label: const Text(
"album_info_card_backup_album_included",
style: TextStyle(
fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold),
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold,
),
).tr(),
backgroundColor: Theme.of(context).primaryColor,
);
@ -51,7 +56,10 @@ class AlbumInfoCard extends HookConsumerWidget {
label: const Text(
"album_info_card_backup_album_excluded",
style: TextStyle(
fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold),
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold,
),
).tr(),
backgroundColor: Colors.red[300],
);
@ -138,15 +146,16 @@ class AlbumInfoCard extends HookConsumerWidget {
height: 200,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12)),
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
image: DecorationImage(
colorFilter: _buildImageFilter(),
image: imageData != null
? MemoryImage(imageData!)
: const AssetImage(
'assets/immich-logo-no-outline.png')
as ImageProvider,
'assets/immich-logo-no-outline.png',
) as ImageProvider,
fit: BoxFit.cover,
),
),
@ -174,9 +183,10 @@ class AlbumInfoCard extends HookConsumerWidget {
Text(
albumInfo.name,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold),
fontSize: 14,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
),
),
Padding(
padding: const EdgeInsets.only(top: 2.0),
@ -186,7 +196,9 @@ class AlbumInfoCard extends HookConsumerWidget {
? " (${'backup_all'.tr()})"
: ""),
style: TextStyle(
fontSize: 12, color: Colors.grey[600]),
fontSize: 12,
color: Colors.grey[600],
),
),
)
],

View file

@ -5,12 +5,12 @@ class BackupInfoCard extends StatelessWidget {
final String title;
final String subtitle;
final String info;
const BackupInfoCard(
{Key? key,
required this.title,
required this.subtitle,
required this.info})
: super(key: key);
const BackupInfoCard({
Key? key,
required this.title,
required this.subtitle,
required this.info,
}) : super(key: key);
@override
Widget build(BuildContext context) {

View file

@ -20,10 +20,13 @@ class AlbumPreviewPage extends HookConsumerWidget {
await album.getAssetListRange(start: 0, end: album.assetCount);
}
useEffect(() {
_getAssetsInAlbum();
return null;
}, []);
useEffect(
() {
_getAssetsInAlbum();
return null;
},
[],
);
return Scaffold(
appBar: AppBar(
@ -39,9 +42,10 @@ class AlbumPreviewPage extends HookConsumerWidget {
child: Text(
"ID ${album.id}",
style: TextStyle(
fontSize: 10,
color: Colors.grey[600],
fontWeight: FontWeight.bold),
fontSize: 10,
color: Colors.grey[600],
fontWeight: FontWeight.bold,
),
),
),
],
@ -59,9 +63,11 @@ class AlbumPreviewPage extends HookConsumerWidget {
),
itemCount: assets.value.length,
itemBuilder: (context, index) {
Future<Uint8List?> thumbData = assets.value[index]
.thumbnailDataWithSize(const ThumbnailSize(200, 200),
quality: 50);
Future<Uint8List?> thumbData =
assets.value[index].thumbnailDataWithSize(
const ThumbnailSize(200, 200),
quality: 50,
);
return FutureBuilder<Uint8List?>(
future: thumbData,

View file

@ -17,10 +17,13 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
final selectedBackupAlbums = ref.watch(backupProvider).selectedBackupAlbums;
final excludedBackupAlbums = ref.watch(backupProvider).excludedBackupAlbums;
useEffect(() {
ref.read(backupProvider.notifier).getBackupInfo();
return null;
}, []);
useEffect(
() {
ref.read(backupProvider.notifier).getBackupInfo();
return null;
},
[],
);
_buildAlbumSelectionList() {
if (availableAlbums.isEmpty) {
@ -42,8 +45,9 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
? const EdgeInsets.only(left: 16.00)
: const EdgeInsets.all(0),
child: AlbumInfoCard(
imageData: thumbnailData,
albumInfo: availableAlbums[index].albumEntity),
imageData: thumbnailData,
albumInfo: availableAlbums[index].albumEntity,
),
);
}),
),
@ -73,13 +77,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
child: Chip(
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)),
borderRadius: BorderRadius.circular(5),
),
label: Text(
album.name,
style: const TextStyle(
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold),
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Theme.of(context).primaryColor,
deleteIconColor: Colors.white,
@ -109,13 +115,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
child: Chip(
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)),
borderRadius: BorderRadius.circular(5),
),
label: Text(
album.name,
style: const TextStyle(
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold),
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.red[300],
deleteIconColor: Colors.white,
@ -185,9 +193,10 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
title: Text(
"backup_album_selection_page_total_assets",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Colors.grey[700]),
fontWeight: FontWeight.bold,
fontSize: 14,
color: Colors.grey[700],
),
).tr(),
trailing: Text(
ref
@ -234,7 +243,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
borderRadius: BorderRadius.circular(12),
),
elevation: 5,
title: Text(
'backup_album_selection_page_selection_info',
@ -250,7 +260,9 @@ class BackupAlbumSelectionPage extends HookConsumerWidget {
Text(
'backup_album_selection_page_assets_scatter',
style: TextStyle(
fontSize: 14, color: Colors.grey[700]),
fontSize: 14,
color: Colors.grey[700],
),
).tr(),
],
),

View file

@ -11,7 +11,6 @@ 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 {
@ -27,16 +26,19 @@ class BackupControllerPage extends HookConsumerWidget {
? false
: true;
useEffect(() {
if (backupState.backupProgress != BackUpProgressEnum.inProgress) {
ref.watch(backupProvider.notifier).getBackupInfo();
}
useEffect(
() {
if (backupState.backupProgress != BackUpProgressEnum.inProgress) {
ref.watch(backupProvider.notifier).getBackupInfo();
}
ref
.watch(websocketProvider.notifier)
.stopListenToEvent('on_upload_success');
return null;
}, []);
ref
.watch(websocketProvider.notifier)
.stopListenToEvent('on_upload_success');
return null;
},
[],
);
Widget _buildStorageInformation() {
return ListTile(
@ -68,10 +70,11 @@ class BackupControllerPage extends HookConsumerWidget {
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: const Text('backup_controller_page_storage_format').tr(
args: [
backupState.serverInfo.diskUse,
backupState.serverInfo.diskSize
]),
args: [
backupState.serverInfo.diskUse,
backupState.serverInfo.diskSize
],
),
),
],
),
@ -129,8 +132,10 @@ class BackupControllerPage extends HookConsumerWidget {
.setAutoBackup(true);
}
},
child: Text(backupBtnText,
style: const TextStyle(fontWeight: FontWeight.bold)),
child: Text(
backupBtnText,
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
)
],
@ -157,9 +162,10 @@ class BackupControllerPage extends HookConsumerWidget {
child: Text(
text.trim().substring(0, text.length - 2),
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 12,
fontWeight: FontWeight.bold),
color: Theme.of(context).primaryColor,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
);
} else {
@ -168,9 +174,10 @@ class BackupControllerPage extends HookConsumerWidget {
child: Text(
"backup_controller_page_none_selected".tr(),
style: TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 12,
fontWeight: FontWeight.bold),
color: Theme.of(context).primaryColor,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
);
}
@ -190,9 +197,10 @@ class BackupControllerPage extends HookConsumerWidget {
child: Text(
text.trim().substring(0, text.length - 2),
style: TextStyle(
color: Colors.red[300],
fontSize: 12,
fontWeight: FontWeight.bold),
color: Colors.red[300],
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
);
} else {
@ -213,9 +221,10 @@ class BackupControllerPage extends HookConsumerWidget {
borderOnForeground: false,
child: ListTile(
minVerticalPadding: 15,
title: const Text("backup_controller_page_albums",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20))
.tr(),
title: const Text(
"backup_controller_page_albums",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
).tr(),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
@ -284,9 +293,9 @@ class BackupControllerPage extends HookConsumerWidget {
fontWeight: FontWeight.bold,
fontSize: 11,
),
).tr(args: [
ref.watch(errorBackupListProvider).length.toString()
]),
).tr(
args: [ref.watch(errorBackupListProvider).length.toString()],
),
backgroundColor: Colors.white,
onPressed: () {
AutoRouter.of(context).push(const FailedBackupStatusRoute());
@ -331,12 +340,16 @@ class BackupControllerPage extends HookConsumerWidget {
child: const Text(
'backup_controller_page_filename',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 10.0),
).tr(args: [
backupState.currentUploadAsset.fileName,
backupState.currentUploadAsset.fileType
.toLowerCase()
]),
fontWeight: FontWeight.bold,
fontSize: 10.0,
),
).tr(
args: [
backupState.currentUploadAsset.fileName,
backupState.currentUploadAsset.fileType
.toLowerCase()
],
),
),
),
],
@ -352,16 +365,20 @@ class BackupControllerPage extends HookConsumerWidget {
padding: const EdgeInsets.all(6.0),
child: const Text(
"backup_controller_page_created",
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 10.0),
).tr(args: [
DateFormat.yMMMMd('en_US').format(
DateTime.parse(
backupState.currentUploadAsset.createdAt
.toString(),
),
)
]),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10.0,
),
).tr(
args: [
DateFormat.yMMMMd('en_US').format(
DateTime.parse(
backupState.currentUploadAsset.createdAt
.toString(),
),
)
],
),
),
),
],
@ -406,14 +423,15 @@ class BackupControllerPage extends HookConsumerWidget {
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
).tr(),
leading: IconButton(
onPressed: () {
ref.watch(websocketProvider.notifier).listenUploadEvent();
AutoRouter.of(context).pop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
)),
onPressed: () {
ref.watch(websocketProvider.notifier).listenUploadEvent();
AutoRouter.of(context).pop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
),
),
body: Padding(
padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32),

View file

@ -19,13 +19,14 @@ class FailedBackupStatusPage extends HookConsumerWidget {
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
leading: IconButton(
onPressed: () {
AutoRouter.of(context).pop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
)),
onPressed: () {
AutoRouter.of(context).pop(true);
},
splashRadius: 24,
icon: const Icon(
Icons.arrow_back_ios_rounded,
),
),
),
body: ListView.builder(
shrinkWrap: true,
@ -92,9 +93,10 @@ class FailedBackupStatusPage extends HookConsumerWidget {
),
),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.grey[700]),
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.grey[700],
),
),
Icon(
Icons.error,