#165 new: bio auth

This commit is contained in:
lollipopkit
2023-09-16 17:26:40 +08:00
parent 2e8761f533
commit 8152829c89
25 changed files with 260 additions and 6 deletions

View File

@@ -164,6 +164,12 @@ abstract class S {
/// **'Attention'** /// **'Attention'**
String get attention; String get attention;
/// No description provided for @authRequired.
///
/// In en, this message translates to:
/// **'Auth required'**
String get authRequired;
/// No description provided for @auto. /// No description provided for @auto.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@@ -218,6 +224,12 @@ abstract class S {
/// **'Run in backgroud'** /// **'Run in backgroud'**
String get bgRun; String get bgRun;
/// No description provided for @bioAuth.
///
/// In en, this message translates to:
/// **'Biometric auth'**
String get bioAuth;
/// No description provided for @canPullRefresh. /// No description provided for @canPullRefresh.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View File

@@ -37,6 +37,9 @@ class SDe extends S {
@override @override
String get attention => 'Achtung'; String get attention => 'Achtung';
@override
String get authRequired => 'Autorisierung erforderlich';
@override @override
String get auto => 'System folgen'; String get auto => 'System folgen';
@@ -64,6 +67,9 @@ class SDe extends S {
@override @override
String get bgRun => 'Hintergrundaktualisierung'; String get bgRun => 'Hintergrundaktualisierung';
@override
String get bioAuth => 'Biozertifizierung';
@override @override
String get canPullRefresh => 'Danach: herunterziehen zum Aktualisieren'; String get canPullRefresh => 'Danach: herunterziehen zum Aktualisieren';

View File

@@ -37,6 +37,9 @@ class SEn extends S {
@override @override
String get attention => 'Attention'; String get attention => 'Attention';
@override
String get authRequired => 'Auth required';
@override @override
String get auto => 'Auto'; String get auto => 'Auto';
@@ -64,6 +67,9 @@ class SEn extends S {
@override @override
String get bgRun => 'Run in backgroud'; String get bgRun => 'Run in backgroud';
@override
String get bioAuth => 'Biometric auth';
@override @override
String get canPullRefresh => 'You can pull to refresh.'; String get canPullRefresh => 'You can pull to refresh.';

View File

@@ -37,6 +37,9 @@ class SId extends S {
@override @override
String get attention => 'Perhatian'; String get attention => 'Perhatian';
@override
String get authRequired => 'Auth diperlukan';
@override @override
String get auto => 'Auto'; String get auto => 'Auto';
@@ -64,6 +67,9 @@ class SId extends S {
@override @override
String get bgRun => 'Jalankan di Backgroud'; String get bgRun => 'Jalankan di Backgroud';
@override
String get bioAuth => 'Biosertifikasi';
@override @override
String get canPullRefresh => 'Anda dapat menarik untuk menyegarkan.'; String get canPullRefresh => 'Anda dapat menarik untuk menyegarkan.';

View File

@@ -37,6 +37,9 @@ class SZh extends S {
@override @override
String get attention => '注意'; String get attention => '注意';
@override
String get authRequired => '需要认证';
@override @override
String get auto => '自动'; String get auto => '自动';
@@ -64,6 +67,9 @@ class SZh extends S {
@override @override
String get bgRun => '后台运行'; String get bgRun => '后台运行';
@override
String get bioAuth => '生物认证';
@override @override
String get canPullRefresh => '可以下拉刷新'; String get canPullRefresh => '可以下拉刷新';
@@ -772,6 +778,9 @@ class SZhTw extends SZh {
@override @override
String get attention => '注意'; String get attention => '注意';
@override
String get authRequired => '需要認證';
@override @override
String get auto => '自動'; String get auto => '自動';
@@ -799,6 +808,9 @@ class SZhTw extends SZh {
@override @override
String get bgRun => '背景運行'; String get bgRun => '背景運行';
@override
String get bioAuth => '生物認證';
@override @override
String get canPullRefresh => '可以下拉更新'; String get canPullRefresh => '可以下拉更新';

View File

@@ -3,6 +3,7 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application <application
android:label="ServerBox" android:label="ServerBox"

View File

@@ -1,11 +1,11 @@
package tech.lolli.toolbox package tech.lolli.toolbox
import android.content.Intent import android.content.Intent
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() { class MainActivity: FlutterFragmentActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine) super.configureFlutterEngine(flutterEngine)
val binaryMessenger = flutterEngine.dartExecutor.binaryMessenger val binaryMessenger = flutterEngine.dartExecutor.binaryMessenger

View File

@@ -8,6 +8,8 @@ PODS:
- Flutter - Flutter
- icloud_storage (0.0.1): - icloud_storage (0.0.1):
- Flutter - Flutter
- local_auth_ios (0.0.1):
- Flutter
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
@@ -29,6 +31,7 @@ DEPENDENCIES:
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- icloud_storage (from `.symlinks/plugins/icloud_storage/ios`) - icloud_storage (from `.symlinks/plugins/icloud_storage/ios`)
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- plain_notification_token (from `.symlinks/plugins/plain_notification_token/ios`) - plain_notification_token (from `.symlinks/plugins/plain_notification_token/ios`)
- r_upgrade (from `.symlinks/plugins/r_upgrade/ios`) - r_upgrade (from `.symlinks/plugins/r_upgrade/ios`)
@@ -47,6 +50,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_native_splash/ios" :path: ".symlinks/plugins/flutter_native_splash/ios"
icloud_storage: icloud_storage:
:path: ".symlinks/plugins/icloud_storage/ios" :path: ".symlinks/plugins/icloud_storage/ios"
local_auth_ios:
:path: ".symlinks/plugins/local_auth_ios/ios"
path_provider_foundation: path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin" :path: ".symlinks/plugins/path_provider_foundation/darwin"
plain_notification_token: plain_notification_token:
@@ -66,6 +71,7 @@ SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
icloud_storage: d9ac7a33ced81df08ba7ea1bf3099cc0ee58f60a icloud_storage: d9ac7a33ced81df08ba7ea1bf3099cc0ee58f60a
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
plain_notification_token: b36467dc91939a7b6754267c701bbaca14996ee1 plain_notification_token: b36467dc91939a7b6754267c701bbaca14996ee1
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114 r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114

View File

@@ -68,5 +68,7 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>NSFaceIDUsageDescription</key>
<string>Required for auth</string>
</dict> </dict>
</plist> </plist>

View File

@@ -64,5 +64,7 @@
</array> </array>
<key>NSLocalNetworkUsageDescription</key> <key>NSLocalNetworkUsageDescription</key>
<string>ServerBox needs to access your local network to discover and connect to your server.</string> <string>ServerBox needs to access your local network to discover and connect to your server.</string>
<key>NSFaceIDUsageDescription</key>
<string>Required for auth</string>
</dict> </dict>
</plist> </plist>

View File

@@ -58,5 +58,7 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>NSFaceIDUsageDescription</key>
<string>Required for auth</string>
</dict> </dict>
</plist> </plist>

View File

@@ -0,0 +1,63 @@
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.dart';
import 'package:toolbox/core/utils/platform/base.dart';
import 'package:local_auth/error_codes.dart' as errs;
class BioAuth {
const BioAuth._();
static final _auth = LocalAuthentication();
static bool get isPlatformSupported => isAndroid || isIOS || isWindows;
static Future<bool> get isAvail async {
if (!isPlatformSupported) return false;
final canCheckBiometrics = await _auth.canCheckBiometrics;
if (!canCheckBiometrics) {
return false;
}
final biometrics = await _auth.getAvailableBiometrics();
if (biometrics.isEmpty) return false;
return biometrics.contains(BiometricType.fingerprint) ||
biometrics.contains(BiometricType.face);
}
static Future<AuthResult> auth([String? msg]) async {
if (!await isAvail) return AuthResult.notAvail;
try {
final reuslt = await _auth.authenticate(
localizedReason: msg ?? 'Auth required',
options: const AuthenticationOptions(
stickyAuth: true,
sensitiveTransaction: true,
biometricOnly: true,
),
);
if (reuslt) {
return AuthResult.success;
}
return AuthResult.fail;
} on PlatformException catch (e) {
switch (e.code) {
case errs.notEnrolled:
return AuthResult.notAvail;
case errs.lockedOut:
case errs.permanentlyLockedOut:
exit(0);
}
return AuthResult.cancel;
}
}
}
enum AuthResult {
success,
// Not match
fail,
// User cancel
cancel,
// Device doesn't support biometrics
notAvail,
}

View File

@@ -205,6 +205,13 @@ class SettingStore extends PersistentStore {
false, false,
); );
/// Only valid on iOS / Android
late final useBioAuth = StoreProperty(
box,
'useBioAuth',
false,
);
// Never show these settings for users // Never show these settings for users
// Guide for these settings: // Guide for these settings:
// - key should start with `_` and be shorter as possible // - key should start with `_` and be shorter as possible

View File

@@ -11,6 +11,7 @@
"alreadyLastDir": "Bereits im letzten Verzeichnis.", "alreadyLastDir": "Bereits im letzten Verzeichnis.",
"alterUrl": "Url ändern", "alterUrl": "Url ändern",
"attention": "Achtung", "attention": "Achtung",
"authRequired": "Autorisierung erforderlich",
"auto": "System folgen", "auto": "System folgen",
"autoCheckUpdate": "Aktualisierung automatisch prüfen", "autoCheckUpdate": "Aktualisierung automatisch prüfen",
"autoConnect": "Automatisch verbinden", "autoConnect": "Automatisch verbinden",
@@ -20,6 +21,7 @@
"backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.", "backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.",
"backupVersionNotMatch": "Die Backup-Version stimmt nicht überein.", "backupVersionNotMatch": "Die Backup-Version stimmt nicht überein.",
"bgRun": "Hintergrundaktualisierung", "bgRun": "Hintergrundaktualisierung",
"bioAuth": "Biozertifizierung",
"canPullRefresh": "Danach: herunterziehen zum Aktualisieren", "canPullRefresh": "Danach: herunterziehen zum Aktualisieren",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"choose": "Auswählen", "choose": "Auswählen",

View File

@@ -11,6 +11,7 @@
"alreadyLastDir": "Already in last directory.", "alreadyLastDir": "Already in last directory.",
"alterUrl": "Alter url", "alterUrl": "Alter url",
"attention": "Attention", "attention": "Attention",
"authRequired": "Auth required",
"auto": "Auto", "auto": "Auto",
"autoCheckUpdate": "Auto check update", "autoCheckUpdate": "Auto check update",
"autoConnect": "Auto connect", "autoConnect": "Auto connect",
@@ -20,6 +21,7 @@
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.", "backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
"backupVersionNotMatch": "Backup version is not match.", "backupVersionNotMatch": "Backup version is not match.",
"bgRun": "Run in backgroud", "bgRun": "Run in backgroud",
"bioAuth": "Biometric auth",
"canPullRefresh": "You can pull to refresh.", "canPullRefresh": "You can pull to refresh.",
"cancel": "Cancel", "cancel": "Cancel",
"choose": "Choose", "choose": "Choose",

View File

@@ -11,6 +11,7 @@
"alreadyLastDir": "Sudah di direktori terakhir.", "alreadyLastDir": "Sudah di direktori terakhir.",
"alterUrl": "Alter url", "alterUrl": "Alter url",
"attention": "Perhatian", "attention": "Perhatian",
"authRequired": "Auth diperlukan",
"auto": "Auto", "auto": "Auto",
"autoCheckUpdate": "Periksa pembaruan otomatis", "autoCheckUpdate": "Periksa pembaruan otomatis",
"autoConnect": "Hubungkan otomatis", "autoConnect": "Hubungkan otomatis",
@@ -20,6 +21,7 @@
"backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.", "backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.",
"backupVersionNotMatch": "Versi cadangan tidak cocok.", "backupVersionNotMatch": "Versi cadangan tidak cocok.",
"bgRun": "Jalankan di Backgroud", "bgRun": "Jalankan di Backgroud",
"bioAuth": "Biosertifikasi",
"canPullRefresh": "Anda dapat menarik untuk menyegarkan.", "canPullRefresh": "Anda dapat menarik untuk menyegarkan.",
"cancel": "Membatalkan", "cancel": "Membatalkan",
"choose": "Memilih", "choose": "Memilih",

View File

@@ -11,6 +11,7 @@
"alreadyLastDir": "已经是最上层目录了", "alreadyLastDir": "已经是最上层目录了",
"alterUrl": "备选链接", "alterUrl": "备选链接",
"attention": "注意", "attention": "注意",
"authRequired": "需要认证",
"auto": "自动", "auto": "自动",
"autoCheckUpdate": "自动检查更新", "autoCheckUpdate": "自动检查更新",
"autoConnect": "自动连接", "autoConnect": "自动连接",
@@ -20,6 +21,7 @@
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。", "backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
"backupVersionNotMatch": "备份版本不匹配,无法恢复", "backupVersionNotMatch": "备份版本不匹配,无法恢复",
"bgRun": "后台运行", "bgRun": "后台运行",
"bioAuth": "生物认证",
"canPullRefresh": "可以下拉刷新", "canPullRefresh": "可以下拉刷新",
"cancel": "取消", "cancel": "取消",
"choose": "选择", "choose": "选择",

View File

@@ -11,6 +11,7 @@
"alreadyLastDir": "已經是最上層目錄了", "alreadyLastDir": "已經是最上層目錄了",
"alterUrl": "備選鏈接", "alterUrl": "備選鏈接",
"attention": "注意", "attention": "注意",
"authRequired": "需要認證",
"auto": "自動", "auto": "自動",
"autoCheckUpdate": "自動檢查更新", "autoCheckUpdate": "自動檢查更新",
"autoConnect": "自動連接", "autoConnect": "自動連接",
@@ -20,6 +21,7 @@
"backupTip": "導出的數據僅進行了簡單加密,請妥善保管。", "backupTip": "導出的數據僅進行了簡單加密,請妥善保管。",
"backupVersionNotMatch": "備份版本不匹配,無法還原", "backupVersionNotMatch": "備份版本不匹配,無法還原",
"bgRun": "背景運行", "bgRun": "背景運行",
"bioAuth": "生物認證",
"canPullRefresh": "可以下拉更新", "canPullRefresh": "可以下拉更新",
"cancel": "取消", "cancel": "取消",
"choose": "選擇", "choose": "選擇",

View File

@@ -7,6 +7,7 @@ import 'package:get_it/get_it.dart';
import 'package:toolbox/core/channel/bg_run.dart'; import 'package:toolbox/core/channel/bg_run.dart';
import 'package:toolbox/core/channel/home_widget.dart'; import 'package:toolbox/core/channel/home_widget.dart';
import 'package:toolbox/core/extension/context/dialog.dart'; import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/utils/platform/auth.dart';
import 'package:toolbox/core/utils/platform/base.dart'; import 'package:toolbox/core/utils/platform/base.dart';
import 'package:toolbox/data/res/github_id.dart'; import 'package:toolbox/data/res/github_id.dart';
import 'package:toolbox/data/res/logger.dart'; import 'package:toolbox/data/res/logger.dart';
@@ -46,6 +47,7 @@ class _HomePageState extends State<HomePage>
late S _s; late S _s;
bool _switchingPage = false; bool _switchingPage = false;
bool _isAuthing = false;
@override @override
void initState() { void initState() {
@@ -81,6 +83,7 @@ class _HomePageState extends State<HomePage>
switch (state) { switch (state) {
case AppLifecycleState.resumed: case AppLifecycleState.resumed:
_auth();
if (!Providers.server.isAutoRefreshOn) { if (!Providers.server.isAutoRefreshOn) {
Providers.server.startAutoRefresh(); Providers.server.startAutoRefresh();
} }
@@ -338,6 +341,8 @@ class _HomePageState extends State<HomePage>
@override @override
Future<void> afterFirstLayout(BuildContext context) async { Future<void> afterFirstLayout(BuildContext context) async {
// Auth required for first launch
_auth();
if (Stores.setting.autoCheckAppUpdate.fetch()) { if (Stores.setting.autoCheckAppUpdate.fetch()) {
doUpdate(context); doUpdate(context);
} }
@@ -385,4 +390,32 @@ class _HomePageState extends State<HomePage>
Loggers.app.warning('Update json settings failed', e, trace); Loggers.app.warning('Update json settings failed', e, trace);
} }
} }
void _auth() {
if (Stores.setting.useBioAuth.fetch()) {
if (!_isAuthing) {
_isAuthing = true;
BioAuth.auth(_s.authRequired).then(
(val) {
switch (val) {
case AuthResult.success:
// wait for animation
Future.delayed(
const Duration(seconds: 1), () => _isAuthing = false);
break;
case AuthResult.fail:
case AuthResult.cancel:
_isAuthing = false;
_auth();
break;
case AuthResult.notAvail:
_isAuthing = false;
Stores.setting.useBioAuth.put(false);
break;
}
},
);
}
}
}
} }

View File

@@ -12,6 +12,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/core/extension/locale.dart'; import 'package:toolbox/core/extension/locale.dart';
import 'package:toolbox/core/extension/context/dialog.dart'; import 'package:toolbox/core/extension/context/dialog.dart';
import 'package:toolbox/core/extension/stringx.dart'; import 'package:toolbox/core/extension/stringx.dart';
import 'package:toolbox/core/utils/platform/auth.dart';
import 'package:toolbox/core/utils/platform/base.dart'; import 'package:toolbox/core/utils/platform/base.dart';
import 'package:toolbox/data/res/provider.dart'; import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/data/res/store.dart'; import 'package:toolbox/data/res/store.dart';
@@ -183,13 +184,16 @@ class _SettingPageState extends State<SettingPage> {
//_buildLaunchPage(), //_buildLaunchPage(),
_buildCheckUpdate(), _buildCheckUpdate(),
]; ];
if (isAndroid) {
children.add(_buildBgRun());
children.add(_buildAndroidWidgetSharedPreference());
}
if (isIOS) { if (isIOS) {
children.add(_buildPushToken()); children.add(_buildPushToken());
children.add(_buildAutoUpdateHomeWidget()); children.add(_buildAutoUpdateHomeWidget());
} }
if (isAndroid) { if (BioAuth.isPlatformSupported) {
children.add(_buildBgRun()); children.add(_buildBioAuth());
children.add(_buildAndroidWidgetSharedPreference());
} }
return Column( return Column(
children: children.map((e) => RoundRectCard(e)).toList(), children: children.map((e) => RoundRectCard(e)).toList(),
@@ -1096,4 +1100,41 @@ class _SettingPageState extends State<SettingPage> {
// trailing: StoreSwitch(prop: _setting.doubleColumnServersPage), // trailing: StoreSwitch(prop: _setting.doubleColumnServersPage),
// ); // );
// } // }
Widget _buildBioAuth() {
return FutureWidget<bool>(
future: BioAuth.isAvail,
loading: ListTile(
title: Text(_s.bioAuth),
subtitle: Text(_s.serverTabLoading, style: UIs.textGrey),
),
error: (e, __) => ListTile(
title: Text(_s.bioAuth),
subtitle: Text('${_s.failed}: $e', style: UIs.textGrey),
),
success: (can) {
return ListTile(
title: Text(_s.bioAuth),
trailing: can
? StoreSwitch(
prop: Stores.setting.useBioAuth,
func: (val) async {
if (val) {
Stores.setting.useBioAuth.put(false);
return;
}
// Only auth when turn off (val == false)
final result = await BioAuth.auth(_s.authRequired);
// If failed, turn on again
if (result != AuthResult.success) {
Stores.setting.useBioAuth.put(true);
}
},
)
: Text(_s.error, style: UIs.textGrey),
);
},
noData: UIs.placeholder,
);
}
} }

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FutureWidget<T> extends StatelessWidget { class FutureWidget<T> extends StatelessWidget {
final Future future; final Future<T> future;
final Widget loading; final Widget loading;
final Widget Function(Object? error, StackTrace? trace) error; final Widget Function(Object? error, StackTrace? trace) error;
final Widget Function(T data) success; final Widget Function(T data) success;

View File

@@ -518,6 +518,46 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
local_auth:
dependency: "direct main"
description:
name: local_auth
sha256: "7e6c63082e399b61e4af71266b012e767a5d4525dd6e9ba41e174fd42d76e115"
url: "https://pub.dev"
source: hosted
version: "2.1.7"
local_auth_android:
dependency: transitive
description:
name: local_auth_android
sha256: "9ad0b1ffa6f04f4d91e38c2d4c5046583e23f4cae8345776a994e8670df57fb1"
url: "https://pub.dev"
source: hosted
version: "1.0.34"
local_auth_ios:
dependency: transitive
description:
name: local_auth_ios
sha256: "26a8d1ad0b4ef6f861d29921be8383000fda952e323a5b6752cf82ca9cf9a7a9"
url: "https://pub.dev"
source: hosted
version: "1.1.4"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
sha256: fc5bd537970a324260fda506cfb61b33ad7426f37a8ea5c461cf612161ebba54
url: "https://pub.dev"
source: hosted
version: "1.0.8"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea"
url: "https://pub.dev"
source: hosted
version: "1.0.10"
logging: logging:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -49,6 +49,7 @@ dependencies:
macos_window_utils: ^1.2.0 macos_window_utils: ^1.2.0
dynamic_color: ^1.6.6 dynamic_color: ^1.6.6
icloud_storage: ^2.2.0 icloud_storage: ^2.2.0
local_auth: ^2.1.7
dev_dependencies: dev_dependencies:
flutter_native_splash: ^2.1.6 flutter_native_splash: ^2.1.6

View File

@@ -7,12 +7,15 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin_c_api.h> #include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <local_auth_windows/local_auth_plugin.h>
#include <share_plus/share_plus_windows_plugin_c_api.h> #include <share_plus/share_plus_windows_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
DynamicColorPluginCApiRegisterWithRegistrar( DynamicColorPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
LocalAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
SharePlusWindowsPluginCApiRegisterWithRegistrar( SharePlusWindowsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(

View File

@@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color dynamic_color
local_auth_windows
share_plus share_plus
url_launcher_windows url_launcher_windows
) )