diff --git a/ui/flutter/lib/api/model/downloader_config.dart b/ui/flutter/lib/api/model/downloader_config.dart index 5cab59455..2e3a0efcd 100644 --- a/ui/flutter/lib/api/model/downloader_config.dart +++ b/ui/flutter/lib/api/model/downloader_config.dart @@ -17,6 +17,7 @@ class DownloaderConfig { factory DownloaderConfig.fromJson(Map json) => _$DownloaderConfigFromJson(json); + Map toJson() => _$DownloaderConfigToJson(this); } @@ -29,6 +30,7 @@ class ProtocolConfig { factory ProtocolConfig.fromJson(Map? json) => json == null ? ProtocolConfig() : _$ProtocolConfigFromJson(json); + Map toJson() => _$ProtocolConfigToJson(this); } @@ -47,6 +49,7 @@ class HttpConfig { factory HttpConfig.fromJson(Map json) => _$HttpConfigFromJson(json); + Map toJson() => _$HttpConfigToJson(this); } @@ -59,19 +62,27 @@ class BtConfig { factory BtConfig.fromJson(Map json) => _$BtConfigFromJson(json); + Map toJson() => _$BtConfigToJson(this); } @JsonSerializable(explicitToJson: true) class ExtraConfig { - String themeMode = ''; - String locale = ''; + String themeMode; + String locale; + bool lastDeleteTaskKeep; + ExtraConfigBt bt = ExtraConfigBt(); - ExtraConfig(); + ExtraConfig({ + this.themeMode = '', + this.locale = '', + this.lastDeleteTaskKeep = false, + }); factory ExtraConfig.fromJson(Map? json) => json == null ? ExtraConfig() : _$ExtraConfigFromJson(json); + Map toJson() => _$ExtraConfigToJson(this); } @@ -112,5 +123,6 @@ class ExtraConfigBt { factory ExtraConfigBt.fromJson(Map json) => _$ExtraConfigBtFromJson(json); + Map toJson() => _$ExtraConfigBtToJson(this); } diff --git a/ui/flutter/lib/api/model/downloader_config.g.dart b/ui/flutter/lib/api/model/downloader_config.g.dart index 662ad4836..b580dfad7 100644 --- a/ui/flutter/lib/api/model/downloader_config.g.dart +++ b/ui/flutter/lib/api/model/downloader_config.g.dart @@ -9,7 +9,7 @@ part of 'downloader_config.dart'; DownloaderConfig _$DownloaderConfigFromJson(Map json) => DownloaderConfig( downloadDir: json['downloadDir'] as String? ?? '', - maxRunning: (json['maxRunning'] as num?)?.toInt() ?? 0, + maxRunning: json['maxRunning'] as int? ?? 0, ) ..protocolConfig = ProtocolConfig.fromJson( json['protocolConfig'] as Map?) @@ -39,7 +39,7 @@ Map _$ProtocolConfigToJson(ProtocolConfig instance) => HttpConfig _$HttpConfigFromJson(Map json) => HttpConfig( userAgent: json['userAgent'] as String? ?? 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36', - connections: (json['connections'] as num?)?.toInt() ?? 16, + connections: json['connections'] as int? ?? 16, useServerCtime: json['useServerCtime'] as bool? ?? false, ); @@ -51,7 +51,7 @@ Map _$HttpConfigToJson(HttpConfig instance) => }; BtConfig _$BtConfigFromJson(Map json) => BtConfig() - ..listenPort = (json['listenPort'] as num).toInt() + ..listenPort = json['listenPort'] as int ..trackers = (json['trackers'] as List).map((e) => e as String).toList(); @@ -60,15 +60,17 @@ Map _$BtConfigToJson(BtConfig instance) => { 'trackers': instance.trackers, }; -ExtraConfig _$ExtraConfigFromJson(Map json) => ExtraConfig() - ..themeMode = json['themeMode'] as String - ..locale = json['locale'] as String - ..bt = ExtraConfigBt.fromJson(json['bt'] as Map); +ExtraConfig _$ExtraConfigFromJson(Map json) => ExtraConfig( + themeMode: json['themeMode'] as String? ?? '', + locale: json['locale'] as String? ?? '', + lastDeleteTaskKeep: json['lastDeleteTaskKeep'] as bool? ?? false, + )..bt = ExtraConfigBt.fromJson(json['bt'] as Map); Map _$ExtraConfigToJson(ExtraConfig instance) => { 'themeMode': instance.themeMode, 'locale': instance.locale, + 'lastDeleteTaskKeep': instance.lastDeleteTaskKeep, 'bt': instance.bt.toJson(), }; diff --git a/ui/flutter/lib/api/model/options.g.dart b/ui/flutter/lib/api/model/options.g.dart index 40a1a8a4e..b496e9fc6 100644 --- a/ui/flutter/lib/api/model/options.g.dart +++ b/ui/flutter/lib/api/model/options.g.dart @@ -10,7 +10,7 @@ Options _$OptionsFromJson(Map json) => Options( name: json['name'] as String, path: json['path'] as String, selectFiles: (json['selectFiles'] as List?) - ?.map((e) => (e as num).toInt()) + ?.map((e) => e as int) .toList() ?? const [], extra: json['extra'], @@ -35,7 +35,7 @@ Map _$OptionsToJson(Options instance) { OptsExtraHttp _$OptsExtraHttpFromJson(Map json) => OptsExtraHttp() - ..connections = (json['connections'] as num).toInt() + ..connections = json['connections'] as int ..autoTorrent = json['autoTorrent'] as bool; Map _$OptsExtraHttpToJson(OptsExtraHttp instance) => diff --git a/ui/flutter/lib/api/model/resource.g.dart b/ui/flutter/lib/api/model/resource.g.dart index 0a5e8fc8a..2feddd86d 100644 --- a/ui/flutter/lib/api/model/resource.g.dart +++ b/ui/flutter/lib/api/model/resource.g.dart @@ -8,7 +8,7 @@ part of 'resource.dart'; Resource _$ResourceFromJson(Map json) => Resource( name: json['name'] as String? ?? "", - size: (json['size'] as num?)?.toInt() ?? 0, + size: json['size'] as int? ?? 0, range: json['range'] as bool? ?? false, files: (json['files'] as List) .map((e) => FileInfo.fromJson(e as Map)) @@ -27,7 +27,7 @@ Map _$ResourceToJson(Resource instance) => { FileInfo _$FileInfoFromJson(Map json) => FileInfo( path: json['path'] as String? ?? "", name: json['name'] as String, - size: (json['size'] as num?)?.toInt() ?? 0, + size: json['size'] as int? ?? 0, req: json['req'] == null ? null : Request.fromJson(json['req'] as Map), diff --git a/ui/flutter/lib/api/model/result.g.dart b/ui/flutter/lib/api/model/result.g.dart index 03d4f734e..452a7c7ca 100644 --- a/ui/flutter/lib/api/model/result.g.dart +++ b/ui/flutter/lib/api/model/result.g.dart @@ -11,7 +11,7 @@ Result _$ResultFromJson( T Function(Object? json) fromJsonT, ) => Result( - code: (json['code'] as num).toInt(), + code: json['code'] as int, msg: json['msg'] as String?, data: _$nullableGenericFromJson(json['data'], fromJsonT), ); diff --git a/ui/flutter/lib/api/model/task.g.dart b/ui/flutter/lib/api/model/task.g.dart index c0a77b956..b5974a168 100644 --- a/ui/flutter/lib/api/model/task.g.dart +++ b/ui/flutter/lib/api/model/task.g.dart @@ -34,9 +34,9 @@ const _$StatusEnumMap = { }; Progress _$ProgressFromJson(Map json) => Progress( - used: (json['used'] as num).toInt(), - speed: (json['speed'] as num).toInt(), - downloaded: (json['downloaded'] as num).toInt(), + used: json['used'] as int, + speed: json['speed'] as int, + downloaded: json['downloaded'] as int, ); Map _$ProgressToJson(Progress instance) => { diff --git a/ui/flutter/lib/app/modules/app/controllers/app_controller.dart b/ui/flutter/lib/app/modules/app/controllers/app_controller.dart index f898b20a2..0135b2467 100644 --- a/ui/flutter/lib/app/modules/app/controllers/app_controller.dart +++ b/ui/flutter/lib/app/modules/app/controllers/app_controller.dart @@ -338,7 +338,7 @@ class AppController extends GetxController with WindowListener, TrayListener { try { downloaderConfig.value = await getConfig(); } catch (e) { - logger.w("load downloader config fail", e); + logger.w("load downloader config fail", e, StackTrace.current); downloaderConfig.value = DownloaderConfig(); } await _initDownloaderConfig(); diff --git a/ui/flutter/lib/app/modules/create/views/create_view.dart b/ui/flutter/lib/app/modules/create/views/create_view.dart index bd3e4bdbc..6821852b0 100644 --- a/ui/flutter/lib/app/modules/create/views/create_view.dart +++ b/ui/flutter/lib/app/modules/create/views/create_view.dart @@ -17,6 +17,7 @@ import '../../../../util/input_formatter.dart'; import '../../../../util/message.dart'; import '../../../../util/util.dart'; import '../../../routes/app_pages.dart'; +import '../../../views/compact_checkbox.dart'; import '../../../views/directory_selector.dart'; import '../../../views/file_list_view.dart'; import '../../app/controllers/app_controller.dart'; @@ -321,23 +322,13 @@ class CreateView extends GetView { Row( mainAxisSize: MainAxisSize.min, children: [ - TextButton( - onPressed: () { - controller.directDownload.value = - !controller.directDownload.value; - }, - child: Row(children: [ - Obx(() => Checkbox( - value: - controller.directDownload.value, - onChanged: (bool? value) { - controller.directDownload.value = - value ?? false; - }, - )), - Text('directDownload'.tr), - ]), - ), + CompactCheckbox( + label: 'directDownload'.tr, + value: controller.directDownload.value, + onChanged: (bool? value) { + controller.directDownload.value = + value ?? false; + }), TextButton( onPressed: () { controller.showAdvanced.value = @@ -415,7 +406,7 @@ class CreateView extends GetView { } } - /* + /* Check if is direct download, there has two ways to direct download 1. Direct download option is checked 2. Muli line urls diff --git a/ui/flutter/lib/app/views/buid_task_list_view.dart b/ui/flutter/lib/app/views/buid_task_list_view.dart index a80b0b3b9..c41987248 100644 --- a/ui/flutter/lib/app/views/buid_task_list_view.dart +++ b/ui/flutter/lib/app/views/buid_task_list_view.dart @@ -12,6 +12,7 @@ import '../../util/file_icon.dart'; import '../../util/icons.dart'; import '../../util/message.dart'; import '../../util/util.dart'; +import '../modules/app/controllers/app_controller.dart'; import '../routes/app_pages.dart'; class BuildTaskListView extends GetView { @@ -73,7 +74,7 @@ class BuildTaskListView extends GetView { } Future showDeleteDialog(String id) { - final keep = true.obs; + final appController = Get.find(); final context = Get.context!; @@ -83,11 +84,14 @@ class BuildTaskListView extends GetView { builder: (_) => AlertDialog( title: Text('deleteTask'.tr), content: Obx(() => CheckboxListTile( - value: keep.value, + value: appController + .downloaderConfig.value.extra.lastDeleteTaskKeep, title: Text('deleteTaskTip'.tr, style: context.textTheme.bodyLarge), onChanged: (v) { - keep.value = v!; + appController.downloaderConfig.update((val) { + val!.extra.lastDeleteTaskKeep = v!; + }); })), actions: [ TextButton( @@ -101,7 +105,10 @@ class BuildTaskListView extends GetView { ), onPressed: () async { try { - await deleteTask(id, !keep.value); + final force = !appController + .downloaderConfig.value.extra.lastDeleteTaskKeep; + await appController.saveConfig(); + await deleteTask(id, force); Get.back(); } catch (e) { showErrorMessage(e); diff --git a/ui/flutter/lib/app/views/compact_checkbox.dart b/ui/flutter/lib/app/views/compact_checkbox.dart new file mode 100644 index 000000000..f2840b5cd --- /dev/null +++ b/ui/flutter/lib/app/views/compact_checkbox.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; + +class CompactCheckbox extends StatefulWidget { + final String label; + final bool value; + final ValueChanged? onChanged; + final double? scale; + final TextStyle? textStyle; + + const CompactCheckbox({ + super.key, + required this.label, + required this.value, + this.onChanged, + this.scale, + this.textStyle, + }); + + @override + State createState() => _CompactCheckboxState(); +} + +class _CompactCheckboxState extends State { + late bool _value; + + @override + void initState() { + super.initState(); + _value = widget.value; + } + + valueChanged(bool? value) { + setState(() { + _value = value!; + }); + widget.onChanged?.call(_value); + } + + @override + Widget build(BuildContext context) { + final checkbox = Checkbox( + value: _value, + onChanged: valueChanged, + ); + + return TextButton( + onPressed: () { + valueChanged(!_value); + }, + child: Row( + children: [ + widget.scale == null + ? checkbox + : Transform.scale( + scale: widget.scale, + child: checkbox, + ), + Text( + widget.label, + style: widget.textStyle, + ), + ], + ), + ); + } +} diff --git a/ui/flutter/lib/core/common/start_config.g.dart b/ui/flutter/lib/core/common/start_config.g.dart index 85e67b856..8732accb0 100644 --- a/ui/flutter/lib/core/common/start_config.g.dart +++ b/ui/flutter/lib/core/common/start_config.g.dart @@ -11,7 +11,7 @@ StartConfig _$StartConfigFromJson(Map json) => StartConfig() ..address = json['address'] as String ..storage = json['storage'] as String ..storageDir = json['storageDir'] as String - ..refreshInterval = (json['refreshInterval'] as num).toInt() + ..refreshInterval = json['refreshInterval'] as int ..apiToken = json['apiToken'] as String; Map _$StartConfigToJson(StartConfig instance) =>