This commit is contained in:
niuhuan 2022-06-30 23:38:42 +08:00
parent 9c51033973
commit 421db2522b
8 changed files with 132 additions and 47 deletions

View File

@ -1,4 +1,6 @@
PODS: PODS:
- app_links (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.2): - DKImagePickerController/Core (4.3.2):
- DKImagePickerController/ImageDataManager - DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource - DKImagePickerController/Resource
@ -46,15 +48,19 @@ PODS:
- SDWebImage/Core (5.12.5) - SDWebImage/Core (5.12.5)
- SwiftyGif (5.4.3) - SwiftyGif (5.4.3)
- TOCropViewController (2.6.1) - TOCropViewController (2.6.1)
- uri_to_file (0.0.1):
- Flutter
- url_launcher_ios (0.0.1): - url_launcher_ios (0.0.1):
- Flutter - Flutter
DEPENDENCIES: DEPENDENCIES:
- app_links (from `.symlinks/plugins/app_links/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- permission_handler (from `.symlinks/plugins/permission_handler/ios`) - permission_handler (from `.symlinks/plugins/permission_handler/ios`)
- uri_to_file (from `.symlinks/plugins/uri_to_file/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS: SPEC REPOS:
@ -66,6 +72,8 @@ SPEC REPOS:
- TOCropViewController - TOCropViewController
EXTERNAL SOURCES: EXTERNAL SOURCES:
app_links:
:path: ".symlinks/plugins/app_links/ios"
file_picker: file_picker:
:path: ".symlinks/plugins/file_picker/ios" :path: ".symlinks/plugins/file_picker/ios"
Flutter: Flutter:
@ -76,10 +84,13 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/image_picker_ios/ios" :path: ".symlinks/plugins/image_picker_ios/ios"
permission_handler: permission_handler:
:path: ".symlinks/plugins/permission_handler/ios" :path: ".symlinks/plugins/permission_handler/ios"
uri_to_file:
:path: ".symlinks/plugins/uri_to_file/ios"
url_launcher_ios: url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios" :path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
app_links: 8941e7bac086136bae70d619141c36f258f4381d
DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d DKImagePickerController: b5eb7f7a388e4643264105d648d01f727110fc3d
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95 file_picker: 817ab1d8cd2da9d2da412a417162deee3500fc95
@ -90,6 +101,7 @@ SPEC CHECKSUMS:
SDWebImage: 0905f1b7760fc8ac4198cae0036600d67478751e SDWebImage: 0905f1b7760fc8ac4198cae0036600d67478751e
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
uri_to_file: c4726881848febf4806f0a5707bd12903e02b0f0
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

View File

@ -2,14 +2,25 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>CFBundleDisplayName</key>
<string>pikapika</string>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>CADisableMinimumFrameDurationOnPhone</key>
<true/> <true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>pikapika</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>PKZ Archive</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>pkz</string>
</array>
</dict>
</array>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -26,12 +37,14 @@
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSPhotoLibraryUsageDescription</key>
<string>Usage images</string>
<key>NSPhotoLibraryAddUsageDescription</key> <key>NSPhotoLibraryAddUsageDescription</key>
<string>Save images</string> <string>Save images</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Usage images</string>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>

View File

@ -27,7 +27,7 @@ String _currentChooserRoot() {
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
return '/storage/emulated/0'; return '/storage/emulated/0';
} else { } else {
throw 'error'; return '';
} }
} }
return _chooserRoot; return _chooserRoot;

View File

