diff --git a/lib/app/key_customization/key_customization.dart b/lib/app/key_customization/key_customization.dart index 5dfc9a17..7851e190 100644 --- a/lib/app/key_customization/key_customization.dart +++ b/lib/app/key_customization/key_customization.dart @@ -16,6 +16,7 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:ui'; import 'package:crypto/crypto.dart'; import 'package:logging/logging.dart'; @@ -48,7 +49,7 @@ class KeyCustomizationManager { } KeyCustomization? get(String? serialNumber) { - _log.debug('Getting customization for: $serialNumber'); + _log.debug('Getting key customization for $serialNumber'); if (serialNumber == null || serialNumber.isEmpty) { return null; @@ -63,11 +64,14 @@ class KeyCustomizationManager { return null; } - void set(KeyCustomization customization) { - _log.debug( - 'Added: ${customization.serialNumber}: ${customization.properties}'); - final sha = getSerialSha(customization.serialNumber); - _customizations[sha] = customization.properties; + void set({required String serial, String? customName, Color? customColor}) { + final properties = { + 'display_color': customColor?.value.toRadixString(16), + 'display_name': customName?.isNotEmpty == true ? customName : null + }; + _log.debug('Setting key customization for $serial: $properties'); + final sha = getSerialSha(serial); + _customizations[sha] = properties; } Future write() async { diff --git a/lib/app/key_customization/models.dart b/lib/app/key_customization/models.dart index 926ff2ed..c1fd4906 100644 --- a/lib/app/key_customization/models.dart +++ b/lib/app/key_customization/models.dart @@ -15,12 +15,29 @@ */ import 'dart:convert'; +import 'dart:ui'; class KeyCustomization { final String serialNumber; - final Map properties; + final Map _properties; - const KeyCustomization(this.serialNumber, this.properties); + const KeyCustomization(this.serialNumber, this._properties); + + String? getName() => _properties['display_name'] as String?; + + Color? getColor() { + var customColor = _properties['display_color'] as String?; + if (customColor == null) { + return null; + } + + var intValue = int.tryParse(customColor, radix: 16); + + if (intValue == null) { + return null; + } + return Color(intValue); + } factory KeyCustomization.fromString(String serialNumber, String encodedJson) { final data = json.decode(String.fromCharCodes(base64Decode(encodedJson))); diff --git a/lib/app/key_customization/views/key_customization_dialog.dart b/lib/app/key_customization/views/key_customization_dialog.dart index cf7494f6..a4520f7e 100644 --- a/lib/app/key_customization/views/key_customization_dialog.dart +++ b/lib/app/key_customization/views/key_customization_dialog.dart @@ -17,7 +17,6 @@ import 'package:flutter/material.dart'; 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'; @@ -25,7 +24,6 @@ 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'; @@ -33,7 +31,21 @@ import '../../views/keys.dart'; import '../models.dart'; import '../state.dart'; -final _log = Logger('key_customization_dialog'); +extension _ColorHelper on String? { + Color? asColor() { + final hexValue = this; + if (hexValue == null) { + return null; + } + + final intValue = int.tryParse(hexValue, radix: 16); + if (intValue == null) { + return null; + } + + return Color(intValue); + } +} class KeyCustomizationDialog extends ConsumerStatefulWidget { final KeyCustomization? initialCustomization; @@ -49,23 +61,14 @@ class KeyCustomizationDialog extends ConsumerStatefulWidget { class _KeyCustomizationDialogState extends ConsumerState { - String? _displayName; - String? _displayColor; - Color? _previewColor; + String? _customName; + Color? _customColor; @override void initState() { super.initState(); - - _displayColor = widget.initialCustomization != null - ? widget.initialCustomization?.properties['display_color'] - : null; - _displayName = widget.initialCustomization != null - ? widget.initialCustomization?.properties['display_name'] - : null; - _previewColor = _displayColor != null - ? Color(int.parse(_displayColor!, radix: 16)) - : null; + _customName = widget.initialCustomization?.getName(); + _customColor = widget.initialCustomization?.getColor(); } @override @@ -76,12 +79,12 @@ class _KeyCustomizationDialogState final Widget hero; if (currentNode != null) { - hero = _CurrentDeviceAvatar(currentNode, _previewColor ?? Colors.white); + hero = _CurrentDeviceAvatar(currentNode, _customColor ?? Colors.white); } else { hero = Column( children: [ _HeroAvatar( - color: _previewColor ?? Colors.white, + color: _customColor ?? Colors.white, child: DeviceAvatar( radius: 64, child: Icon(isAndroid ? Icons.no_cell : Icons.usb), @@ -103,24 +106,17 @@ class _KeyCustomizationDialogState colorScheme: ColorScheme.fromSeed( brightness: theme.brightness, seedColor: - _previewColor ?? primaryColor ?? theme.colorScheme.primary), + _customColor ?? primaryColor ?? theme.colorScheme.primary), ), child: ResponsiveDialog( actions: [ TextButton( onPressed: () async { - KeyCustomization newValue = KeyCustomization( - widget.initialCustomization!.serialNumber, { - 'display_color': _displayColor, - 'display_name': _displayName - }); - - _log.debug('Saving customization for ' - '${widget.initialCustomization!.serialNumber}: ' - '$_displayName/$_displayColor'); - final manager = ref.read(keyCustomizationManagerProvider); - manager.set(newValue); + manager.set( + serial: widget.initialCustomization!.serialNumber, + customName: _customName, + customColor: _customColor); await manager.write(); ref.invalidate(lightThemeProvider); @@ -146,7 +142,7 @@ class _KeyCustomizationDialogState children: [ AppTextFormField( //controller: displayNameController, - initialValue: _displayName, + initialValue: _customName, maxLength: 20, decoration: AppInputDecoration( border: const OutlineInputBorder(), @@ -157,7 +153,7 @@ class _KeyCustomizationDialogState textInputAction: TextInputAction.done, onChanged: (value) { setState(() { - _displayName = value.trim(); + _customName = value.trim(); }); }, onFieldSubmitted: (_) {}, @@ -167,18 +163,19 @@ class _KeyCustomizationDialogState alignment: WrapAlignment.center, children: [ ...[ - [Colors.yellow, 'FFFFEB3B'], - [Colors.orange, 'FFFF9800'], - [Colors.red, 'FFF44336'], - [Colors.deepPurple, 'FF673AB7'], - [Colors.green, 'FF4CAF50'], - [Colors.teal, 'FF009688'], - [Colors.cyan, 'FF00BCD4'] + Colors.yellow.withOpacity(1.0), + Colors.orange.withOpacity(1.0), + Colors.red.withOpacity(1.0), + Colors.deepPurple.withOpacity(1.0), + Colors.green.withOpacity(1.0), + Colors.teal.withOpacity(1.0), + Colors.cyan.withOpacity(1.0), + 'FF88FFBB'.asColor() // example ].map((e) => _ColorButton( - color: e[0] as MaterialColor, - isSelected: _displayColor == e[1], + color: e, + isSelected: _customColor == e, onPressed: () { - _updateColor(e[1] as String?); + _updateColor(e); }, )), @@ -187,14 +184,14 @@ class _KeyCustomizationDialogState onPressed: () => _updateColor(null), constraints: const BoxConstraints( minWidth: 32.0, minHeight: 32.0), - fillColor: _displayColor == null + fillColor: _customColor == null ? theme.colorScheme.surface : theme.colorScheme.onSurface, shape: const CircleBorder(), child: Icon( Icons.cancel_rounded, size: 16, - color: _displayColor == null + color: _customColor == null ? theme.colorScheme.onSurface : theme.colorScheme.surface, ), @@ -210,11 +207,9 @@ class _KeyCustomizationDialogState ); } - void _updateColor(String? colorString) { + void _updateColor(Color? color) { setState(() { - _displayColor = colorString; - _previewColor = - colorString != null ? Color(int.parse(colorString, radix: 16)) : null; + _customColor = color; }); } } @@ -310,7 +305,7 @@ class _CurrentDeviceAvatar extends ConsumerWidget { } class _ColorButton extends StatefulWidget { - final MaterialColor color; + final Color? color; final bool isSelected; final Function()? onPressed; diff --git a/lib/app/state.dart b/lib/app/state.dart index e9410bc9..8dd17e1c 100755 --- a/lib/app/state.dart +++ b/lib/app/state.dart @@ -176,14 +176,8 @@ class ThemeNotifier extends Notifier { Color? primaryColor = color; if (yubiKeyData != null) { final manager = ref.read(keyCustomizationManagerProvider); - final customization = manager.get(yubiKeyData.info.serial?.toString()); - String? displayColorCustomization = - customization?.properties['display_color']; - - if (displayColorCustomization != null) { - primaryColor = Color(int.parse(displayColorCustomization, radix: 16)); - } + primaryColor = customization?.getColor() ?? color; } primaryColor ??= ref.read(primaryColorProvider); diff --git a/lib/app/views/device_picker.dart b/lib/app/views/device_picker.dart index a9e8d5dd..dc7d52fa 100644 --- a/lib/app/views/device_picker.dart +++ b/lib/app/views/device_picker.dart @@ -420,17 +420,9 @@ _DeviceRow _buildDeviceRow( nfcReader: (_, __) => l10n.s_select_to_scan, ); - String displayName = node.name; - if (info?.serial != null) { - final properties = ref - .read(keyCustomizationManagerProvider) - .get(info?.serial?.toString()) - ?.properties; - var customName = properties?['display_name']; - if (customName != null && customName != '') { - displayName = customName; - } - } + final keyCustomization = + ref.read(keyCustomizationManagerProvider).get(info?.serial?.toString()); + String displayName = keyCustomization?.getName() ?? node.name; return _DeviceRow( key: ValueKey(node.path.key), @@ -461,24 +453,13 @@ _DeviceRow _buildCurrentDeviceRow( final title = messages.removeAt(0); final subtitle = messages.join('\n'); - String displayName = title; - final serialNumber = data.hasValue ? data.value?.info.serial?.toString() : null; - Color? displayColor; - if (serialNumber != null) { - final properties = - ref.read(keyCustomizationManagerProvider).get(serialNumber)?.properties; - var customName = properties?['display_name']; - if (customName != null && customName != '') { - displayName = customName; - } - var customColor = properties?['display_color']; - if (customColor != null) { - displayColor = Color(int.parse(customColor, radix: 16)); - } - } + final keyCustomization = + ref.read(keyCustomizationManagerProvider).get(serialNumber); + String displayName = keyCustomization?.getName() ?? title; + Color? displayColor = keyCustomization?.getColor(); return _DeviceRow( key: keys.deviceInfoListTile,