simplify working with KeyCustomization

This commit is contained in:
Adam Velebil 2024-01-23 12:36:13 +01:00
parent 56e20520a2
commit 20f8d6fd25
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
5 changed files with 81 additions and 90 deletions

View File

@ -16,6 +16,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:ui';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
@ -48,7 +49,7 @@ class KeyCustomizationManager {
} }
KeyCustomization? get(String? serialNumber) { KeyCustomization? get(String? serialNumber) {
_log.debug('Getting customization for: $serialNumber'); _log.debug('Getting key customization for $serialNumber');
if (serialNumber == null || serialNumber.isEmpty) { if (serialNumber == null || serialNumber.isEmpty) {
return null; return null;
@ -63,11 +64,14 @@ class KeyCustomizationManager {
return null; return null;
} }
void set(KeyCustomization customization) { void set({required String serial, String? customName, Color? customColor}) {
_log.debug( final properties = <String, String?>{
'Added: ${customization.serialNumber}: ${customization.properties}'); 'display_color': customColor?.value.toRadixString(16),
final sha = getSerialSha(customization.serialNumber); 'display_name': customName?.isNotEmpty == true ? customName : null
_customizations[sha] = customization.properties; };
_log.debug('Setting key customization for $serial: $properties');
final sha = getSerialSha(serial);
_customizations[sha] = properties;
} }
Future<void> write() async { Future<void> write() async {

View File

@ -15,12 +15,29 @@
*/ */
import 'dart:convert'; import 'dart:convert';
import 'dart:ui';
class KeyCustomization { class KeyCustomization {
final String serialNumber; final String serialNumber;
final Map<String, dynamic> properties; final Map<String, dynamic> _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) { factory KeyCustomization.fromString(String serialNumber, String encodedJson) {
final data = json.decode(String.fromCharCodes(base64Decode(encodedJson))); final data = json.decode(String.fromCharCodes(base64Decode(encodedJson)));

View File

@ -17,7 +17,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart';
import '../../../core/state.dart'; import '../../../core/state.dart';
import '../../../management/models.dart'; import '../../../management/models.dart';
@ -25,7 +24,6 @@ import '../../../widgets/app_input_decoration.dart';
import '../../../widgets/app_text_form_field.dart'; import '../../../widgets/app_text_form_field.dart';
import '../../../widgets/focus_utils.dart'; import '../../../widgets/focus_utils.dart';
import '../../../widgets/responsive_dialog.dart'; import '../../../widgets/responsive_dialog.dart';
import '../../logging.dart';
import '../../models.dart'; import '../../models.dart';
import '../../state.dart'; import '../../state.dart';
import '../../views/device_avatar.dart'; import '../../views/device_avatar.dart';
@ -33,7 +31,21 @@ import '../../views/keys.dart';
import '../models.dart'; import '../models.dart';
import '../state.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 { class KeyCustomizationDialog extends ConsumerStatefulWidget {
final KeyCustomization? initialCustomization; final KeyCustomization? initialCustomization;
@ -49,23 +61,14 @@ class KeyCustomizationDialog extends ConsumerStatefulWidget {
class _KeyCustomizationDialogState class _KeyCustomizationDialogState
extends ConsumerState<KeyCustomizationDialog> { extends ConsumerState<KeyCustomizationDialog> {
String? _displayName; String? _customName;
String? _displayColor; Color? _customColor;
Color? _previewColor;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_customName = widget.initialCustomization?.getName();
_displayColor = widget.initialCustomization != null _customColor = widget.initialCustomization?.getColor();
? 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;
} }
@override @override
@ -76,12 +79,12 @@ class _KeyCustomizationDialogState
final Widget hero; final Widget hero;
if (currentNode != null) { if (currentNode != null) {
hero = _CurrentDeviceAvatar(currentNode, _previewColor ?? Colors.white); hero = _CurrentDeviceAvatar(currentNode, _customColor ?? Colors.white);
} else { } else {
hero = Column( hero = Column(
children: [ children: [
_HeroAvatar( _HeroAvatar(
color: _previewColor ?? Colors.white, color: _customColor ?? Colors.white,
child: DeviceAvatar( child: DeviceAvatar(
radius: 64, radius: 64,
child: Icon(isAndroid ? Icons.no_cell : Icons.usb), child: Icon(isAndroid ? Icons.no_cell : Icons.usb),
@ -103,24 +106,17 @@ class _KeyCustomizationDialogState
colorScheme: ColorScheme.fromSeed( colorScheme: ColorScheme.fromSeed(
brightness: theme.brightness, brightness: theme.brightness,
seedColor: seedColor:
_previewColor ?? primaryColor ?? theme.colorScheme.primary), _customColor ?? primaryColor ?? theme.colorScheme.primary),
), ),
child: ResponsiveDialog( child: ResponsiveDialog(
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {
KeyCustomization newValue = KeyCustomization(
widget.initialCustomization!.serialNumber, <String, dynamic>{
'display_color': _displayColor,
'display_name': _displayName
});
_log.debug('Saving customization for '
'${widget.initialCustomization!.serialNumber}: '
'$_displayName/$_displayColor');
final manager = ref.read(keyCustomizationManagerProvider); final manager = ref.read(keyCustomizationManagerProvider);
manager.set(newValue); manager.set(
serial: widget.initialCustomization!.serialNumber,
customName: _customName,
customColor: _customColor);
await manager.write(); await manager.write();
ref.invalidate(lightThemeProvider); ref.invalidate(lightThemeProvider);
@ -146,7 +142,7 @@ class _KeyCustomizationDialogState
children: [ children: [
AppTextFormField( AppTextFormField(
//controller: displayNameController, //controller: displayNameController,
initialValue: _displayName, initialValue: _customName,
maxLength: 20, maxLength: 20,
decoration: AppInputDecoration( decoration: AppInputDecoration(
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
@ -157,7 +153,7 @@ class _KeyCustomizationDialogState
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
_displayName = value.trim(); _customName = value.trim();
}); });
}, },
onFieldSubmitted: (_) {}, onFieldSubmitted: (_) {},
@ -167,18 +163,19 @@ class _KeyCustomizationDialogState
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
children: [ children: [
...[ ...[
[Colors.yellow, 'FFFFEB3B'], Colors.yellow.withOpacity(1.0),
[Colors.orange, 'FFFF9800'], Colors.orange.withOpacity(1.0),
[Colors.red, 'FFF44336'], Colors.red.withOpacity(1.0),
[Colors.deepPurple, 'FF673AB7'], Colors.deepPurple.withOpacity(1.0),
[Colors.green, 'FF4CAF50'], Colors.green.withOpacity(1.0),
[Colors.teal, 'FF009688'], Colors.teal.withOpacity(1.0),
[Colors.cyan, 'FF00BCD4'] Colors.cyan.withOpacity(1.0),
'FF88FFBB'.asColor() // example
].map((e) => _ColorButton( ].map((e) => _ColorButton(
color: e[0] as MaterialColor, color: e,
isSelected: _displayColor == e[1], isSelected: _customColor == e,
onPressed: () { onPressed: () {
_updateColor(e[1] as String?); _updateColor(e);
}, },
)), )),
@ -187,14 +184,14 @@ class _KeyCustomizationDialogState
onPressed: () => _updateColor(null), onPressed: () => _updateColor(null),
constraints: const BoxConstraints( constraints: const BoxConstraints(
minWidth: 32.0, minHeight: 32.0), minWidth: 32.0, minHeight: 32.0),
fillColor: _displayColor == null fillColor: _customColor == null
? theme.colorScheme.surface ? theme.colorScheme.surface
: theme.colorScheme.onSurface, : theme.colorScheme.onSurface,
shape: const CircleBorder(), shape: const CircleBorder(),
child: Icon( child: Icon(
Icons.cancel_rounded, Icons.cancel_rounded,
size: 16, size: 16,
color: _displayColor == null color: _customColor == null
? theme.colorScheme.onSurface ? theme.colorScheme.onSurface
: theme.colorScheme.surface, : theme.colorScheme.surface,
), ),
@ -210,11 +207,9 @@ class _KeyCustomizationDialogState
); );
} }
void _updateColor(String? colorString) { void _updateColor(Color? color) {
setState(() { setState(() {
_displayColor = colorString; _customColor = color;
_previewColor =
colorString != null ? Color(int.parse(colorString, radix: 16)) : null;
}); });
} }
} }
@ -310,7 +305,7 @@ class _CurrentDeviceAvatar extends ConsumerWidget {
} }
class _ColorButton extends StatefulWidget { class _ColorButton extends StatefulWidget {
final MaterialColor color; final Color? color;
final bool isSelected; final bool isSelected;
final Function()? onPressed; final Function()? onPressed;

View File

@ -176,14 +176,8 @@ class ThemeNotifier extends Notifier<ThemeData> {
Color? primaryColor = color; Color? primaryColor = color;
if (yubiKeyData != null) { if (yubiKeyData != null) {
final manager = ref.read(keyCustomizationManagerProvider); final manager = ref.read(keyCustomizationManagerProvider);
final customization = manager.get(yubiKeyData.info.serial?.toString()); final customization = manager.get(yubiKeyData.info.serial?.toString());
String? displayColorCustomization = primaryColor = customization?.getColor() ?? color;
customization?.properties['display_color'];
if (displayColorCustomization != null) {
primaryColor = Color(int.parse(displayColorCustomization, radix: 16));
}
} }
primaryColor ??= ref.read(primaryColorProvider); primaryColor ??= ref.read(primaryColorProvider);

View File

@ -420,17 +420,9 @@ _DeviceRow _buildDeviceRow(
nfcReader: (_, __) => l10n.s_select_to_scan, nfcReader: (_, __) => l10n.s_select_to_scan,
); );
String displayName = node.name; final keyCustomization =
if (info?.serial != null) { ref.read(keyCustomizationManagerProvider).get(info?.serial?.toString());
final properties = ref String displayName = keyCustomization?.getName() ?? node.name;
.read(keyCustomizationManagerProvider)
.get(info?.serial?.toString())
?.properties;
var customName = properties?['display_name'];
if (customName != null && customName != '') {
displayName = customName;
}
}
return _DeviceRow( return _DeviceRow(
key: ValueKey(node.path.key), key: ValueKey(node.path.key),
@ -461,24 +453,13 @@ _DeviceRow _buildCurrentDeviceRow(
final title = messages.removeAt(0); final title = messages.removeAt(0);
final subtitle = messages.join('\n'); final subtitle = messages.join('\n');
String displayName = title;
final serialNumber = final serialNumber =
data.hasValue ? data.value?.info.serial?.toString() : null; data.hasValue ? data.value?.info.serial?.toString() : null;
Color? displayColor; final keyCustomization =
if (serialNumber != null) { ref.read(keyCustomizationManagerProvider).get(serialNumber);
final properties = String displayName = keyCustomization?.getName() ?? title;
ref.read(keyCustomizationManagerProvider).get(serialNumber)?.properties; Color? displayColor = keyCustomization?.getColor();
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));
}
}
return _DeviceRow( return _DeviceRow(
key: keys.deviceInfoListTile, key: keys.deviceInfoListTile,