@ -7,6 +7,7 @@ import 'package:pikapika/basic/Common.dart';
import 'package:pikapika/basic/Method.dart'; import 'package:pikapika/basic/Method.dart';
import 'package:pikapika/basic/config/ChooserRoot.dart'; import 'package:pikapika/basic/config/ChooserRoot.dart';
import 'PkzArchiveScreen.dart';
import 'components/ContentLoading.dart'; import 'components/ContentLoading.dart';
import 'components/RightClickPop.dart'; import 'components/RightClickPop.dart';
@ -60,13 +61,7 @@ class _DownloadImportScreenState extends State<DownloadImportScreen> {
List<Widget> actions = []; List<Widget> actions = [];
if (Platform.isWindows || actions.add(_fileImportButton());
Platform.isMacOS ||
Platform.isLinux ||
Platform.isAndroid) {
actions.add(_fileImportButton());
}
actions.add(_networkImportButton()); actions.add(_networkImportButton());
return Scaffold( return Scaffold(
@ -101,31 +96,44 @@ class _DownloadImportScreenState extends State<DownloadImportScreen> {
allowMultiple: false, allowMultiple: false,
initialDirectory: chooseRoot, initialDirectory: chooseRoot,
type: FileType.custom, type: FileType.custom,
allowedExtensions: ['zip'], allowedExtensions: ['pkz', 'zip'],
allowCompression: false, allowCompression: false,
); );
String? path = ls != null && ls.count > 0 ? ls.paths[0] : null; String? path = ls != null && ls.count > 0 ? ls.paths[0] : null;
if (path != null) { if (path != null) {
try { if (path.endsWith(".pkz")) {
setState(() { Navigator.of(context).push(
_importing = true; MaterialPageRoute(
}); builder: (BuildContext context) =>
await method.importComicDownload(path); PkzArchiveScreen(pkzPath: path),
setState(() { ),
_importMessage = "导入成功"; );
}); } else if (path.endsWith(".zip")) {
} catch (e) { try {
setState(() { setState(() {
_importMessage = "导入失败 $e"; _importing = true;
}); });
} finally { await method.importComicDownload(path);
setState(() { setState(() {
_importing = false; _importMessage = "导入成功";
}); });
} catch (e) {
setState(() {
_importMessage = "导入失败 $e";
});
} finally {
setState(() {
_importing = false;
});
}
} }
} }
}, },
child: const Text('选择zip文件进行导入'), child: const Text(
'选择zip文件进行导入\n选择pkz文件进行阅读',
style: TextStyle(),
textAlign: TextAlign.center,
),
); );
} }

View File

