Skip to content

Commit

Permalink
Merge PR #1575
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamVe committed May 29, 2024
2 parents e23f599 + 5e9dfbc commit 492d045
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,13 @@ class MainActivity : FlutterFragmentActivity() {
logger.debug("Starting nfc discovery")
yubikit.startNfcDiscovery(
nfcConfiguration.disableNfcDiscoverySound(appPreferences.silenceNfcSounds),
this,
::processYubiKey
)
this
) { nfcYubiKeyDevice ->
if (!deviceManager.isUsbKeyConnected()) {
launchProcessYubiKey(nfcYubiKeyDevice)
}
}

hasNfc = true
} catch (e: NfcNotAvailable) {
hasNfc = false
Expand All @@ -131,7 +135,7 @@ class MainActivity : FlutterFragmentActivity() {
logger.debug("YubiKey was disconnected, stopping usb discovery")
stopUsbDiscovery()
}
processYubiKey(device)
launchProcessYubiKey(device)
}
}

Expand Down Expand Up @@ -214,7 +218,7 @@ class MainActivity : FlutterFragmentActivity() {
val device = NfcYubiKeyDevice(tag, nfcConfiguration.timeout, executor)
lifecycleScope.launch {
try {
contextManager?.processYubiKey(device)
processYubiKey(device)
device.remove {
executor.shutdown()
startNfcDiscovery()
Expand Down Expand Up @@ -269,41 +273,45 @@ class MainActivity : FlutterFragmentActivity() {
}
}

private fun processYubiKey(device: YubiKeyDevice) {
lifecycleScope.launch {
val deviceInfo = getDeviceInfo(device)
deviceManager.setDeviceInfo(deviceInfo)
private suspend fun processYubiKey(device: YubiKeyDevice) {
val deviceInfo = getDeviceInfo(device)
deviceManager.setDeviceInfo(deviceInfo)

if (deviceInfo == null) {
return@launch
}
if (deviceInfo == null) {
return
}

val supportedContexts = DeviceManager.getSupportedContexts(deviceInfo)
logger.debug("Connected key supports: {}", supportedContexts)
if (!supportedContexts.contains(viewModel.appContext.value)) {
val preferredContext = DeviceManager.getPreferredContext(supportedContexts)
logger.debug(
"Current context ({}) is not supported by the key. Using preferred context {}",
viewModel.appContext.value,
preferredContext
)
switchContext(preferredContext)
}
val supportedContexts = DeviceManager.getSupportedContexts(deviceInfo)
logger.debug("Connected key supports: {}", supportedContexts)
if (!supportedContexts.contains(viewModel.appContext.value)) {
val preferredContext = DeviceManager.getPreferredContext(supportedContexts)
logger.debug(
"Current context ({}) is not supported by the key. Using preferred context {}",
viewModel.appContext.value,
preferredContext
)
switchContext(preferredContext)
}

if (contextManager == null) {
switchContext(DeviceManager.getPreferredContext(supportedContexts))
}
if (contextManager == null) {
switchContext(DeviceManager.getPreferredContext(supportedContexts))
}

contextManager?.let {
try {
it.processYubiKey(device)
} catch (e: Throwable) {
logger.error("Error processing YubiKey in AppContextManager", e)
}
contextManager?.let {
try {
it.processYubiKey(device)
} catch (e: Throwable) {
logger.error("Error processing YubiKey in AppContextManager", e)
}
}
}

private fun launchProcessYubiKey(device: YubiKeyDevice) {
lifecycleScope.launch {
processYubiKey(device)
}
}

private var contextManager: AppContextManager? = null
private lateinit var deviceManager: DeviceManager
private lateinit var appContext: AppContext
Expand Down Expand Up @@ -342,7 +350,7 @@ class MainActivity : FlutterFragmentActivity() {

viewModel.appContext.observe(this) {
switchContext(it)
viewModel.connectedYubiKey.value?.let(::processYubiKey)
viewModel.connectedYubiKey.value?.let(::launchProcessYubiKey)
}
}

Expand Down
7 changes: 5 additions & 2 deletions lib/android/fido/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import 'dart:async';
import 'dart:convert';

import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart';
Expand Down Expand Up @@ -177,8 +178,10 @@ class _FidoFingerprintsNotifier extends FidoFingerprintsNotifier {
if (json == null) {
state = const AsyncValue.loading();
} else {
List<Fingerprint> newState = List.from(
(json as List).map((e) => Fingerprint.fromJson(e)).toList());
List<Fingerprint> newState = List.from((json as List)
.map((e) => Fingerprint.fromJson(e))
.sortedBy<String>((f) => f.label.toLowerCase())
.toList());
state = AsyncValue.data(newState);
}
}, onError: (err, stackTrace) {
Expand Down
19 changes: 5 additions & 14 deletions lib/android/oath/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -207,33 +207,24 @@ final addCredentialsToAnyProvider = Provider(
final androidCredentialListProvider = StateNotifierProvider.autoDispose
.family<OathCredentialListNotifier, List<OathPair>?, DevicePath>(
(ref, devicePath) {
var notifier = _AndroidCredentialListNotifier(
ref.watch(withContextProvider),
ref.watch(currentDeviceProvider)?.transport == Transport.usb,
);
var notifier =
_AndroidCredentialListNotifier(ref.watch(withContextProvider), ref);
return notifier;
},
);

class _AndroidCredentialListNotifier extends OathCredentialListNotifier {
final _events = const EventChannel('android.oath.credentials');
final WithContext _withContext;
final bool _isUsbAttached;
final Ref _ref;
late StreamSubscription _sub;

_AndroidCredentialListNotifier(this._withContext, this._isUsbAttached)
: super() {
_AndroidCredentialListNotifier(this._withContext, this._ref) : super() {
_sub = _events.receiveBroadcastStream().listen((event) {
final json = jsonDecode(event);
List<OathPair>? newState = json != null
? List.from((json as List).map((e) => OathPair.fromJson(e)).toList())
: null;
if (state != null && newState == null) {
// If we go from non-null to null this means we should stop listening to
// avoid receiving a message for a different notifier as there is only
// one channel.
_sub.cancel();
}
state = newState;
});
}
Expand All @@ -249,7 +240,7 @@ class _AndroidCredentialListNotifier extends OathCredentialListNotifier {
// Prompt for touch if needed
UserInteractionController? controller;
Timer? touchTimer;
if (_isUsbAttached) {
if (_ref.read(currentDeviceProvider)?.transport == Transport.usb) {
void triggerTouchPrompt() async {
controller = await _withContext(
(context) async {
Expand Down
34 changes: 14 additions & 20 deletions lib/home/views/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
final enabledCapabilities = widget.deviceData.info.config
.enabledCapabilities[widget.deviceData.node.transport] ??
0;
final primaryColor = ref.watch(defaultColorProvider);
final primaryColor = ref.watch(primaryColorProvider);

// We need this to avoid unwanted app switch animation
if (hide) {
Expand Down Expand Up @@ -219,19 +219,14 @@ class _DeviceColor extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context)!;
final theme = Theme.of(context);
final primaryColor = ref.watch(defaultColorProvider);
final defaultColor =
(isAndroid && ref.read(androidSdkVersionProvider) >= 31)
? theme.colorScheme.onSurface
: primaryColor;
final defaultColor = ref.watch(defaultColorProvider);
final customColor = initialCustomization.color;

return ChoiceFilterChip<Color?>(
disableHover: true,
value: customColor,
items: const [null],
selected: customColor != null && customColor != defaultColor,
selected: customColor != null && customColor.value != defaultColor.value,
itemBuilder: (e) => Wrap(
alignment: WrapAlignment.center,
runSpacing: 8,
Expand All @@ -250,32 +245,31 @@ class _DeviceColor extends ConsumerWidget {
Colors.lightGreen
].map((e) => _ColorButton(
color: e,
isSelected: customColor == e,
isSelected: customColor?.value == e.value,
onPressed: () {
_updateColor(e, ref);
Navigator.of(context).pop();
},
)),

// remove color button
// "use default color" button
RawMaterialButton(
onPressed: () {
_updateColor(null, ref);
Navigator.of(context).pop();
},
constraints: const BoxConstraints(minWidth: 26.0, minHeight: 26.0),
fillColor: (isAndroid && ref.read(androidSdkVersionProvider) >= 31)
? theme.colorScheme.onSurface
: primaryColor,
fillColor: defaultColor,
hoverColor: Colors.black12,
shape: const CircleBorder(),
child: Icon(
Symbols.cancel,
size: 16,
color: customColor == null
? theme.colorScheme.onSurface
: theme.colorScheme.surface.withOpacity(0.2),
),
child: Icon(customColor == null ? Symbols.circle : Symbols.clear,
fill: 1,
size: 16,
weight: 700,
opticalSize: 20,
color: defaultColor.computeLuminance() > 0.7
? Colors.grey // for bright colors
: Colors.white),
),
],
),
Expand Down

0 comments on commit 492d045

Please sign in to comment.