Application lock (iOS)
This commit is contained in:
parent
7a8e70e693
commit
5f3b73d12c
|
@ -37,7 +37,7 @@ PODS:
|
|||
- image_cropper (0.0.4):
|
||||
- Flutter
|
||||
- TOCropViewController (~> 2.6.1)
|
||||
- image_picker (0.0.1):
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- "permission_handler (5.1.0+2)":
|
||||
- Flutter
|
||||
|
@ -53,7 +53,7 @@ DEPENDENCIES:
|
|||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
|
||||
- image_picker (from `.symlinks/plugins/image_picker/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
|
||||
|
@ -72,8 +72,8 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter
|
||||
image_cropper:
|
||||
:path: ".symlinks/plugins/image_cropper/ios"
|
||||
image_picker:
|
||||
:path: ".symlinks/plugins/image_picker/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
permission_handler:
|
||||
:path: ".symlinks/plugins/permission_handler/ios"
|
||||
url_launcher_ios:
|
||||
|
@ -85,7 +85,7 @@ SPEC CHECKSUMS:
|
|||
file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1
|
||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||
image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98
|
||||
image_picker: 541dcbb3b9cf32d87eacbd957845d8651d6c62c3
|
||||
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
|
||||
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
|
||||
SDWebImage: 0905f1b7760fc8ac4198cae0036600d67478751e
|
||||
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
|
||||
|
@ -94,4 +94,4 @@ SPEC CHECKSUMS:
|
|||
|
||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||
|
||||
COCOAPODS: 1.11.2
|
||||
COCOAPODS: 1.11.3
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
import Mobile
|
||||
import LocalAuthentication
|
||||
|
||||
@UIApplicationMain
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
|
@ -34,6 +35,18 @@ import Mobile
|
|||
result(FlutterError(code: "", message: "params error", details: ""))
|
||||
}
|
||||
}
|
||||
else if call.method == "verifyAuthentication"{
|
||||
let context = LAContext()
|
||||
let can = context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)
|
||||
guard can == true else {
|
||||
result(false)
|
||||
return
|
||||
}
|
||||
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "身份验证") { (success, error) in
|
||||
result(success)
|
||||
}
|
||||
|
||||
}
|
||||
else if call.method == "iosSaveFileToImage"{
|
||||
if let args = call.arguments as? Dictionary<String, Any>,
|
||||
let path = args["path"] as? String{
|
||||
|
|
|
@ -717,4 +717,8 @@ class Method {
|
|||
List list = json.decode(rsp);
|
||||
return list.map((e) => Collection.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
Future<bool> verifyAuthentication() async {
|
||||
return await _channel.invokeMethod("verifyAuthentication");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../Common.dart';
|
||||
import '../Method.dart';
|
||||
|
||||
const _propertyName = "authentication";
|
||||
late bool _authentication;
|
||||
|
||||
Future<void> initAuthentication() async {
|
||||
_authentication =
|
||||
(await method.loadProperty(_propertyName, "false")) == "true";
|
||||
}
|
||||
|
||||
bool currentAuthentication() {
|
||||
return _authentication;
|
||||
}
|
||||
|
||||
Future<void> _chooseAuthentication(BuildContext context) async {
|
||||
if (await method.verifyAuthentication()) {
|
||||
String? result =
|
||||
await chooseListDialog<String>(context, "进入APP时验证身份", ["是", "否"]);
|
||||
if (result != null) {
|
||||
var target = result == "是";
|
||||
await method.saveProperty(_propertyName, "$target");
|
||||
_authentication = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget authenticationSetting() {
|
||||
if (Platform.isIOS != true) {
|
||||
return Container();
|
||||
}
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: const Text("进入APP时验证身份"),
|
||||
subtitle: Text(_authentication ? "是" : "否"),
|
||||
onTap: () async {
|
||||
await _chooseAuthentication(context);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
|
@ -63,6 +63,9 @@ Future<dynamic> _inputChooserRoot(BuildContext context) async {
|
|||
}
|
||||
|
||||
Widget chooserRootSetting() {
|
||||
if (Platform.isIOS) {
|
||||
return Container();
|
||||
}
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:pikapika/basic/Method.dart';
|
|||
import 'package:pikapika/basic/config/Themes.dart';
|
||||
import 'package:pikapika/basic/enum/ErrorTypes.dart';
|
||||
import 'package:pikapika/screens/RegisterScreen.dart';
|
||||
import 'package:pikapika/screens/SettingsScreen.dart';
|
||||
import 'package:pikapika/screens/components/NetworkSetting.dart';
|
||||
|
||||
import 'AppScreen.dart';
|
||||
|
@ -59,6 +60,19 @@ class _AccountScreenState extends State<AccountScreen> {
|
|||
appBar: AppBar(
|
||||
title: const Text('配置选项'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SettingsScreen(
|
||||
hiddenAccountInfo: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Text('设置'),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (androidNightModeDisplay) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:pikapika/basic/config/Address.dart';
|
||||
import 'package:pikapika/basic/config/AndroidDisplayMode.dart';
|
||||
import 'package:pikapika/basic/config/AndroidSecureFlag.dart';
|
||||
import 'package:pikapika/basic/config/Authentication.dart';
|
||||
import 'package:pikapika/basic/config/AutoClean.dart';
|
||||
import 'package:pikapika/basic/config/AutoFullScreen.dart';
|
||||
import 'package:pikapika/basic/config/ChooserRoot.dart';
|
||||
|
@ -43,6 +44,8 @@ class InitScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _InitScreenState extends State<InitScreen> {
|
||||
var _authenticating = false;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
_init();
|
||||
|
@ -83,7 +86,51 @@ class _InitScreenState extends State<InitScreen> {
|
|||
await initExportRename();
|
||||
await initVersion();
|
||||
await initUsingRightClickPop();
|
||||
await initAuthentication();
|
||||
autoCheckNewVersion();
|
||||
setState(() {
|
||||
_authenticating = currentAuthentication();
|
||||
});
|
||||
if (_authenticating) {
|
||||
_goAuthentication();
|
||||
} else {
|
||||
_goApplication();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_authenticating) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("身份验证"),
|
||||
),
|
||||
body: Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: MaterialButton(
|
||||
onPressed: () {
|
||||
_goAuthentication();
|
||||
},
|
||||
child: const Text('您在之前使用APP时开启了身份验证, 请点这段文字进行身份核查, 核查通过后将会进入APP'),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xfffffced),
|
||||
body: ConstrainedBox(
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: Image.asset(
|
||||
"lib/assets/init.jpg",
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future _goApplication() async {
|
||||
// 登录, 如果token失效重新登录, 网络不好的时候可能需要1分钟
|
||||
if (await method.preLogin()) {
|
||||
// 如果token或username+password有效则直接进入登录好的界面
|
||||
|
@ -100,17 +147,9 @@ class _InitScreenState extends State<InitScreen> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xfffffced),
|
||||
body: ConstrainedBox(
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: Image.asset(
|
||||
"lib/assets/init.jpg",
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
);
|
||||
Future _goAuthentication() async {
|
||||
if (await method.verifyAuthentication()) {
|
||||
_goApplication();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,17 @@ import 'package:pikapika/basic/config/shadowCategoriesMode.dart';
|
|||
import 'package:pikapika/screens/components/NetworkSetting.dart';
|
||||
import 'package:pikapika/screens/components/RightClickPop.dart';
|
||||
|
||||
import '../basic/config/Authentication.dart';
|
||||
import '../basic/config/UsingRightClickPop.dart';
|
||||
import 'CleanScreen.dart';
|
||||
import 'MigrateScreen.dart';
|
||||
import 'ModifyPasswordScreen.dart';
|
||||
|
||||
class SettingsScreen extends StatelessWidget {
|
||||
const SettingsScreen({Key? key}) : super(key: key);
|
||||
final bool hiddenAccountInfo;
|
||||
|
||||
const SettingsScreen({Key? key, this.hiddenAccountInfo = false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -51,16 +55,18 @@ class SettingsScreen extends StatelessWidget {
|
|||
body: ListView(
|
||||
children: [
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const ModifyPasswordScreen()),
|
||||
);
|
||||
},
|
||||
title: const Text('修改密码'),
|
||||
),
|
||||
hiddenAccountInfo
|
||||
? Container()
|
||||
: ListTile(
|
||||
onTap: () async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const ModifyPasswordScreen()),
|
||||
);
|
||||
},
|
||||
title: const Text('修改密码'),
|
||||
),
|
||||
const Divider(),
|
||||
const NetworkSetting(),
|
||||
const Divider(),
|
||||
|
@ -94,6 +100,7 @@ class SettingsScreen extends StatelessWidget {
|
|||
const Divider(),
|
||||
androidDisplayModeSetting(),
|
||||
androidSecureFlagSetting(),
|
||||
authenticationSetting(),
|
||||
const Divider(),
|
||||
chooserRootSetting(),
|
||||
downloadThreadCountSetting(),
|
||||
|
@ -131,5 +138,4 @@ class SettingsScreen extends StatelessWidget {
|
|||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue