2021-09-29 23:57:09 +00:00
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
2021-10-14 10:12:36 +00:00
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
2021-11-11 03:00:38 +00:00
|
|
|
import 'package:pikapika/basic/Channels.dart';
|
|
|
|
import 'package:pikapika/basic/Common.dart';
|
|
|
|
import 'package:pikapika/basic/Cross.dart';
|
|
|
|
import 'package:pikapika/basic/Entities.dart';
|
|
|
|
import 'package:pikapika/basic/Method.dart';
|
2022-02-25 10:46:11 +00:00
|
|
|
import 'package:pikapika/basic/config/ExportRename.dart';
|
2021-11-11 03:00:38 +00:00
|
|
|
import 'package:pikapika/screens/DownloadExportToSocketScreen.dart';
|
2021-09-29 23:57:09 +00:00
|
|
|
|
2023-01-31 10:50:51 +00:00
|
|
|
import '../basic/config/IconLoading.dart';
|
2021-09-29 23:57:09 +00:00
|
|
|
import 'components/ContentError.dart';
|
|
|
|
import 'components/ContentLoading.dart';
|
|
|
|
import 'components/DownloadInfoCard.dart';
|
2022-03-25 14:57:30 +00:00
|
|
|
import 'components/RightClickPop.dart';
|
2021-09-29 23:57:09 +00:00
|
|
|
|
|
|
|
// 导出
|
|
|
|
class DownloadExportToFileScreen extends StatefulWidget {
|
|
|
|
final String comicId;
|
|
|
|
final String comicTitle;
|
|
|
|
|
2022-03-17 03:31:25 +00:00
|
|
|
const DownloadExportToFileScreen({
|
2021-09-29 23:57:09 +00:00
|
|
|
required this.comicId,
|
|
|
|
required this.comicTitle,
|
2022-03-17 03:31:25 +00:00
|
|
|
Key? key,
|
|
|
|
}) : super(key: key);
|
2021-09-29 23:57:09 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
State<StatefulWidget> createState() => _DownloadExportToFileScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _DownloadExportToFileScreenState
|
|
|
|
extends State<DownloadExportToFileScreen> {
|
|
|
|
late DownloadComic _task;
|
|
|
|
late Future _future = _load();
|
|
|
|
late bool exporting = false;
|
|
|
|
late String exportMessage = "导出中";
|
|
|
|
late String exportResult = "";
|
|
|
|
|
|
|
|
Future _load() async {
|
|
|
|
_task = (await method.loadDownloadComic(widget.comicId))!;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
registerEvent(_onMessageChange, "EXPORT");
|
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
unregisterEvent(_onMessageChange);
|
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onMessageChange(event) {
|
|
|
|
setState(() {
|
|
|
|
exportMessage = event;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2022-06-29 19:02:01 +00:00
|
|
|
Widget build(BuildContext context) {
|
2022-03-25 14:57:30 +00:00
|
|
|
return rightClickPop(
|
|
|
|
child: buildScreen(context),
|
|
|
|
context: context,
|
|
|
|
canPop: !exporting,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget buildScreen(BuildContext context) {
|
2021-09-29 23:57:09 +00:00
|
|
|
if (exporting) {
|
|
|
|
return Scaffold(
|
|
|
|
body: ContentLoading(label: exportMessage),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
|
|
|
title: Text("导出 - " + widget.comicTitle),
|
|
|
|
),
|
|
|
|
body: FutureBuilder(
|
|
|
|
future: _future,
|
|
|
|
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
|
|
|
|
if (snapshot.hasError) {
|
|
|
|
return ContentError(
|
|
|
|
error: snapshot.error,
|
|
|
|
stackTrace: snapshot.stackTrace,
|
|
|
|
onRefresh: () async {
|
|
|
|
setState(() {
|
|
|
|
_future = _load();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (snapshot.connectionState != ConnectionState.done) {
|
2022-03-19 04:12:27 +00:00
|
|
|
return const ContentLoading(label: '加载中');
|
2021-09-29 23:57:09 +00:00
|
|
|
}
|
|
|
|
return ListView(
|
|
|
|
children: [
|
|
|
|
DownloadInfoCard(task: _task),
|
|
|
|
Container(
|
2022-03-19 04:12:27 +00:00
|
|
|
padding: const EdgeInsets.all(8),
|
2021-09-29 23:57:09 +00:00
|
|
|
child: exportResult != "" ? Text(exportResult) : Container(),
|
|
|
|
),
|
|
|
|
Container(
|
2022-03-19 04:12:27 +00:00
|
|
|
padding: const EdgeInsets.all(8),
|
|
|
|
child: const Text('TIPS : 选择一个目录'),
|
2021-09-29 23:57:09 +00:00
|
|
|
),
|
|
|
|
..._buildExportToFileButtons(),
|
|
|
|
MaterialButton(
|
|
|
|
onPressed: () async {
|
|
|
|
Navigator.of(context).push(
|
2023-01-31 10:50:51 +00:00
|
|
|
mixRoute(
|
2021-09-29 23:57:09 +00:00
|
|
|
builder: (context) => DownloadExportToSocketScreen(
|
|
|
|
task: _task,
|
|
|
|
comicId: widget.comicId,
|
|
|
|
comicTitle: widget.comicTitle,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
child: _buildButtonInner('传输到其他设备'),
|
|
|
|
),
|
2022-07-01 05:39:08 +00:00
|
|
|
Container(height: 10),
|
2021-09-29 23:57:09 +00:00
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
List<Widget> _buildExportToFileButtons() {
|
2021-10-14 10:12:36 +00:00
|
|
|
List<Widget> widgets = [];
|
2021-09-29 23:57:09 +00:00
|
|
|
if (Platform.isWindows ||
|
|
|
|
Platform.isMacOS ||
|
|
|
|
Platform.isLinux ||
|
|
|
|
Platform.isAndroid) {
|
2021-10-14 10:12:36 +00:00
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
2021-11-18 01:53:30 +00:00
|
|
|
late String? path;
|
|
|
|
try {
|
2022-10-14 17:54:50 +00:00
|
|
|
path = Platform.isIOS
|
|
|
|
? await method.iosGetDocumentDir()
|
|
|
|
: await chooseFolder(context);
|
2021-11-18 01:53:30 +00:00
|
|
|
} catch (e) {
|
|
|
|
defaultToast(context, "$e");
|
|
|
|
return;
|
|
|
|
}
|
2022-02-25 10:46:11 +00:00
|
|
|
var name = "";
|
|
|
|
if (currentExportRename()) {
|
|
|
|
var rename = await inputString(
|
|
|
|
context,
|
|
|
|
"请输入保存后的名称",
|
|
|
|
defaultValue: _task.title,
|
|
|
|
);
|
|
|
|
if (rename != null && rename.isNotEmpty) {
|
|
|
|
name = rename;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-10-14 10:12:36 +00:00
|
|
|
print("path $path");
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
await method.exportComicDownloadToJPG(
|
|
|
|
widget.comicId,
|
|
|
|
path,
|
2022-02-25 10:46:11 +00:00
|
|
|
name,
|
2021-10-14 10:12:36 +00:00
|
|
|
);
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: _buildButtonInner('导出到HTML+JPG\n(可直接在相册中打开观看)'),
|
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
2022-06-29 19:02:01 +00:00
|
|
|
/////////////////////
|
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
|
|
|
late String? path;
|
|
|
|
try {
|
2022-10-14 17:54:50 +00:00
|
|
|
path = Platform.isIOS
|
|
|
|
? await method.iosGetDocumentDir()
|
|
|
|
: await chooseFolder(context);
|
2022-06-29 19:02:01 +00:00
|
|
|
} catch (e) {
|
|
|
|
defaultToast(context, "$e");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var name = "";
|
|
|
|
if (currentExportRename()) {
|
|
|
|
var rename = await inputString(
|
|
|
|
context,
|
|
|
|
"请输入保存后的名称",
|
|
|
|
defaultValue: _task.title,
|
|
|
|
);
|
|
|
|
if (rename != null && rename.isNotEmpty) {
|
|
|
|
name = rename;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
print("path $path");
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
await method.exportComicDownloadToPkz(
|
|
|
|
[widget.comicId],
|
|
|
|
path,
|
|
|
|
name,
|
|
|
|
);
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child:
|
2022-07-01 05:39:08 +00:00
|
|
|
_buildButtonInner('导出到xxx.pkz\n(可直接打开观看的格式,不支持导入)\n(可以躲避网盘或者聊天软件的扫描)'),
|
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
|
|
|
/////////////////////
|
|
|
|
/////////////////////
|
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
|
|
|
late String? path;
|
|
|
|
try {
|
2022-10-14 17:54:50 +00:00
|
|
|
path = Platform.isIOS
|
|
|
|
? await method.iosGetDocumentDir()
|
|
|
|
: await chooseFolder(context);
|
2022-07-01 05:39:08 +00:00
|
|
|
} catch (e) {
|
|
|
|
defaultToast(context, "$e");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var name = "";
|
|
|
|
if (currentExportRename()) {
|
|
|
|
var rename = await inputString(
|
|
|
|
context,
|
|
|
|
"请输入保存后的名称",
|
|
|
|
defaultValue: _task.title,
|
|
|
|
);
|
|
|
|
if (rename != null && rename.isNotEmpty) {
|
|
|
|
name = rename;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
print("path $path");
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
await method.exportComicDownloadToPki(
|
|
|
|
widget.comicId,
|
|
|
|
path,
|
|
|
|
name,
|
|
|
|
);
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child:
|
|
|
|
_buildButtonInner('导出到xxx.pki\n(只支持导入, 不支持直接阅读)\n(可以躲避网盘或者聊天软件的扫描)\n(后期版本可能支持直接阅读)'),
|
2022-06-29 19:02:01 +00:00
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
|
|
|
/////////////////////
|
2021-10-14 10:12:36 +00:00
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
2021-11-18 01:53:30 +00:00
|
|
|
late String? path;
|
|
|
|
try {
|
2022-10-14 17:54:50 +00:00
|
|
|
path = Platform.isIOS
|
|
|
|
? await method.iosGetDocumentDir()
|
|
|
|
: await chooseFolder(context);
|
2021-11-18 01:53:30 +00:00
|
|
|
} catch (e) {
|
|
|
|
defaultToast(context, "$e");
|
|
|
|
return;
|
|
|
|
}
|
2022-02-25 10:46:11 +00:00
|
|
|
var name = "";
|
|
|
|
if (currentExportRename()) {
|
|
|
|
var rename = await inputString(
|
|
|
|
context,
|
|
|
|
"请输入保存后的名称",
|
|
|
|
defaultValue: _task.title,
|
|
|
|
);
|
|
|
|
if (rename != null && rename.isNotEmpty) {
|
|
|
|
name = rename;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-10-14 10:12:36 +00:00
|
|
|
print("path $path");
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
await method.exportComicDownload(
|
|
|
|
widget.comicId,
|
|
|
|
path,
|
2022-02-25 10:46:11 +00:00
|
|
|
name,
|
2021-10-14 10:12:36 +00:00
|
|
|
);
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
2021-09-29 23:57:09 +00:00
|
|
|
}
|
2021-10-14 10:12:36 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
child: _buildButtonInner('导出到HTML.zip\n(可从其他设备导入 / 解压后可阅读)'),
|
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
2023-02-03 02:09:39 +00:00
|
|
|
//////////////////////
|
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
|
|
|
late String? path;
|
|
|
|
try {
|
|
|
|
path = Platform.isIOS
|
|
|
|
? await method.iosGetDocumentDir()
|
|
|
|
: await chooseFolder(context);
|
|
|
|
} catch (e) {
|
|
|
|
defaultToast(context, "$e");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var name = "";
|
|
|
|
if (currentExportRename()) {
|
|
|
|
var rename = await inputString(
|
|
|
|
context,
|
|
|
|
"请输入保存后的名称",
|
|
|
|
defaultValue: _task.title,
|
|
|
|
);
|
|
|
|
if (rename != null && rename.isNotEmpty) {
|
|
|
|
name = rename;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
print("path $path");
|
|
|
|
if (path != null) {
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
await method.exportComicJpegsEvenNotFinish(
|
|
|
|
widget.comicId,
|
|
|
|
path,
|
|
|
|
name,
|
|
|
|
);
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: _buildButtonInner('导出到HTML+JPG\n(即使没有下载成功)'),
|
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
2021-10-14 10:12:36 +00:00
|
|
|
}
|
|
|
|
if (Platform.isIOS || Platform.isAndroid) {
|
|
|
|
widgets.add(MaterialButton(
|
|
|
|
onPressed: () async {
|
|
|
|
if (!(await confirmDialog(context, "导出确认", "将本漫画所有图片到相册?"))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!(await Permission.storage.request()).isGranted) {
|
2022-03-17 03:31:25 +00:00
|
|
|
return;
|
2021-10-14 10:12:36 +00:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
setState(() {
|
|
|
|
exporting = true;
|
|
|
|
});
|
|
|
|
// 导出所有图片数据
|
|
|
|
var count = 0;
|
|
|
|
List<DownloadEp> eps = await method.downloadEpList(widget.comicId);
|
|
|
|
for (var i = 0; i < eps.length; i++) {
|
|
|
|
var pics = await method.downloadPicturesByEpId(eps[i].id);
|
|
|
|
for (var j = 0; j < pics.length; j++) {
|
2021-09-29 23:57:09 +00:00
|
|
|
setState(() {
|
2021-10-14 10:12:36 +00:00
|
|
|
exportMessage = "导出图片 ${count++} 张";
|
2021-09-29 23:57:09 +00:00
|
|
|
});
|
2021-10-14 10:12:36 +00:00
|
|
|
await saveImageQuiet(
|
|
|
|
await method.downloadImagePath(pics[j].localPath),
|
|
|
|
context,
|
2021-09-29 23:57:09 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-10-14 10:12:36 +00:00
|
|
|
setState(() {
|
|
|
|
exportResult = "导出成功";
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
setState(() {
|
|
|
|
exportResult = "导出失败 $e";
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
exporting = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2022-05-18 03:57:38 +00:00
|
|
|
child: _buildButtonInner('将所有图片导出到手机相册'),
|
2021-10-14 10:12:36 +00:00
|
|
|
));
|
|
|
|
widgets.add(Container(height: 10));
|
2021-09-29 23:57:09 +00:00
|
|
|
}
|
2021-10-14 10:12:36 +00:00
|
|
|
return widgets;
|
2021-09-29 23:57:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildButtonInner(String text) {
|
|
|
|
return LayoutBuilder(
|
|
|
|
builder: (BuildContext context, BoxConstraints constraints) {
|
|
|
|
return Container(
|
|
|
|
width: constraints.maxWidth,
|
2022-03-19 04:12:27 +00:00
|
|
|
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
2021-09-29 23:57:09 +00:00
|
|
|
color: (Theme.of(context).textTheme.bodyText1?.color ?? Colors.black)
|
|
|
|
.withOpacity(.05),
|
|
|
|
child: Text(
|
|
|
|
text,
|
|
|
|
textAlign: TextAlign.center,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|