mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-22 17:51:29 +03:00
shorten names, refactor
This commit is contained in:
parent
58552c0102
commit
17e383742c
@ -51,9 +51,9 @@ import com.yubico.authenticator.management.ManagementHandler
|
||||
import com.yubico.authenticator.oath.AppLinkMethodChannel
|
||||
import com.yubico.authenticator.oath.OathManager
|
||||
import com.yubico.authenticator.oath.OathViewModel
|
||||
import com.yubico.authenticator.yubikit.NfcActivityDispatcher
|
||||
import com.yubico.authenticator.yubikit.NfcActivityListener
|
||||
import com.yubico.authenticator.yubikit.NfcActivityState
|
||||
import com.yubico.authenticator.yubikit.NfcStateDispatcher
|
||||
import com.yubico.authenticator.yubikit.NfcStateListener
|
||||
import com.yubico.authenticator.yubikit.NfcState
|
||||
import com.yubico.authenticator.yubikit.DeviceInfoHelper.Companion.getDeviceInfo
|
||||
import com.yubico.authenticator.yubikit.withConnection
|
||||
import com.yubico.yubikit.android.YubiKitManager
|
||||
@ -79,7 +79,6 @@ import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.concurrent.Executors
|
||||
import javax.crypto.Mac
|
||||
@ -104,16 +103,16 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(MainActivity::class.java)
|
||||
|
||||
private val nfcActivityListener = object : NfcActivityListener {
|
||||
private val nfcStateListener = object : NfcStateListener {
|
||||
|
||||
var appMethodChannel : AppMethodChannel? = null
|
||||
|
||||
override fun onChange(newState: NfcActivityState) {
|
||||
override fun onChange(newState: NfcState) {
|
||||
appMethodChannel?.let {
|
||||
logger.debug("setting nfc activity state to ${newState.name}")
|
||||
it.nfcActivityStateChanged(newState)
|
||||
logger.debug("set nfc state to ${newState.name}")
|
||||
it.nfcStateChanged(newState)
|
||||
} ?: {
|
||||
logger.warn("cannot set nfc activity state to ${newState.name} - no method channel")
|
||||
logger.warn("failed set nfc state to ${newState.name} - no method channel")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,7 +130,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
|
||||
yubikit = YubiKitManager(
|
||||
UsbYubiKeyManager(this),
|
||||
NfcYubiKeyManager(this, NfcActivityDispatcher(nfcActivityListener))
|
||||
NfcYubiKeyManager(this, NfcStateDispatcher(nfcStateListener))
|
||||
)
|
||||
}
|
||||
|
||||
@ -319,7 +318,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
}
|
||||
|
||||
if (device is NfcYubiKeyDevice) {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_STARTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.ONGOING)
|
||||
}
|
||||
|
||||
// If NFC and FIPS check for SCP11b key
|
||||
@ -342,7 +341,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
} catch (e: Exception) {
|
||||
logger.debug("Exception while getting scp keys: ", e)
|
||||
if (device is NfcYubiKeyDevice) {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.FAILURE)
|
||||
}
|
||||
null
|
||||
}
|
||||
@ -376,14 +375,14 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
try {
|
||||
it.processYubiKey(device)
|
||||
if (!switchedContext && device is NfcYubiKeyDevice) {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_FINISHED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.SUCCESS)
|
||||
device.remove {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.READY)
|
||||
appMethodChannel.nfcStateChanged(NfcState.IDLE)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.debug("Caught Exception during YubiKey processing: ", e)
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.FAILURE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -420,7 +419,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
appLinkMethodChannel = AppLinkMethodChannel(messenger)
|
||||
managementHandler = ManagementHandler(messenger, deviceManager)
|
||||
|
||||
nfcActivityListener.appMethodChannel = appMethodChannel
|
||||
nfcStateListener.appMethodChannel = appMethodChannel
|
||||
|
||||
flutterStreams = listOf(
|
||||
viewModel.deviceInfo.streamTo(this, messenger, "android.devices.deviceInfo"),
|
||||
@ -486,7 +485,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
}
|
||||
|
||||
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
nfcActivityListener.appMethodChannel = null
|
||||
nfcStateListener.appMethodChannel = null
|
||||
flutterStreams.forEach { it.close() }
|
||||
contextManager?.dispose()
|
||||
deviceManager.dispose()
|
||||
@ -626,14 +625,14 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
fun nfcAdapterStateChanged(value: Boolean) {
|
||||
methodChannel.invokeMethod(
|
||||
"nfcAdapterStateChanged",
|
||||
JSONObject(mapOf("nfcEnabled" to value)).toString()
|
||||
JSONObject(mapOf("enabled" to value)).toString()
|
||||
)
|
||||
}
|
||||
|
||||
fun nfcActivityStateChanged(activityState: NfcActivityState) {
|
||||
fun nfcStateChanged(activityState: NfcState) {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
methodChannel.invokeMethod(
|
||||
"nfcActivityChanged",
|
||||
"nfcStateChanged",
|
||||
JSONObject(mapOf("state" to activityState.value)).toString()
|
||||
)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import com.yubico.authenticator.DialogManager
|
||||
import com.yubico.authenticator.MainActivity
|
||||
import com.yubico.authenticator.MainViewModel
|
||||
import com.yubico.authenticator.OperationContext
|
||||
import com.yubico.authenticator.yubikit.NfcActivityState
|
||||
import com.yubico.authenticator.yubikit.NfcState
|
||||
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
|
||||
import com.yubico.yubikit.core.YubiKeyDevice
|
||||
import com.yubico.yubikit.core.smartcard.scp.ScpKeyParams
|
||||
@ -222,11 +222,11 @@ class DeviceManager(
|
||||
if (e is ContextDisposedException) {
|
||||
// the key does not have the needed context anymore
|
||||
// we cannot continue
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.FAILURE)
|
||||
throw e
|
||||
}
|
||||
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.FAILURE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,7 +242,7 @@ class DeviceManager(
|
||||
try {
|
||||
return onNfc.invoke().value
|
||||
} catch (e: Exception) {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
appMethodChannel.nfcStateChanged(NfcState.FAILURE)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import com.yubico.authenticator.NULL
|
||||
import com.yubico.authenticator.device.DeviceManager
|
||||
import com.yubico.authenticator.fido.data.Session
|
||||
import com.yubico.authenticator.fido.data.YubiKitFidoSession
|
||||
import com.yubico.authenticator.yubikit.NfcActivityState
|
||||
import com.yubico.yubikit.core.application.CommandState
|
||||
import com.yubico.yubikit.core.fido.CtapException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
* Copyright (C) 2023-2024 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,10 +16,10 @@
|
||||
|
||||
package com.yubico.authenticator.yubikit
|
||||
|
||||
enum class NfcActivityState(val value: Int) {
|
||||
NOT_ACTIVE(0),
|
||||
READY(1),
|
||||
PROCESSING_STARTED(2),
|
||||
PROCESSING_FINISHED(3),
|
||||
PROCESSING_INTERRUPTED(4)
|
||||
enum class NfcState(val value: Int) {
|
||||
DISABLED(0),
|
||||
IDLE(1),
|
||||
ONGOING(2),
|
||||
SUCCESS(3),
|
||||
FAILURE(4)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
* Copyright (C) 2023-2024 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -18,8 +18,6 @@ package com.yubico.authenticator.yubikit
|
||||
|
||||
import android.app.Activity
|
||||
import android.nfc.NfcAdapter
|
||||
import android.nfc.Tag
|
||||
import com.yubico.authenticator.yubikit.NfcActivityListener
|
||||
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcConfiguration
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcDispatcher
|
||||
@ -27,16 +25,16 @@ import com.yubico.yubikit.android.transport.nfc.NfcReaderDispatcher
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
interface NfcActivityListener {
|
||||
fun onChange(newState: NfcActivityState)
|
||||
interface NfcStateListener {
|
||||
fun onChange(newState: NfcState)
|
||||
}
|
||||
|
||||
class NfcActivityDispatcher(private val listener: NfcActivityListener) : NfcDispatcher {
|
||||
class NfcStateDispatcher(private val listener: NfcStateListener) : NfcDispatcher {
|
||||
|
||||
private lateinit var adapter: NfcAdapter
|
||||
private lateinit var yubikitNfcDispatcher: NfcReaderDispatcher
|
||||
|
||||
private val logger = LoggerFactory.getLogger(NfcActivityDispatcher::class.java)
|
||||
private val logger = LoggerFactory.getLogger(NfcStateDispatcher::class.java)
|
||||
|
||||
override fun enable(
|
||||
activity: Activity,
|
||||
@ -46,33 +44,17 @@ class NfcActivityDispatcher(private val listener: NfcActivityListener) : NfcDisp
|
||||
adapter = NfcAdapter.getDefaultAdapter(activity)
|
||||
yubikitNfcDispatcher = NfcReaderDispatcher(adapter)
|
||||
|
||||
logger.debug("enabling yubikit NFC activity dispatcher")
|
||||
logger.debug("enabling yubikit NFC state dispatcher")
|
||||
yubikitNfcDispatcher.enable(
|
||||
activity,
|
||||
nfcConfiguration,
|
||||
TagInterceptor(listener, handler)
|
||||
handler
|
||||
)
|
||||
//listener.onChange(NfcActivityState.READY)
|
||||
}
|
||||
|
||||
override fun disable(activity: Activity) {
|
||||
listener.onChange(NfcActivityState.NOT_ACTIVE)
|
||||
listener.onChange(NfcState.DISABLED)
|
||||
yubikitNfcDispatcher.disable(activity)
|
||||
logger.debug("disabling yubikit NFC activity dispatcher")
|
||||
}
|
||||
|
||||
class TagInterceptor(
|
||||
private val listener: NfcActivityListener,
|
||||
private val tagHandler: NfcDispatcher.OnTagHandler
|
||||
) : NfcDispatcher.OnTagHandler {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(TagInterceptor::class.java)
|
||||
|
||||
override fun onTag(tag: Tag) {
|
||||
//listener.onChange(NfcActivityState.PROCESSING_STARTED)
|
||||
logger.debug("forwarding tag")
|
||||
tagHandler.onTag(tag)
|
||||
}
|
||||
|
||||
logger.debug("disabling yubikit NFC state dispatcher")
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../theme.dart';
|
||||
import 'state.dart';
|
||||
|
||||
@ -73,16 +74,14 @@ void setupAppMethodsChannel(WidgetRef ref) {
|
||||
switch (call.method) {
|
||||
case 'nfcAdapterStateChanged':
|
||||
{
|
||||
var nfcEnabled = args['nfcEnabled'];
|
||||
ref.read(androidNfcStateProvider.notifier).setNfcEnabled(nfcEnabled);
|
||||
var enabled = args['enabled'];
|
||||
ref.read(androidNfcAdapterState.notifier).enable(enabled);
|
||||
break;
|
||||
}
|
||||
case 'nfcActivityChanged':
|
||||
case 'nfcStateChanged':
|
||||
{
|
||||
var nfcActivityState = args['state'];
|
||||
ref
|
||||
.read(androidNfcActivityProvider.notifier)
|
||||
.setActivityState(nfcActivityState);
|
||||
var nfcState = args['state'];
|
||||
ref.read(androidNfcState.notifier).set(nfcState);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -40,12 +40,12 @@ class _NfcOverlayProvider extends Notifier<int> {
|
||||
|
||||
@override
|
||||
int build() {
|
||||
ref.listen(androidNfcActivityProvider, (previous, current) {
|
||||
ref.listen(androidNfcState, (previous, current) {
|
||||
processingViewTimeout?.cancel();
|
||||
final notifier = ref.read(nfcEventNotifier.notifier);
|
||||
|
||||
switch (current) {
|
||||
case NfcActivity.processingStarted:
|
||||
case NfcState.ongoing:
|
||||
// the "Hold still..." view will be shown after this timeout
|
||||
// if the action is finished before, the timer might be cancelled
|
||||
// causing the view not to be visible at all
|
||||
@ -55,19 +55,20 @@ class _NfcOverlayProvider extends Notifier<int> {
|
||||
notifier.send(showHoldStill());
|
||||
});
|
||||
break;
|
||||
case NfcActivity.processingFinished:
|
||||
case NfcState.success:
|
||||
notifier.send(showDone());
|
||||
notifier
|
||||
.send(const NfcHideViewEvent(delay: Duration(milliseconds: 400)));
|
||||
break;
|
||||
case NfcActivity.processingInterrupted:
|
||||
case NfcState.failure:
|
||||
notifier.send(showFailed());
|
||||
break;
|
||||
case NfcActivity.notActive:
|
||||
_log.debug('Received not handled notActive');
|
||||
case NfcState.disabled:
|
||||
_log.debug('Received state: disabled');
|
||||
break;
|
||||
case NfcState.idle:
|
||||
_log.debug('Received state: idle');
|
||||
break;
|
||||
case NfcActivity.ready:
|
||||
_log.debug('Received not handled ready');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -69,33 +69,33 @@ class _AndroidClipboard extends AppClipboard {
|
||||
}
|
||||
}
|
||||
|
||||
class NfcStateNotifier extends StateNotifier<bool> {
|
||||
NfcStateNotifier() : super(false);
|
||||
class NfcAdapterState extends StateNotifier<bool> {
|
||||
NfcAdapterState() : super(false);
|
||||
|
||||
void setNfcEnabled(bool value) {
|
||||
void enable(bool value) {
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
||||
enum NfcActivity {
|
||||
notActive,
|
||||
ready,
|
||||
processingStarted,
|
||||
processingFinished,
|
||||
processingInterrupted,
|
||||
enum NfcState {
|
||||
disabled,
|
||||
idle,
|
||||
ongoing,
|
||||
success,
|
||||
failure,
|
||||
}
|
||||
|
||||
class NfcActivityNotifier extends StateNotifier<NfcActivity> {
|
||||
NfcActivityNotifier() : super(NfcActivity.notActive);
|
||||
class NfcStateNotifier extends StateNotifier<NfcState> {
|
||||
NfcStateNotifier() : super(NfcState.disabled);
|
||||
|
||||
void setActivityState(int stateValue) {
|
||||
void set(int stateValue) {
|
||||
var newState = switch (stateValue) {
|
||||
0 => NfcActivity.notActive,
|
||||
1 => NfcActivity.ready,
|
||||
2 => NfcActivity.processingStarted,
|
||||
3 => NfcActivity.processingFinished,
|
||||
4 => NfcActivity.processingInterrupted,
|
||||
_ => NfcActivity.notActive
|
||||
0 => NfcState.disabled,
|
||||
1 => NfcState.idle,
|
||||
2 => NfcState.ongoing,
|
||||
3 => NfcState.success,
|
||||
4 => NfcState.failure,
|
||||
_ => NfcState.disabled
|
||||
};
|
||||
|
||||
state = newState;
|
||||
@ -108,12 +108,11 @@ final androidSdkVersionProvider = Provider<int>((ref) => -1);
|
||||
|
||||
final androidNfcSupportProvider = Provider<bool>((ref) => false);
|
||||
|
||||
final androidNfcStateProvider =
|
||||
StateNotifierProvider<NfcStateNotifier, bool>((ref) => NfcStateNotifier());
|
||||
final androidNfcAdapterState =
|
||||
StateNotifierProvider<NfcAdapterState, bool>((ref) => NfcAdapterState());
|
||||
|
||||
final androidNfcActivityProvider =
|
||||
StateNotifierProvider<NfcActivityNotifier, NfcActivity>(
|
||||
(ref) => NfcActivityNotifier());
|
||||
final androidNfcState = StateNotifierProvider<NfcStateNotifier, NfcState>(
|
||||
(ref) => NfcStateNotifier());
|
||||
|
||||
final androidSupportedThemesProvider = StateProvider<List<ThemeMode>>((ref) {
|
||||
if (ref.read(androidSdkVersionProvider) < 29) {
|
||||
@ -220,6 +219,7 @@ class NfcTapActionNotifier extends StateNotifier<NfcTapAction> {
|
||||
static const _prefNfcOpenApp = 'prefNfcOpenApp';
|
||||
static const _prefNfcCopyOtp = 'prefNfcCopyOtp';
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
NfcTapActionNotifier._(this._prefs, super._state);
|
||||
|
||||
factory NfcTapActionNotifier(SharedPreferences prefs) {
|
||||
@ -261,6 +261,7 @@ class NfcKbdLayoutNotifier extends StateNotifier<String> {
|
||||
static const String _defaultClipKbdLayout = 'US';
|
||||
static const _prefClipKbdLayout = 'prefClipKbdLayout';
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
NfcKbdLayoutNotifier(this._prefs)
|
||||
: super(_prefs.getString(_prefClipKbdLayout) ?? _defaultClipKbdLayout);
|
||||
|
||||
@ -279,6 +280,7 @@ final androidNfcBypassTouchProvider =
|
||||
class NfcBypassTouchNotifier extends StateNotifier<bool> {
|
||||
static const _prefNfcBypassTouch = 'prefNfcBypassTouch';
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
NfcBypassTouchNotifier(this._prefs)
|
||||
: super(_prefs.getBool(_prefNfcBypassTouch) ?? false);
|
||||
|
||||
@ -297,6 +299,7 @@ final androidNfcSilenceSoundsProvider =
|
||||
class NfcSilenceSoundsNotifier extends StateNotifier<bool> {
|
||||
static const _prefNfcSilenceSounds = 'prefNfcSilenceSounds';
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
NfcSilenceSoundsNotifier(this._prefs)
|
||||
: super(_prefs.getBool(_prefNfcSilenceSounds) ?? false);
|
||||
|
||||
@ -315,6 +318,7 @@ final androidUsbLaunchAppProvider =
|
||||
class UsbLaunchAppNotifier extends StateNotifier<bool> {
|
||||
static const _prefUsbOpenApp = 'prefUsbOpenApp';
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
UsbLaunchAppNotifier(this._prefs)
|
||||
: super(_prefs.getBool(_prefUsbOpenApp) ?? false);
|
||||
|
||||
|
@ -58,7 +58,7 @@ class _WindowStateNotifier extends StateNotifier<WindowState>
|
||||
if (lifeCycleState == AppLifecycleState.resumed) {
|
||||
_log.debug('Reading nfc enabled value');
|
||||
isNfcEnabled().then((value) =>
|
||||
_ref.read(androidNfcStateProvider.notifier).setNfcEnabled(value));
|
||||
_ref.read(androidNfcAdapterState.notifier).enable(value));
|
||||
}
|
||||
} else {
|
||||
_log.debug('Ignoring appLifecycleStateChange');
|
||||
|
@ -71,7 +71,7 @@ class DevicePickerContent extends ConsumerWidget {
|
||||
Widget? androidNoKeyWidget;
|
||||
if (isAndroid && devices.isEmpty) {
|
||||
var hasNfcSupport = ref.watch(androidNfcSupportProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcStateProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcAdapterState);
|
||||
final subtitle = hasNfcSupport && isNfcEnabled
|
||||
? l10n.l_insert_or_tap_yk
|
||||
: l10n.l_insert_yk;
|
||||
|
@ -52,8 +52,8 @@ class MainPage extends ConsumerWidget {
|
||||
);
|
||||
|
||||
if (isAndroid) {
|
||||
isNfcEnabled().then((value) =>
|
||||
ref.read(androidNfcStateProvider.notifier).setNfcEnabled(value));
|
||||
isNfcEnabled().then(
|
||||
(value) => ref.read(androidNfcAdapterState.notifier).enable(value));
|
||||
}
|
||||
|
||||
// If the current device changes, we need to pop any open dialogs.
|
||||
@ -98,7 +98,7 @@ class MainPage extends ConsumerWidget {
|
||||
if (deviceNode == null) {
|
||||
if (isAndroid) {
|
||||
var hasNfcSupport = ref.watch(androidNfcSupportProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcStateProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcAdapterState);
|
||||
return HomeMessagePage(
|
||||
centered: true,
|
||||
graphic: noKeyImage,
|
||||
|
@ -46,7 +46,7 @@ class MessagePageNotInitialized extends ConsumerWidget {
|
||||
|
||||
if (isAndroid) {
|
||||
var hasNfcSupport = ref.watch(androidNfcSupportProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcStateProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcAdapterState);
|
||||
var isUsbYubiKey =
|
||||
ref.watch(attachedDevicesProvider).firstOrNull?.transport ==
|
||||
Transport.usb;
|
||||
|
Loading…
Reference in New Issue
Block a user