v1.0.1
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import 'package:flutter_dmzj/app/controller/base_controller.dart';
|
||||
import 'package:flutter_dmzj/models/novel/novel_detail_model.dart';
|
||||
|
||||
import 'package:flutter_dmzj/requests/novel_request.dart';
|
||||
import 'package:flutter_dmzj/routes/app_navigator.dart';
|
||||
import 'package:flutter_dmzj/services/novel_download_service.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class NovelSelectChapterController extends BaseController {
|
||||
final int novelId;
|
||||
NovelSelectChapterController(this.novelId);
|
||||
final NovelRequest request = NovelRequest();
|
||||
|
||||
RxList<NovelDetailVolume> volumes = RxList<NovelDetailVolume>();
|
||||
|
||||
String novelTitle = "";
|
||||
String novelCover = "";
|
||||
|
||||
RxMap<int, RxSet<int>> selectIds = RxMap<int, RxSet<int>>();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
loadDetail();
|
||||
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
/// 加载信息
|
||||
void loadDetail() async {
|
||||
try {
|
||||
pageLoadding.value = true;
|
||||
pageError.value = false;
|
||||
var result = await request.novelDetail(novelId: novelId);
|
||||
novelTitle = result.data.name;
|
||||
novelCover = result.data.cover;
|
||||
var chpaterResult = await request.novelChapter(novelId: novelId);
|
||||
var ls = chpaterResult.map((e) => NovelDetailVolume.fromJson(e)).toList();
|
||||
selectIds.value = {};
|
||||
for (var item in ls) {
|
||||
selectIds.addAll({
|
||||
item.volumeId: RxSet<int>(),
|
||||
});
|
||||
}
|
||||
volumes.value = ls;
|
||||
} catch (e) {
|
||||
pageError.value = true;
|
||||
errorMsg.value = e.toString();
|
||||
} finally {
|
||||
pageLoadding.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
void selectItem(NovelDetailChapter item) {
|
||||
var chapterIds = selectIds[item.volumeId]!;
|
||||
if (chapterIds.contains(item.chapterId)) {
|
||||
chapterIds.remove(item.chapterId);
|
||||
} else {
|
||||
chapterIds.add(item.chapterId);
|
||||
}
|
||||
}
|
||||
|
||||
void selectAll() {
|
||||
for (var volume in volumes) {
|
||||
for (var chapter in volume.chapters) {
|
||||
var chapterIds = selectIds[volume.volumeId]!;
|
||||
var id = "${novelId}_${volume.volumeId}_${chapter.chapterId}";
|
||||
if (!NovelDownloadService.instance.downloadIds.contains(id)) {
|
||||
chapterIds.add(chapter.chapterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanAll() {
|
||||
for (var volume in selectIds.values) {
|
||||
volume.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void toDownloadManage() {
|
||||
AppNavigator.toNovelDownloadManage(1);
|
||||
}
|
||||
|
||||
void startDownload() {
|
||||
var chapterIds = <int>[];
|
||||
for (var item in selectIds.values) {
|
||||
chapterIds.addAll(item);
|
||||
}
|
||||
if (chapterIds.isEmpty) {
|
||||
SmartDialog.showToast("请选择需要下载的章节");
|
||||
return;
|
||||
}
|
||||
for (var id in chapterIds) {
|
||||
//搜索章节
|
||||
NovelDetailVolume? volume;
|
||||
NovelDetailChapter? chapter;
|
||||
for (var item in volumes) {
|
||||
var chapterItem =
|
||||
item.chapters.firstWhereOrNull((y) => y.chapterId == id);
|
||||
if (chapterItem != null) {
|
||||
volume = item;
|
||||
chapter = chapterItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (volume == null || chapter == null) {
|
||||
continue;
|
||||
}
|
||||
NovelDownloadService.instance.addTask(
|
||||
novelId: novelId,
|
||||
chapterId: chapter.chapterId,
|
||||
chapterSort: chapter.chapterOrder,
|
||||
volumeName: volume.volumeName,
|
||||
novelTitle: novelTitle,
|
||||
novelCover: novelCover,
|
||||
chapterName: chapter.chapterName,
|
||||
isVip: false,
|
||||
volumeId: volume.volumeId,
|
||||
volumeOrder: volume.volumeOrder,
|
||||
);
|
||||
}
|
||||
cleanAll();
|
||||
SmartDialog.showToast("已添加到下载列表,下载过程中请保持APP在前台运行");
|
||||
}
|
||||
}
|
||||
175
lib/modules/novel/select_chapter/novel_select_chapter_page.dart
Normal file
175
lib/modules/novel/select_chapter/novel_select_chapter_page.dart
Normal file
@@ -0,0 +1,175 @@
|
||||
import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dmzj/models/novel/novel_detail_model.dart';
|
||||
|
||||
import 'package:flutter_dmzj/modules/novel/select_chapter/novel_select_chapter_controller.dart';
|
||||
import 'package:flutter_dmzj/services/novel_download_service.dart';
|
||||
import 'package:flutter_dmzj/widgets/status/app_error_widget.dart';
|
||||
import 'package:flutter_dmzj/widgets/status/app_loadding_widget.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:remixicon/remixicon.dart';
|
||||
|
||||
class NovelSelectChapterPage extends StatelessWidget {
|
||||
final int novelId;
|
||||
final NovelSelectChapterController controller;
|
||||
NovelSelectChapterPage(this.novelId, {super.key})
|
||||
: controller = Get.put(
|
||||
NovelSelectChapterController(novelId),
|
||||
tag: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("选择下载章节"),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: controller.toDownloadManage,
|
||||
child: const Text("下载管理"),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Stack(
|
||||
children: [
|
||||
EasyRefresh(
|
||||
header: const MaterialHeader(),
|
||||
onRefresh: controller.loadDetail,
|
||||
child: _buildVolumes(),
|
||||
),
|
||||
Obx(
|
||||
() => Offstage(
|
||||
offstage: !controller.pageLoadding.value,
|
||||
child: const AppLoaddingWidget(),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => Offstage(
|
||||
offstage: !controller.pageError.value,
|
||||
child: AppErrorWidget(
|
||||
errorMsg: controller.errorMsg.value,
|
||||
onRefresh: () => controller.loadDetail(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: const TextStyle(fontSize: 14),
|
||||
),
|
||||
onPressed: controller.selectAll,
|
||||
icon: const Icon(
|
||||
Remix.checkbox_line,
|
||||
size: 20,
|
||||
),
|
||||
label: const Text("全选"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: const TextStyle(fontSize: 14),
|
||||
),
|
||||
onPressed: controller.cleanAll,
|
||||
icon: const Icon(
|
||||
Remix.checkbox_blank_line,
|
||||
size: 20,
|
||||
),
|
||||
label: const Text("取消选中"),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: const TextStyle(fontSize: 14),
|
||||
),
|
||||
onPressed: controller.startDownload,
|
||||
icon: const Icon(
|
||||
Remix.download_line,
|
||||
size: 20,
|
||||
),
|
||||
label: const Text("下载选中"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVolumes() {
|
||||
return Obx(
|
||||
() => ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: controller.volumes.length,
|
||||
itemBuilder: (_, i) {
|
||||
var item = controller.volumes[i];
|
||||
return _buildChapters(item);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildChapters(NovelDetailVolume item) {
|
||||
return Obx(
|
||||
() {
|
||||
var volume = controller.selectIds[item.volumeId]!;
|
||||
return ExpansionTile(
|
||||
title: Text("${item.volumeName}(共${item.chapters.length}话)"),
|
||||
leading: SizedBox(
|
||||
width: 40,
|
||||
child: Checkbox(
|
||||
value: volume.length == item.chapters.length,
|
||||
onChanged: (e) {
|
||||
if (e!) {
|
||||
volume.addAll(
|
||||
item.chapters
|
||||
.where((x) => !NovelDownloadService.instance.downloadIds
|
||||
.contains(
|
||||
"${novelId}_${x.volumeId}_${x.chapterId}"))
|
||||
.map((e) => e.chapterId),
|
||||
);
|
||||
} else {
|
||||
volume.clear();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
children: item.chapters
|
||||
.map(
|
||||
(chapter) => CheckboxListTile(
|
||||
value: volume.contains(chapter.chapterId),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
title: Text(
|
||||
chapter.chapterName,
|
||||
style: Get.textTheme.titleSmall,
|
||||
),
|
||||
enabled: !NovelDownloadService.instance.downloadIds.contains(
|
||||
"${novelId}_${chapter.volumeId}_${chapter.chapterId}"),
|
||||
subtitle: NovelDownloadService.instance.downloadIds.contains(
|
||||
"${novelId}_${chapter.volumeId}_${chapter.chapterId}")
|
||||
? const Text("已下载")
|
||||
: null,
|
||||
onChanged: (e) {
|
||||
if (e!) {
|
||||
volume.add(chapter.chapterId);
|
||||
} else {
|
||||
volume.remove(chapter.chapterId);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user