mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 10:11:52 +03:00
add widget
This commit is contained in:
parent
861eae846c
commit
ec87865643
@ -16,6 +16,11 @@
|
||||
|
||||
package com.yubico.authenticator
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.*
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
@ -42,16 +47,22 @@ import com.yubico.authenticator.logging.FlutterLog
|
||||
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.yubikit.android.YubiKitManager
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcConfiguration
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcNotAvailable
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyManager
|
||||
import com.yubico.yubikit.android.transport.usb.UsbConfiguration
|
||||
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyManager
|
||||
import com.yubico.yubikit.core.YubiKeyDevice
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -74,6 +85,20 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(MainActivity::class.java)
|
||||
|
||||
private val nfcActivityListener = object : NfcActivityListener {
|
||||
|
||||
var appMethodChannel : AppMethodChannel? = null
|
||||
|
||||
override fun onChange(newState: NfcActivityState) {
|
||||
appMethodChannel?.let {
|
||||
logger.debug("setting nfc activity state to ${newState.name}")
|
||||
it.nfcActivityStateChanged(newState)
|
||||
} ?: {
|
||||
logger.warn("cannot set nfc activity state to ${newState.name} - no method channel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@ -85,7 +110,10 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
|
||||
allowScreenshots(false)
|
||||
|
||||
yubikit = YubiKitManager(this)
|
||||
yubikit = YubiKitManager(
|
||||
UsbYubiKeyManager(this),
|
||||
NfcYubiKeyManager(this, NfcActivityDispatcher(nfcActivityListener))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,6 +291,11 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
it.processYubiKey(device)
|
||||
if (device is NfcYubiKeyDevice) {
|
||||
device.remove {
|
||||
appMethodChannel.nfcActivityStateChanged(NfcActivityState.READY)
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logger.error("Error processing YubiKey in AppContextManager", e)
|
||||
}
|
||||
@ -291,6 +324,8 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
appMethodChannel = AppMethodChannel(messenger)
|
||||
appLinkMethodChannel = AppLinkMethodChannel(messenger)
|
||||
|
||||
nfcActivityListener.appMethodChannel = appMethodChannel
|
||||
|
||||
flutterStreams = listOf(
|
||||
viewModel.deviceInfo.streamTo(this, messenger, "android.devices.deviceInfo"),
|
||||
oathViewModel.sessionState.streamTo(this, messenger, "android.oath.sessionState"),
|
||||
@ -306,7 +341,8 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
viewModel,
|
||||
oathViewModel,
|
||||
dialogManager,
|
||||
appPreferences
|
||||
appPreferences,
|
||||
nfcActivityListener
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
@ -315,6 +351,7 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
}
|
||||
|
||||
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
nfcActivityListener.appMethodChannel = null
|
||||
flutterStreams.forEach { it.close() }
|
||||
super.cleanUpFlutterEngine(flutterEngine)
|
||||
}
|
||||
@ -427,6 +464,15 @@ class MainActivity : FlutterFragmentActivity() {
|
||||
JSONObject(mapOf("nfcEnabled" to value)).toString()
|
||||
)
|
||||
}
|
||||
|
||||
fun nfcActivityStateChanged(activityState: NfcActivityState) {
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
methodChannel.invokeMethod(
|
||||
"nfcActivityChanged",
|
||||
JSONObject(mapOf("state" to activityState.value)).toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun allowScreenshots(value: Boolean): Boolean {
|
||||
|
@ -27,7 +27,6 @@ import com.yubico.authenticator.*
|
||||
import com.yubico.authenticator.device.Capabilities
|
||||
import com.yubico.authenticator.device.Info
|
||||
import com.yubico.authenticator.device.UnknownDevice
|
||||
import com.yubico.authenticator.logging.Log
|
||||
import com.yubico.authenticator.oath.data.Code
|
||||
import com.yubico.authenticator.oath.data.CodeType
|
||||
import com.yubico.authenticator.oath.data.Credential
|
||||
@ -43,6 +42,8 @@ import com.yubico.authenticator.oath.keystore.ClearingMemProvider
|
||||
import com.yubico.authenticator.oath.keystore.KeyProvider
|
||||
import com.yubico.authenticator.oath.keystore.KeyStoreProvider
|
||||
import com.yubico.authenticator.oath.keystore.SharedPrefProvider
|
||||
import com.yubico.authenticator.yubikit.NfcActivityListener
|
||||
import com.yubico.authenticator.yubikit.NfcActivityState
|
||||
import com.yubico.authenticator.yubikit.getDeviceInfo
|
||||
import com.yubico.authenticator.yubikit.withConnection
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
|
||||
@ -76,6 +77,7 @@ class OathManager(
|
||||
private val oathViewModel: OathViewModel,
|
||||
private val dialogManager: DialogManager,
|
||||
private val appPreferences: AppPreferences,
|
||||
private val nfcActivityListener: NfcActivityListener
|
||||
) : AppContextManager {
|
||||
companion object {
|
||||
const val NFC_DATA_CLEANUP_DELAY = 30L * 1000 // 30s
|
||||
@ -330,9 +332,14 @@ class OathManager(
|
||||
logger.debug(
|
||||
"Successfully read Oath session info (and credentials if unlocked) from connected key"
|
||||
)
|
||||
|
||||
nfcActivityListener.onChange(NfcActivityState.PROCESSING_FINISHED)
|
||||
} catch (e: Exception) {
|
||||
// OATH not enabled/supported, try to get DeviceInfo over other USB interfaces
|
||||
logger.error("Failed to connect to CCID", e)
|
||||
|
||||
nfcActivityListener.onChange(NfcActivityState.PROCESSING_INTERRUPTED)
|
||||
|
||||
if (device.transport == Transport.USB || e is ApplicationNotAvailableException) {
|
||||
val deviceInfo = try {
|
||||
getDeviceInfo(device)
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.yubico.authenticator.yubikit
|
||||
|
||||
import android.app.Activity
|
||||
import android.nfc.NfcAdapter
|
||||
import android.nfc.Tag
|
||||
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcConfiguration
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcDispatcher
|
||||
import com.yubico.yubikit.android.transport.nfc.NfcReaderDispatcher
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
interface NfcActivityListener {
|
||||
fun onChange(newState: NfcActivityState)
|
||||
}
|
||||
|
||||
class NfcActivityDispatcher(private val listener: NfcActivityListener) : NfcDispatcher {
|
||||
|
||||
private lateinit var adapter: NfcAdapter
|
||||
private lateinit var yubikitNfcDispatcher: NfcReaderDispatcher
|
||||
|
||||
private val logger = LoggerFactory.getLogger(NfcActivityDispatcher::class.java)
|
||||
|
||||
override fun enable(
|
||||
activity: Activity,
|
||||
nfcConfiguration: NfcConfiguration,
|
||||
handler: NfcDispatcher.OnTagHandler
|
||||
) {
|
||||
adapter = NfcAdapter.getDefaultAdapter(activity)
|
||||
yubikitNfcDispatcher = NfcReaderDispatcher(adapter)
|
||||
|
||||
logger.debug("enabling yubikit NFC activity dispatcher")
|
||||
yubikitNfcDispatcher.enable(
|
||||
activity,
|
||||
nfcConfiguration,
|
||||
TagInterceptor(listener, handler)
|
||||
)
|
||||
listener.onChange(NfcActivityState.READY)
|
||||
}
|
||||
|
||||
override fun disable(activity: Activity) {
|
||||
listener.onChange(NfcActivityState.NOT_ACTIVE)
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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)
|
||||
}
|
@ -57,6 +57,12 @@ void setupAppMethodsChannel(WidgetRef ref) {
|
||||
ref.read(androidNfcStateProvider.notifier).setNfcEnabled(nfcEnabled);
|
||||
break;
|
||||
}
|
||||
case 'nfcActivityChanged':
|
||||
{
|
||||
var nfcActivityState = args['state'];
|
||||
ref.read(androidNfcActivityProvider.notifier).setActivityState(nfcActivityState);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw PlatformException(
|
||||
code: 'NotImplemented',
|
||||
|
@ -73,6 +73,32 @@ class NfcStateNotifier extends StateNotifier<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
enum NfcActivity {
|
||||
notActive,
|
||||
ready,
|
||||
processingStarted,
|
||||
processingFinished,
|
||||
processingInterrupted,
|
||||
}
|
||||
|
||||
class NfcActivityNotifier extends StateNotifier<NfcActivity> {
|
||||
NfcActivityNotifier() : super(NfcActivity.notActive);
|
||||
|
||||
void setActivityState(int stateValue) {
|
||||
|
||||
var newState = switch (stateValue) {
|
||||
0 => NfcActivity.notActive,
|
||||
1 => NfcActivity.ready,
|
||||
2 => NfcActivity.processingStarted,
|
||||
3 => NfcActivity.processingFinished,
|
||||
4 => NfcActivity.processingInterrupted,
|
||||
_ => NfcActivity.notActive
|
||||
};
|
||||
|
||||
state = newState;
|
||||
}
|
||||
}
|
||||
|
||||
final androidSdkVersionProvider = Provider<int>((ref) => -1);
|
||||
|
||||
final androidNfcSupportProvider = Provider<bool>((ref) => false);
|
||||
@ -80,6 +106,10 @@ final androidNfcSupportProvider = Provider<bool>((ref) => false);
|
||||
final androidNfcStateProvider =
|
||||
StateNotifierProvider<NfcStateNotifier, bool>((ref) => NfcStateNotifier());
|
||||
|
||||
final androidNfcActivityProvider = StateNotifierProvider<NfcActivityNotifier, NfcActivity>((ref) =>
|
||||
NfcActivityNotifier()
|
||||
);
|
||||
|
||||
final androidSupportedThemesProvider = StateProvider<List<ThemeMode>>((ref) {
|
||||
if (ref.read(androidSdkVersionProvider) < 29) {
|
||||
// the user can select from light or dark theme of the app
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Yubico.
|
||||
* Copyright (C) 2022-2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,9 +21,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'views/nfc/nfc_activity_widget.dart';
|
||||
|
||||
import '../app/state.dart';
|
||||
import '../app/views/user_interaction.dart';
|
||||
import '../widgets/custom_icons.dart';
|
||||
|
||||
const _channel = MethodChannel('com.yubico.authenticator.channel.dialog');
|
||||
|
||||
@ -35,6 +36,7 @@ final androidDialogProvider = Provider<_DialogProvider>(
|
||||
|
||||
class _DialogProvider {
|
||||
final WithContext _withContext;
|
||||
final Widget _icon = const NfcActivityWidget(width: 64, height: 64);
|
||||
UserInteractionController? _controller;
|
||||
|
||||
_DialogProvider(this._withContext) {
|
||||
@ -65,46 +67,29 @@ class _DialogProvider {
|
||||
_controller = null;
|
||||
}
|
||||
|
||||
Widget? _getIcon(String? icon) => switch (icon) {
|
||||
'nfc' => nfcIcon,
|
||||
'success' => const Icon(Icons.check_circle),
|
||||
'error' => const Icon(Icons.error),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
Future<void> _updateDialogState(
|
||||
String? title, String? description, String? iconName) async {
|
||||
final icon = _getIcon(iconName);
|
||||
await _withContext((context) async {
|
||||
_controller?.updateContent(
|
||||
title: title,
|
||||
description: description,
|
||||
icon: icon != null
|
||||
? IconTheme(
|
||||
data: IconTheme.of(context).copyWith(size: 64),
|
||||
child: icon,
|
||||
)
|
||||
: null,
|
||||
icon: _icon,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _showDialog(
|
||||
String title, String description, String? iconName) async {
|
||||
final icon = _getIcon(iconName);
|
||||
_controller = await _withContext((context) async => promptUserInteraction(
|
||||
context,
|
||||
title: title,
|
||||
description: description,
|
||||
icon: icon != null
|
||||
? IconTheme(
|
||||
data: IconTheme.of(context).copyWith(size: 64),
|
||||
child: icon,
|
||||
)
|
||||
: null,
|
||||
onCancel: () {
|
||||
_channel.invokeMethod('cancel');
|
||||
},
|
||||
));
|
||||
_controller = await _withContext((context) async {
|
||||
return promptUserInteraction(
|
||||
context,
|
||||
title: title,
|
||||
description: description,
|
||||
icon: _icon,
|
||||
onCancel: () {
|
||||
_channel.invokeMethod('cancel');
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
41
lib/android/views/nfc/main_page_nfc_activity_widget.dart
Normal file
41
lib/android/views/nfc/main_page_nfc_activity_widget.dart
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yubico_authenticator/android/state.dart';
|
||||
import 'package:yubico_authenticator/android/views/nfc/nfc_activity_widget.dart';
|
||||
|
||||
class MainPageNfcActivityWidget extends StatelessWidget {
|
||||
final Widget widget;
|
||||
const MainPageNfcActivityWidget(this.widget, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NfcActivityWidget(
|
||||
width: 128.0,
|
||||
height: 128.0,
|
||||
iconView: (nfcActivityState) {
|
||||
return Opacity(
|
||||
opacity: switch (nfcActivityState) {
|
||||
NfcActivity.processingStarted => 1.0,
|
||||
_ => 0.8
|
||||
},
|
||||
child: widget,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
90
lib/android/views/nfc/nfc_activity_icon.dart
Normal file
90
lib/android/views/nfc/nfc_activity_icon.dart
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yubico_authenticator/android/state.dart';
|
||||
|
||||
/// Default icon for [NfcActivityWidget]
|
||||
class NfcActivityIcon extends StatelessWidget {
|
||||
final NfcActivity nfcActivity;
|
||||
|
||||
const NfcActivityIcon(this.nfcActivity, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => switch (nfcActivity) {
|
||||
NfcActivity.processingStarted => const _NfcIconWithOpacity(1.0),
|
||||
_ => const _NfcIconWithOpacity(0.8)
|
||||
};
|
||||
}
|
||||
|
||||
class _NfcIconWithOpacity extends StatelessWidget {
|
||||
final double opacity;
|
||||
|
||||
const _NfcIconWithOpacity(this.opacity);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Opacity(
|
||||
opacity: opacity,
|
||||
child: const _NfcIcon(),
|
||||
);
|
||||
}
|
||||
|
||||
class _NfcIcon extends StatelessWidget {
|
||||
const _NfcIcon();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = IconTheme.of(context);
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext buildContext, BoxConstraints constraints) =>
|
||||
CustomPaint(
|
||||
size: Size.copy(constraints.biggest),
|
||||
painter: _NfcIconPainter(theme.color ?? Colors.black),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NfcIconPainter extends CustomPainter {
|
||||
final Color color;
|
||||
|
||||
_NfcIconPainter(this.color);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final step = size.width / 4;
|
||||
const sweep = pi / 4;
|
||||
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeCap = StrokeCap.round
|
||||
..strokeWidth = step / 2;
|
||||
|
||||
final rect =
|
||||
Offset(size.width * -1.7, 0) & Size(size.width * 2, size.height);
|
||||
for (var i = 0; i < 3; i++) {
|
||||
canvas.drawArc(rect.inflate(i * step), -sweep / 2, sweep, false, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
}
|
49
lib/android/views/nfc/nfc_activity_widget.dart
Normal file
49
lib/android/views/nfc/nfc_activity_widget.dart
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Yubico.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import '../../../app/logging.dart';
|
||||
import '../../state.dart';
|
||||
import 'nfc_activity_icon.dart';
|
||||
|
||||
final _logger = Logger('NfcActivityWidget');
|
||||
|
||||
class NfcActivityWidget extends ConsumerWidget {
|
||||
final double width;
|
||||
final double height;
|
||||
final Widget Function(NfcActivity)? iconView;
|
||||
|
||||
const NfcActivityWidget(
|
||||
{super.key, this.width = 32.0, this.height = 32.0, this.iconView});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final NfcActivity nfcActivityState = ref.watch(androidNfcActivityProvider);
|
||||
|
||||
_logger.debug('State for NfcActivityWidget changed to $nfcActivityState');
|
||||
|
||||
return IgnorePointer(
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: iconView?.call(nfcActivityState) ??
|
||||
NfcActivityIcon(nfcActivityState)),
|
||||
);
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import '../../android/app_methods.dart';
|
||||
import '../../android/state.dart';
|
||||
import '../../android/views/nfc/main_page_nfc_activity_widget.dart';
|
||||
import '../../exception/cancellation_exception.dart';
|
||||
import '../../core/state.dart';
|
||||
import '../../fido/views/fido_screen.dart';
|
||||
@ -82,7 +83,7 @@ class MainPage extends ConsumerWidget {
|
||||
var hasNfcSupport = ref.watch(androidNfcSupportProvider);
|
||||
var isNfcEnabled = ref.watch(androidNfcStateProvider);
|
||||
return MessagePage(
|
||||
graphic: noKeyImage,
|
||||
graphic: MainPageNfcActivityWidget(noKeyImage),
|
||||
message: hasNfcSupport && isNfcEnabled
|
||||
? l10n.l_insert_or_tap_yk
|
||||
: l10n.l_insert_yk,
|
||||
|
Loading…
Reference in New Issue
Block a user