opt download (#1755)

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
dom
2025-11-27 21:00:13 +08:00
committed by GitHub
parent ded78e534f
commit 9ccaa3072b
25 changed files with 1161 additions and 410 deletions

View File

@@ -0,0 +1,79 @@
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models_new/download/bili_download_entry_info.dart';
import 'package:PiliPlus/pages/common/multi_select/base.dart'
show BaseMultiSelectMixin;
import 'package:PiliPlus/pages/common/search/common_search_controller.dart';
import 'package:PiliPlus/services/download/download_service.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class DownloadSearchController
extends
CommonSearchController<
List<BiliDownloadEntryInfo>,
BiliDownloadEntryInfo
>
with BaseMultiSelectMixin<BiliDownloadEntryInfo> {
final _downloadService = Get.find<DownloadService>();
@override
List<BiliDownloadEntryInfo> get list => loadingState.value.data!;
@override
Rx<LoadingState<List<BiliDownloadEntryInfo>?>> get state => loadingState;
@override
Future<LoadingState<List<BiliDownloadEntryInfo>>> customGetData() async {
final text = editController.text.toLowerCase();
return Success(
_downloadService.downloadList
.where(
(e) =>
e.title.toLowerCase().contains(text) ||
e.showTitle.toLowerCase().contains(text),
)
.toList(),
);
}
void onRemoveSingle(int index, BiliDownloadEntryInfo entry) {
loadingState
..value.data!.removeAt(index)
..refresh();
_downloadService.deleteDownload(
entry: entry,
removeList: true,
);
GStorage.watchProgress.delete(entry.cid.toString());
}
@override
void onRemove() {
showConfirmDialog(
context: Get.context!,
title: '确定删除选中视频?',
onConfirm: () async {
SmartDialog.showLoading();
final allChecked = this.allChecked.toList();
for (var entry in allChecked) {
await GStorage.watchProgress.delete(entry.cid.toString());
await _downloadService.deleteDownload(
entry: entry,
removeList: true,
refresh: false,
);
}
loadingState
..value.data!.removeWhere(allChecked.contains)
..refresh();
_downloadService.flagNotifier.refresh();
if (enableMultiSelect.value) {
rxCount.value = 0;
enableMultiSelect.value = false;
}
SmartDialog.dismiss();
},
);
}
}

View File

@@ -0,0 +1,75 @@
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/models_new/download/bili_download_entry_info.dart';
import 'package:PiliPlus/pages/common/search/common_search_page.dart';
import 'package:PiliPlus/pages/download/detail/widgets/item.dart';
import 'package:PiliPlus/pages/download/search/controller.dart';
import 'package:PiliPlus/services/download/download_service.dart';
import 'package:PiliPlus/utils/grid.dart';
import 'package:flutter/material.dart'
hide SliverGridDelegateWithMaxCrossAxisExtent;
import 'package:get/get.dart';
class DownloadSearchPage extends StatefulWidget {
const DownloadSearchPage({
super.key,
required this.progress,
});
final ValueNotifier progress;
@override
State<DownloadSearchPage> createState() => _DownloadSearchPageState();
}
class _DownloadSearchPageState
extends
CommonSearchPageState<
DownloadSearchPage,
List<BiliDownloadEntryInfo>,
BiliDownloadEntryInfo
> {
@override
DownloadSearchController controller = Get.put(DownloadSearchController());
final _downloadService = Get.find<DownloadService>();
@override
List<Widget>? get extraActions => [
IconButton(
tooltip: '多选',
onPressed: () {
if (controller.enableMultiSelect.value) {
controller.handleSelect();
} else {
controller.enableMultiSelect.value = true;
}
},
icon: const Icon(Icons.edit_note),
),
];
@override
Widget buildList(List<BiliDownloadEntryInfo> list) {
if (list.isNotEmpty) {
return SliverGrid.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
mainAxisSpacing: 2,
mainAxisExtent: 100,
maxCrossAxisExtent: Grid.smallCardWidth * 2,
),
itemBuilder: (context, index) {
final entry = list[index];
return DetailItem(
entry: entry,
progress: widget.progress,
downloadService: _downloadService,
showTitle: true,
onDelete: () => controller.onRemoveSingle(index, entry),
controller: controller,
);
},
itemCount: list.length,
);
}
return const HttpError();
}
}