@ -62,8 +62,8 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
actions: [ actions: [
exportButton(), exportButton(),
importButton(), importButton(),
pauseButton(),
resetFailedButton(), resetFailedButton(),
pauseButton(),
], ],
), ),
body: FutureBuilder( body: FutureBuilder(
@ -147,8 +147,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
} }
Widget exportButton() { Widget exportButton() {
return MaterialButton( return IconButton(
minWidth: 0,
onPressed: () async { onPressed: () async {
await Navigator.push( await Navigator.push(
context, context,
@ -157,7 +156,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
), ),
); );
}, },
child: Column( icon: Column(
children: [ children: [
Expanded(child: Container()), Expanded(child: Container()),
const Icon( const Icon(
@ -175,8 +174,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
} }
Widget importButton() { Widget importButton() {
return MaterialButton( return IconButton(
minWidth: 0,
onPressed: () async { onPressed: () async {
await Navigator.push( await Navigator.push(
context, context,
@ -188,7 +186,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
_f = method.allDownloads(); _f = method.allDownloads();
}); });
}, },
child: Column( icon: Column(
children: [ children: [
Expanded(child: Container()), Expanded(child: Container()),
const Icon( const Icon(
@ -260,8 +258,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
} }
Widget resetFailedButton() { Widget resetFailedButton() {
return MaterialButton( return IconButton(
minWidth: 0,
onPressed: () async { onPressed: () async {
await method.resetFailed(); await method.resetFailed();
setState(() { setState(() {
@ -269,7 +266,7 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
}); });
defaultToast(context, "所有失败的下载已经恢复"); defaultToast(context, "所有失败的下载已经恢复");
}, },
child: Column( icon: Column(
children: [ children: [
Expanded(child: Container()), Expanded(child: Container()),
const Icon( const Icon(

View File

@ -113,7 +113,7 @@ class _InitScreenState extends State<InitScreen> {
File file = await toFile(initUrl!); File file = await toFile(initUrl!);
Navigator.of(context).pushReplacement(MaterialPageRoute( Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => builder: (BuildContext context) =>
PkzArchiveScreen(pkzPath: file.path), PkzArchiveScreen(pkzPath: file.path, holdPkz: true),
)); ));
return; return;
} }

View File

@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
@ -7,14 +9,20 @@ import 'package:pikapika/basic/Entities.dart';
import 'package:pikapika/basic/Method.dart'; import 'package:pikapika/basic/Method.dart';
import 'package:pikapika/screens/components/ContentBuilder.dart'; import 'package:pikapika/screens/components/ContentBuilder.dart';
import 'package:pikapika/screens/components/PkzComicInfoCard.dart'; import 'package:pikapika/screens/components/PkzComicInfoCard.dart';
import 'package:uri_to_file/uri_to_file.dart';
import '../basic/Navigator.dart'; import '../basic/Navigator.dart';
import 'PkzComicInfoScreen.dart'; import 'PkzComicInfoScreen.dart';
class PkzArchiveScreen extends StatefulWidget { class PkzArchiveScreen extends StatefulWidget {
final bool holdPkz;
final String pkzPath; final String pkzPath;
const PkzArchiveScreen({Key? key, required this.pkzPath}) : super(key: key); const PkzArchiveScreen({
Key? key,
required this.pkzPath,
this.holdPkz = false,
}) : super(key: key);
@override @override
State<StatefulWidget> createState() => _PkzArchiveScreenState(); State<StatefulWidget> createState() => _PkzArchiveScreenState();
@ -25,9 +33,27 @@ class _PkzArchiveScreenState extends State<PkzArchiveScreen> with RouteAware {
late String _fileName; late String _fileName;
late Future _future; late Future _future;
late PkzArchive _info; late PkzArchive _info;
StreamSubscription<Uri>? _linkSubscription;
@override @override
void initState() { void initState() {
if (widget.holdPkz) {
final appLinks = AppLinks();
// todo cancel , APP关闭时销毁, APP里
_linkSubscription = appLinks.uriLinkStream.listen((uri) async {
RegExp regExp = RegExp(r"^.*\.pkz$");
final matches = regExp.allMatches(uri.toString());
if (matches.isNotEmpty) {
File file = await toFile(uri.toString());
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
PkzArchiveScreen(pkzPath: file.path),
),
);
}
});
}
_fileName = p.basename(widget.pkzPath); _fileName = p.basename(widget.pkzPath);
_future = _load(); _future = _load();
super.initState(); super.initState();
@ -41,6 +67,7 @@ class _PkzArchiveScreenState extends State<PkzArchiveScreen> with RouteAware {
@override @override
void dispose() { void dispose() {
_linkSubscription?.cancel();
routeObserver.unsubscribe(this); routeObserver.unsubscribe(this);
super.dispose(); super.dispose();
} }
@ -68,6 +95,7 @@ class _PkzArchiveScreenState extends State<PkzArchiveScreen> with RouteAware {
builder: (BuildContext context) => PkzComicInfoScreen( builder: (BuildContext context) => PkzComicInfoScreen(
pkzPath: widget.pkzPath, pkzPath: widget.pkzPath,
pkzComic: _info.comics.first, pkzComic: _info.comics.first,
holdPkz: true,
), ),
)); ));
} }

View File

@ -1,19 +1,29 @@
import 'dart:async';
import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'package:pikapika/basic/Entities.dart'; import 'package:pikapika/basic/Entities.dart';
import 'package:pikapika/basic/Method.dart'; import 'package:pikapika/basic/Method.dart';
import 'package:pikapika/screens/PkzReaderScreen.dart'; import 'package:pikapika/screens/PkzReaderScreen.dart';
import 'package:uri_to_file/uri_to_file.dart';
import '../basic/Navigator.dart'; import '../basic/Navigator.dart';
import 'PkzArchiveScreen.dart';
import 'components/PkzComicInfoCard.dart'; import 'components/PkzComicInfoCard.dart';
class PkzComicInfoScreen extends StatefulWidget { class PkzComicInfoScreen extends StatefulWidget {
final bool holdPkz;
final String pkzPath; final String pkzPath;
final PkzComic pkzComic; final PkzComic pkzComic;
const PkzComicInfoScreen( const PkzComicInfoScreen({
{Key? key, required this.pkzPath, required this.pkzComic}) Key? key,
: super(key: key); required this.pkzPath,
required this.pkzComic,
this.holdPkz = false,
}) : super(key: key);
@override @override
State<StatefulWidget> createState() => _PkzComicInfoScreenState(); State<StatefulWidget> createState() => _PkzComicInfoScreenState();
@ -22,9 +32,25 @@ class PkzComicInfoScreen extends StatefulWidget {
class _PkzComicInfoScreenState extends State<PkzComicInfoScreen> class _PkzComicInfoScreenState extends State<PkzComicInfoScreen>
with RouteAware { with RouteAware {
PkzComicViewLog? _log; PkzComicViewLog? _log;
StreamSubscription<Uri>? _linkSubscription;
@override @override
void initState() { void initState() {
if (widget.holdPkz) {
final appLinks = AppLinks();
// todo cancel , APP关闭时销毁, APP里
_linkSubscription = appLinks.uriLinkStream.listen((uri) async {
RegExp regExp = RegExp(r"^.*\.pkz$");
final matches = regExp.allMatches(uri.toString());
if (matches.isNotEmpty) {
File file = await toFile(uri.toString());
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) =>
PkzArchiveScreen(pkzPath: file.path),
));
}
});
}
_load(); _load();
super.initState(); super.initState();
} }
@ -37,6 +63,7 @@ class _PkzComicInfoScreenState extends State<PkzComicInfoScreen>
@override @override
void dispose() { void dispose() {
_linkSubscription?.cancel();
routeObserver.unsubscribe(this); routeObserver.unsubscribe(this);
super.dispose(); super.dispose();
} }