diff --git a/lib/app/key_customization.dart b/lib/app/key_customization/key_customization.dart similarity index 90% rename from lib/app/key_customization.dart rename to lib/app/key_customization/key_customization.dart index b7005f53..5dfc9a17 100644 --- a/lib/app/key_customization.dart +++ b/lib/app/key_customization/key_customization.dart @@ -18,22 +18,14 @@ import 'dart:convert'; import 'dart:io'; import 'package:crypto/crypto.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; -import 'logging.dart'; +import '../logging.dart'; import 'models.dart'; -final _log = Logger('key_customization'); - -final keyCustomizationManagerProvider = - Provider((ref) { - final retval = KeyCustomizationManager(); - retval.read(); - return retval; -}); +final _log = Logger('key_customization_manager'); class KeyCustomizationManager { var _customizations = {}; diff --git a/lib/app/key_customization/models.dart b/lib/app/key_customization/models.dart new file mode 100644 index 00000000..926ff2ed --- /dev/null +++ b/lib/app/key_customization/models.dart @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 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:convert'; + +class KeyCustomization { + final String serialNumber; + final Map properties; + + const KeyCustomization(this.serialNumber, this.properties); + + factory KeyCustomization.fromString(String serialNumber, String encodedJson) { + final data = json.decode(String.fromCharCodes(base64Decode(encodedJson))); + return KeyCustomization(serialNumber, data); + } +} diff --git a/lib/app/key_customization/state.dart b/lib/app/key_customization/state.dart new file mode 100644 index 00000000..b60e3c77 --- /dev/null +++ b/lib/app/key_customization/state.dart @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 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_riverpod/flutter_riverpod.dart'; + +import 'key_customization.dart'; + +final keyCustomizationManagerProvider = + Provider((ref) { + final retval = KeyCustomizationManager(); + retval.read(); + return retval; +}); diff --git a/lib/app/views/key_customization_dialog.dart b/lib/app/key_customization/views/key_customization_dialog.dart similarity index 90% rename from lib/app/views/key_customization_dialog.dart rename to lib/app/key_customization/views/key_customization_dialog.dart index bc02786c..cf7494f6 100644 --- a/lib/app/views/key_customization_dialog.dart +++ b/lib/app/key_customization/views/key_customization_dialog.dart @@ -19,20 +19,21 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; -import '../../core/state.dart'; -import '../../management/models.dart'; -import '../../widgets/app_input_decoration.dart'; -import '../../widgets/app_text_form_field.dart'; -import '../../widgets/focus_utils.dart'; -import '../../widgets/responsive_dialog.dart'; -import '../key_customization.dart'; -import '../logging.dart'; +import '../../../core/state.dart'; +import '../../../management/models.dart'; +import '../../../widgets/app_input_decoration.dart'; +import '../../../widgets/app_text_form_field.dart'; +import '../../../widgets/focus_utils.dart'; +import '../../../widgets/responsive_dialog.dart'; +import '../../logging.dart'; +import '../../models.dart'; +import '../../state.dart'; +import '../../views/device_avatar.dart'; +import '../../views/keys.dart'; import '../models.dart'; import '../state.dart'; -import 'device_avatar.dart'; -import 'keys.dart'; -final _log = Logger('KeyCustomizationDialog'); +final _log = Logger('key_customization_dialog'); class KeyCustomizationDialog extends ConsumerStatefulWidget { final KeyCustomization? initialCustomization; @@ -62,7 +63,6 @@ class _KeyCustomizationDialogState _displayName = widget.initialCustomization != null ? widget.initialCustomization?.properties['display_name'] : null; - _previewColor = _displayColor != null ? Color(int.parse(_displayColor!, radix: 16)) : null; @@ -71,7 +71,7 @@ class _KeyCustomizationDialogState @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - final currentNode = widget.node; //ref.watch(currentDeviceProvider); + final currentNode = widget.node; final theme = Theme.of(context); final Widget hero; @@ -231,18 +231,22 @@ String _getDeviceInfoString(BuildContext context, DeviceInfo info) { ].join(' '); } -List _getDeviceStrings(BuildContext context, DeviceNode node) { - final messages = (node is UsbYubiKeyNode) +List _getDeviceStrings( + BuildContext context, WidgetRef ref, DeviceNode node) { + final data = ref.watch(currentDeviceDataProvider); + + final messages = node is UsbYubiKeyNode ? node.info != null ? [node.name, _getDeviceInfoString(context, node.info!)] : [] - : []; - - // Add the NFC reader name, unless it's already included (as device name, like on Android) - if (node is NfcReaderNode && !messages.contains(node.name)) { - messages.add(node.name); - } - + : data.hasValue + ? data.value?.node.path == node.path + ? [ + data.value!.name, + _getDeviceInfoString(context, data.value!.info) + ] + : [] + : []; return messages; } @@ -282,8 +286,6 @@ class _HeroAvatar extends StatelessWidget { class _CurrentDeviceAvatar extends ConsumerWidget { final DeviceNode node; - - //final AsyncValue data; final Color color; const _CurrentDeviceAvatar(this.node, this.color); @@ -291,7 +293,7 @@ class _CurrentDeviceAvatar extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final hero = DeviceAvatar.deviceNode(node, radius: 64); - final messages = _getDeviceStrings(context, node); + final messages = _getDeviceStrings(context, ref, node); return Column( children: [ diff --git a/lib/app/models.dart b/lib/app/models.dart index c08abbb4..cd279bd8 100755 --- a/lib/app/models.dart +++ b/lib/app/models.dart @@ -14,8 +14,6 @@ * limitations under the License. */ -import 'dart:convert'; - import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -111,9 +109,11 @@ class DevicePath { @freezed class DeviceNode with _$DeviceNode { const DeviceNode._(); + factory DeviceNode.usbYubiKey( DevicePath path, String name, UsbPid pid, DeviceInfo? info) = UsbYubiKeyNode; + factory DeviceNode.nfcReader(DevicePath path, String name) = NfcReaderNode; Transport get transport => @@ -146,15 +146,3 @@ class WindowState with _$WindowState { @Default(false) bool hidden, }) = _WindowState; } - -class KeyCustomization { - final String serialNumber; - final Map properties; - - const KeyCustomization(this.serialNumber, this.properties); - - factory KeyCustomization.fromString(String serialNumber, String encodedJson) { - final data = json.decode(String.fromCharCodes(base64Decode(encodedJson))); - return KeyCustomization(serialNumber, data); - } -} diff --git a/lib/app/state.dart b/lib/app/state.dart index 9cbebcd3..e9410bc9 100755 --- a/lib/app/state.dart +++ b/lib/app/state.dart @@ -27,7 +27,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../core/state.dart'; import '../theme.dart'; import 'features.dart' as features; -import 'key_customization.dart'; +import 'key_customization/state.dart'; import 'logging.dart'; import 'models.dart'; diff --git a/lib/app/views/device_picker.dart b/lib/app/views/device_picker.dart index a7eae126..58b60d69 100644 --- a/lib/app/views/device_picker.dart +++ b/lib/app/views/device_picker.dart @@ -23,12 +23,14 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../../android/state.dart'; import '../../core/state.dart'; import '../../management/models.dart'; -import '../key_customization.dart'; +import '../key_customization/key_customization.dart'; +import '../key_customization/models.dart'; +import '../key_customization/state.dart'; +import '../key_customization/views/key_customization_dialog.dart'; import '../message.dart'; import '../models.dart'; import '../state.dart'; import 'device_avatar.dart'; -import 'key_customization_dialog.dart'; import 'keys.dart' as keys; final _hiddenDevicesProvider =