mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
chore: handle requeue upload when target albums changed (#20089)
* chore: handle requeue upload when target albums changed * chore: remove debug
This commit is contained in:
parent
f1cac122ed
commit
1011cdb376
@ -1330,6 +1330,7 @@
|
|||||||
"no_results": "No results",
|
"no_results": "No results",
|
||||||
"no_results_description": "Try a synonym or more general keyword",
|
"no_results_description": "Try a synonym or more general keyword",
|
||||||
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
|
||||||
|
"no_uploads_in_progress": "No uploads in progress",
|
||||||
"not_in_any_album": "Not in any album",
|
"not_in_any_album": "Not in any album",
|
||||||
"not_selected": "Not selected",
|
"not_selected": "Not selected",
|
||||||
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
|
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
|
||||||
|
@ -44,9 +44,6 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||||||
(album) => album.backupSelection == BackupSelection.selected,
|
(album) => album.backupSelection == BackupSelection.selected,
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
final uploadItems = ref.watch(
|
|
||||||
driftBackupProvider.select((state) => state.uploadItems),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -85,14 +82,13 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||||||
onStart: () async => await startBackup(),
|
onStart: () async => await startBackup(),
|
||||||
onStop: () async => await stopBackup(),
|
onStop: () async => await stopBackup(),
|
||||||
),
|
),
|
||||||
if (uploadItems.isNotEmpty)
|
TextButton.icon(
|
||||||
TextButton.icon(
|
icon: const Icon(Icons.info_outline_rounded),
|
||||||
icon: const Icon(Icons.info_outline_rounded),
|
onPressed: () => context.pushRoute(
|
||||||
onPressed: () => context.pushRoute(
|
const DriftUploadDetailRoute(),
|
||||||
const DriftUploadDetailRoute(),
|
|
||||||
),
|
|
||||||
label: Text("view_details".t(context: context)),
|
|
||||||
),
|
),
|
||||||
|
label: Text("view_details".t(context: context)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -9,6 +9,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
|
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
|
||||||
@ -28,6 +29,8 @@ class _DriftBackupAlbumSelectionPageState
|
|||||||
extends ConsumerState<DriftBackupAlbumSelectionPage> {
|
extends ConsumerState<DriftBackupAlbumSelectionPage> {
|
||||||
String _searchQuery = '';
|
String _searchQuery = '';
|
||||||
bool _isSearchMode = false;
|
bool _isSearchMode = false;
|
||||||
|
int _initialTotalAssetCount = 0;
|
||||||
|
bool _hasPopped = false;
|
||||||
late ValueNotifier<bool> _enableSyncUploadAlbum;
|
late ValueNotifier<bool> _enableSyncUploadAlbum;
|
||||||
late TextEditingController _searchController;
|
late TextEditingController _searchController;
|
||||||
late FocusNode _searchFocusNode;
|
late FocusNode _searchFocusNode;
|
||||||
@ -43,6 +46,9 @@ class _DriftBackupAlbumSelectionPageState
|
|||||||
.read(appSettingsServiceProvider)
|
.read(appSettingsServiceProvider)
|
||||||
.getSetting(AppSettingsEnum.syncAlbums);
|
.getSetting(AppSettingsEnum.syncAlbums);
|
||||||
ref.read(backupAlbumProvider.notifier).getAll();
|
ref.read(backupAlbumProvider.notifier).getAll();
|
||||||
|
|
||||||
|
_initialTotalAssetCount =
|
||||||
|
ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -79,179 +85,207 @@ class _DriftBackupAlbumSelectionPageState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return PopScope(
|
||||||
appBar: AppBar(
|
onPopInvokedWithResult: (didPop, result) async {
|
||||||
leading: IconButton(
|
// There is an issue with Flutter where the pop event
|
||||||
onPressed: () => context.maybePop(),
|
// can be triggered multiple times, so we guard it with _hasPopped
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
if (didPop && !_hasPopped) {
|
||||||
),
|
_hasPopped = true;
|
||||||
title: _isSearchMode
|
|
||||||
? SearchField(
|
await ref.read(driftBackupProvider.notifier).getBackupStatus();
|
||||||
hintText: 'search_albums'.t(context: context),
|
final currentTotalAssetCount =
|
||||||
autofocus: true,
|
ref.read(driftBackupProvider.select((p) => p.totalCount));
|
||||||
controller: _searchController,
|
|
||||||
focusNode: _searchFocusNode,
|
if (currentTotalAssetCount != _initialTotalAssetCount) {
|
||||||
onChanged: (value) =>
|
final isBackupEnabled = ref
|
||||||
setState(() => _searchQuery = value.trim()),
|
.read(appSettingsServiceProvider)
|
||||||
|
.getSetting(AppSettingsEnum.enableBackup);
|
||||||
|
|
||||||
|
if (!isBackupEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final backupNotifier = ref.read(driftBackupProvider.notifier);
|
||||||
|
|
||||||
|
backupNotifier.cancel().then((_) {
|
||||||
|
backupNotifier.backup();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () async => await context.maybePop(),
|
||||||
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
|
),
|
||||||
|
title: _isSearchMode
|
||||||
|
? SearchField(
|
||||||
|
hintText: 'search_albums'.t(context: context),
|
||||||
|
autofocus: true,
|
||||||
|
controller: _searchController,
|
||||||
|
focusNode: _searchFocusNode,
|
||||||
|
onChanged: (value) =>
|
||||||
|
setState(() => _searchQuery = value.trim()),
|
||||||
|
)
|
||||||
|
: const Text(
|
||||||
|
"backup_album_selection_page_select_albums",
|
||||||
|
).t(context: context),
|
||||||
|
actions: [
|
||||||
|
if (!_isSearchMode)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.search),
|
||||||
|
onPressed: () => setState(() {
|
||||||
|
_isSearchMode = true;
|
||||||
|
_searchQuery = '';
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
: const Text(
|
else
|
||||||
"backup_album_selection_page_select_albums",
|
IconButton(
|
||||||
).t(context: context),
|
icon: const Icon(Icons.close),
|
||||||
actions: [
|
onPressed: () => setState(() {
|
||||||
if (!_isSearchMode)
|
_isSearchMode = false;
|
||||||
IconButton(
|
_searchQuery = '';
|
||||||
icon: const Icon(Icons.search),
|
_searchController.clear();
|
||||||
onPressed: () => setState(() {
|
}),
|
||||||
_isSearchMode = true;
|
),
|
||||||
_searchQuery = '';
|
],
|
||||||
}),
|
elevation: 0,
|
||||||
)
|
),
|
||||||
else
|
body: CustomScrollView(
|
||||||
IconButton(
|
physics: const ClampingScrollPhysics(),
|
||||||
icon: const Icon(Icons.close),
|
slivers: [
|
||||||
onPressed: () => setState(() {
|
SliverToBoxAdapter(
|
||||||
_isSearchMode = false;
|
child: Column(
|
||||||
_searchQuery = '';
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
_searchController.clear();
|
children: [
|
||||||
}),
|
Padding(
|
||||||
),
|
padding: const EdgeInsets.symmetric(
|
||||||
],
|
vertical: 8.0,
|
||||||
elevation: 0,
|
horizontal: 16.0,
|
||||||
),
|
|
||||||
body: CustomScrollView(
|
|
||||||
physics: const ClampingScrollPhysics(),
|
|
||||||
slivers: [
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 8.0,
|
|
||||||
horizontal: 16.0,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"backup_album_selection_page_selection_info",
|
|
||||||
style: context.textTheme.titleSmall,
|
|
||||||
).t(context: context),
|
|
||||||
),
|
|
||||||
// Selected Album Chips
|
|
||||||
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: Wrap(
|
|
||||||
children: [
|
|
||||||
_SelectedAlbumNameChips(
|
|
||||||
selectedBackupAlbums: selectedBackupAlbums,
|
|
||||||
),
|
|
||||||
_ExcludedAlbumNameChips(
|
|
||||||
excludedBackupAlbums: excludedBackupAlbums,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SettingsSwitchListTile(
|
|
||||||
valueNotifier: _enableSyncUploadAlbum,
|
|
||||||
title: "sync_albums".t(context: context),
|
|
||||||
subtitle:
|
|
||||||
"sync_upload_album_setting_subtitle".t(context: context),
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
titleStyle: context.textTheme.bodyLarge?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
subtitleStyle: context.textTheme.labelLarge?.copyWith(
|
|
||||||
color: context.colorScheme.primary,
|
|
||||||
),
|
|
||||||
onChanged: handleSyncAlbumToggle,
|
|
||||||
),
|
|
||||||
|
|
||||||
ListTile(
|
|
||||||
title: Text(
|
|
||||||
"albums_on_device_count".t(
|
|
||||||
context: context,
|
|
||||||
args: {'count': albumCount.toString()},
|
|
||||||
),
|
),
|
||||||
style: context.textTheme.titleSmall,
|
|
||||||
),
|
|
||||||
subtitle: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
"backup_album_selection_page_albums_tap",
|
"backup_album_selection_page_selection_info",
|
||||||
style: context.textTheme.labelLarge?.copyWith(
|
style: context.textTheme.titleSmall,
|
||||||
color: context.primaryColor,
|
|
||||||
),
|
|
||||||
).t(context: context),
|
).t(context: context),
|
||||||
),
|
),
|
||||||
trailing: IconButton(
|
// Selected Album Chips
|
||||||
splashRadius: 16,
|
|
||||||
icon: Icon(
|
|
||||||
Icons.info,
|
|
||||||
size: 20,
|
|
||||||
color: context.primaryColor,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
// show the dialog
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.all(Radius.circular(10)),
|
|
||||||
),
|
|
||||||
elevation: 5,
|
|
||||||
title: Text(
|
|
||||||
'backup_album_selection_page_selection_info',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: context.primaryColor,
|
|
||||||
),
|
|
||||||
).t(context: context),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: ListBody(
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'backup_album_selection_page_assets_scatter',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
).t(context: context),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
if (Platform.isAndroid)
|
Padding(
|
||||||
_SelectAllButton(
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
filteredAlbums: filteredAlbums,
|
child: Wrap(
|
||||||
selectedBackupAlbums: selectedBackupAlbums,
|
children: [
|
||||||
|
_SelectedAlbumNameChips(
|
||||||
|
selectedBackupAlbums: selectedBackupAlbums,
|
||||||
|
),
|
||||||
|
_ExcludedAlbumNameChips(
|
||||||
|
excludedBackupAlbums: excludedBackupAlbums,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
|
SettingsSwitchListTile(
|
||||||
|
valueNotifier: _enableSyncUploadAlbum,
|
||||||
|
title: "sync_albums".t(context: context),
|
||||||
|
subtitle: "sync_upload_album_setting_subtitle"
|
||||||
|
.t(context: context),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
titleStyle: context.textTheme.bodyLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
subtitleStyle: context.textTheme.labelLarge?.copyWith(
|
||||||
|
color: context.colorScheme.primary,
|
||||||
|
),
|
||||||
|
onChanged: handleSyncAlbumToggle,
|
||||||
|
),
|
||||||
|
|
||||||
|
ListTile(
|
||||||
|
title: Text(
|
||||||
|
"albums_on_device_count".t(
|
||||||
|
context: context,
|
||||||
|
args: {'count': albumCount.toString()},
|
||||||
|
),
|
||||||
|
style: context.textTheme.titleSmall,
|
||||||
|
),
|
||||||
|
subtitle: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Text(
|
||||||
|
"backup_album_selection_page_albums_tap",
|
||||||
|
style: context.textTheme.labelLarge?.copyWith(
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
).t(context: context),
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
splashRadius: 16,
|
||||||
|
icon: Icon(
|
||||||
|
Icons.info,
|
||||||
|
size: 20,
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
// show the dialog
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
elevation: 5,
|
||||||
|
title: Text(
|
||||||
|
'backup_album_selection_page_selection_info',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: context.primaryColor,
|
||||||
|
),
|
||||||
|
).t(context: context),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: ListBody(
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'backup_album_selection_page_assets_scatter',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
).t(context: context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (Platform.isAndroid)
|
||||||
|
_SelectAllButton(
|
||||||
|
filteredAlbums: filteredAlbums,
|
||||||
|
selectedBackupAlbums: selectedBackupAlbums,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SliverLayoutBuilder(
|
||||||
SliverLayoutBuilder(
|
builder: (context, constraints) {
|
||||||
builder: (context, constraints) {
|
if (constraints.crossAxisExtent > 600) {
|
||||||
if (constraints.crossAxisExtent > 600) {
|
return _AlbumSelectionGrid(
|
||||||
return _AlbumSelectionGrid(
|
filteredAlbums: filteredAlbums,
|
||||||
filteredAlbums: filteredAlbums,
|
searchQuery: _searchQuery,
|
||||||
searchQuery: _searchQuery,
|
);
|
||||||
);
|
} else {
|
||||||
} else {
|
return _AlbumSelectionList(
|
||||||
return _AlbumSelectionList(
|
filteredAlbums: filteredAlbums,
|
||||||
filteredAlbums: filteredAlbums,
|
searchQuery: _searchQuery,
|
||||||
searchQuery: _searchQuery,
|
);
|
||||||
);
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class DriftUploadDetailPage extends ConsumerWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Icons.cloud_upload_outlined,
|
Icons.cloud_off_rounded,
|
||||||
size: 80,
|
size: 80,
|
||||||
color: context.colorScheme.onSurface.withValues(alpha: 0.3),
|
color: context.colorScheme.onSurface.withValues(alpha: 0.3),
|
||||||
),
|
),
|
||||||
@ -79,7 +79,9 @@ class DriftUploadDetailPage extends ConsumerWidget {
|
|||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
color: context.colorScheme.surfaceContainer,
|
color: item.isFailed != null
|
||||||
|
? context.colorScheme.errorContainer
|
||||||
|
: context.colorScheme.surfaceContainer,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: const BorderRadius.all(
|
borderRadius: const BorderRadius.all(
|
||||||
Radius.circular(16),
|
Radius.circular(16),
|
||||||
|
@ -41,6 +41,7 @@ class DriftUploadStatus {
|
|||||||
final double progress;
|
final double progress;
|
||||||
final int fileSize;
|
final int fileSize;
|
||||||
final String networkSpeedAsString;
|
final String networkSpeedAsString;
|
||||||
|
final bool? isFailed;
|
||||||
|
|
||||||
const DriftUploadStatus({
|
const DriftUploadStatus({
|
||||||
required this.taskId,
|
required this.taskId,
|
||||||
@ -48,6 +49,7 @@ class DriftUploadStatus {
|
|||||||
required this.progress,
|
required this.progress,
|
||||||
required this.fileSize,
|
required this.fileSize,
|
||||||
required this.networkSpeedAsString,
|
required this.networkSpeedAsString,
|
||||||
|
this.isFailed,
|
||||||
});
|
});
|
||||||
|
|
||||||
DriftUploadStatus copyWith({
|
DriftUploadStatus copyWith({
|
||||||
@ -56,6 +58,7 @@ class DriftUploadStatus {
|
|||||||
double? progress,
|
double? progress,
|
||||||
int? fileSize,
|
int? fileSize,
|
||||||
String? networkSpeedAsString,
|
String? networkSpeedAsString,
|
||||||
|
bool? isFailed,
|
||||||
}) {
|
}) {
|
||||||
return DriftUploadStatus(
|
return DriftUploadStatus(
|
||||||
taskId: taskId ?? this.taskId,
|
taskId: taskId ?? this.taskId,
|
||||||
@ -63,12 +66,13 @@ class DriftUploadStatus {
|
|||||||
progress: progress ?? this.progress,
|
progress: progress ?? this.progress,
|
||||||
fileSize: fileSize ?? this.fileSize,
|
fileSize: fileSize ?? this.fileSize,
|
||||||
networkSpeedAsString: networkSpeedAsString ?? this.networkSpeedAsString,
|
networkSpeedAsString: networkSpeedAsString ?? this.networkSpeedAsString,
|
||||||
|
isFailed: isFailed ?? this.isFailed,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString)';
|
return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString, isFailed: $isFailed)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -79,7 +83,8 @@ class DriftUploadStatus {
|
|||||||
other.filename == filename &&
|
other.filename == filename &&
|
||||||
other.progress == progress &&
|
other.progress == progress &&
|
||||||
other.fileSize == fileSize &&
|
other.fileSize == fileSize &&
|
||||||
other.networkSpeedAsString == networkSpeedAsString;
|
other.networkSpeedAsString == networkSpeedAsString &&
|
||||||
|
other.isFailed == isFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -88,7 +93,8 @@ class DriftUploadStatus {
|
|||||||
filename.hashCode ^
|
filename.hashCode ^
|
||||||
progress.hashCode ^
|
progress.hashCode ^
|
||||||
fileSize.hashCode ^
|
fileSize.hashCode ^
|
||||||
networkSpeedAsString.hashCode;
|
networkSpeedAsString.hashCode ^
|
||||||
|
isFailed.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
@ -98,6 +104,7 @@ class DriftUploadStatus {
|
|||||||
'progress': progress,
|
'progress': progress,
|
||||||
'fileSize': fileSize,
|
'fileSize': fileSize,
|
||||||
'networkSpeedAsString': networkSpeedAsString,
|
'networkSpeedAsString': networkSpeedAsString,
|
||||||
|
'isFailed': isFailed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +115,7 @@ class DriftUploadStatus {
|
|||||||
progress: map['progress'] as double,
|
progress: map['progress'] as double,
|
||||||
fileSize: map['fileSize'] as int,
|
fileSize: map['fileSize'] as int,
|
||||||
networkSpeedAsString: map['networkSpeedAsString'] as String,
|
networkSpeedAsString: map['networkSpeedAsString'] as String,
|
||||||
|
isFailed: map['isFailed'] != null ? map['isFailed'] as bool : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +243,8 @@ class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
|
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
|
||||||
|
final taskId = update.task.taskId;
|
||||||
|
|
||||||
switch (update.status) {
|
switch (update.status) {
|
||||||
case TaskStatus.complete:
|
case TaskStatus.complete:
|
||||||
if (update.task.group == kBackupGroup) {
|
if (update.task.group == kBackupGroup) {
|
||||||
@ -245,14 +255,26 @@ class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the completed task from the upload items
|
// Remove the completed task from the upload items
|
||||||
final taskId = update.task.taskId;
|
|
||||||
if (state.uploadItems.containsKey(taskId)) {
|
if (state.uploadItems.containsKey(taskId)) {
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||||
_removeUploadItem(taskId);
|
_removeUploadItem(taskId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
case TaskStatus.failed:
|
case TaskStatus.failed:
|
||||||
|
final currentItem = state.uploadItems[taskId];
|
||||||
|
if (currentItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
uploadItems: {
|
||||||
|
...state.uploadItems,
|
||||||
|
taskId: currentItem.copyWith(
|
||||||
|
isFailed: true,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TaskStatus.canceled:
|
case TaskStatus.canceled:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user