2021-12-02 13:44:17 +03:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
2022-01-12 14:49:04 +03:00
|
|
|
import 'package:yubico_authenticator/management/models.dart';
|
|
|
|
import 'package:collection/collection.dart';
|
2021-12-02 13:44:17 +03:00
|
|
|
|
|
|
|
import '../models.dart';
|
|
|
|
import '../state.dart';
|
|
|
|
import 'device_avatar.dart';
|
|
|
|
|
2022-01-12 14:49:04 +03:00
|
|
|
Function _listEquals = const ListEquality().equals;
|
|
|
|
|
2021-12-02 13:44:17 +03:00
|
|
|
class MainActionsDialog extends ConsumerWidget {
|
|
|
|
const MainActionsDialog({Key? key}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
2022-01-12 14:49:04 +03:00
|
|
|
final devices = ref.watch(attachedDevicesProvider).toList();
|
|
|
|
final currentNode = ref.watch(currentDeviceProvider);
|
|
|
|
final data = ref.watch(currentDeviceDataProvider);
|
2021-12-02 13:44:17 +03:00
|
|
|
final actions = ref.watch(menuActionsProvider)(context);
|
2022-01-12 14:49:04 +03:00
|
|
|
|
|
|
|
if (currentNode != null) {
|
|
|
|
devices.removeWhere((e) => _listEquals(e.path, currentNode.path));
|
|
|
|
}
|
2021-12-02 13:44:17 +03:00
|
|
|
|
|
|
|
return SimpleDialog(
|
|
|
|
children: [
|
2022-01-12 14:49:04 +03:00
|
|
|
if (currentNode != null)
|
|
|
|
CurrentDeviceRow(
|
|
|
|
currentNode,
|
|
|
|
data?.name,
|
|
|
|
info: data?.info,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
...devices.map(
|
|
|
|
(e) => DeviceRow(
|
|
|
|
e,
|
|
|
|
e.name,
|
|
|
|
info: e.when(
|
|
|
|
usbYubiKey: (path, name, pid, info) => info,
|
|
|
|
nfcReader: (path, name) => null,
|
|
|
|
),
|
|
|
|
selected: false,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
ref.read(currentDeviceProvider.notifier).setCurrentDevice(e);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
2021-12-02 13:44:17 +03:00
|
|
|
if (actions.isNotEmpty) const Divider(),
|
|
|
|
...actions.map((a) => ListTile(
|
|
|
|
dense: true,
|
|
|
|
leading: a.icon,
|
|
|
|
title: Text(a.text),
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
a.action?.call();
|
|
|
|
},
|
|
|
|
)),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-12 14:49:04 +03:00
|
|
|
class CurrentDeviceRow extends StatelessWidget {
|
|
|
|
final DeviceNode node;
|
|
|
|
final String? name;
|
|
|
|
final DeviceInfo? info;
|
|
|
|
final Function() onTap;
|
|
|
|
|
|
|
|
const CurrentDeviceRow(
|
|
|
|
this.node,
|
|
|
|
this.name, {
|
|
|
|
required this.info,
|
|
|
|
required this.onTap,
|
|
|
|
Key? key,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final subtitle = node is NfcReaderNode
|
|
|
|
? info != null
|
|
|
|
? '${node.name}\nS/N: ${info!.serial} F/W: ${info!.version}'
|
|
|
|
: node.name
|
|
|
|
: 'S/N: ${info!.serial} F/W: ${info!.version}';
|
|
|
|
return ListTile(
|
|
|
|
leading: DeviceAvatar(
|
|
|
|
node,
|
|
|
|
name ?? '',
|
|
|
|
info,
|
|
|
|
selected: true,
|
|
|
|
),
|
|
|
|
title: Text(name ?? 'No YubiKey present'),
|
|
|
|
isThreeLine: subtitle.contains('\n'),
|
|
|
|
subtitle: Text(subtitle),
|
|
|
|
onTap: onTap,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-02 13:44:17 +03:00
|
|
|
class DeviceRow extends StatelessWidget {
|
2022-01-12 14:49:04 +03:00
|
|
|
final DeviceNode node;
|
|
|
|
final String name;
|
|
|
|
final DeviceInfo? info;
|
2021-12-02 13:44:17 +03:00
|
|
|
final bool selected;
|
2022-01-12 14:49:04 +03:00
|
|
|
final Function() onTap;
|
|
|
|
|
2021-12-02 13:44:17 +03:00
|
|
|
const DeviceRow(
|
2022-01-12 14:49:04 +03:00
|
|
|
this.node,
|
|
|
|
this.name, {
|
|
|
|
required this.info,
|
|
|
|
required this.onTap,
|
2021-12-02 13:44:17 +03:00
|
|
|
this.selected = false,
|
|
|
|
Key? key,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-01-12 14:49:04 +03:00
|
|
|
return ListTile(
|
|
|
|
leading: DeviceAvatar(
|
|
|
|
node,
|
|
|
|
name,
|
|
|
|
info,
|
|
|
|
selected: selected,
|
|
|
|
),
|
|
|
|
title: Text(name),
|
|
|
|
subtitle: Text(
|
|
|
|
info == null
|
|
|
|
? (selected ? 'No YubiKey present' : 'Select to scan')
|
|
|
|
: 'S/N: ${info!.serial} F/W: ${info!.version}',
|
2021-12-02 13:44:17 +03:00
|
|
|
),
|
2022-01-12 14:49:04 +03:00
|
|
|
onTap: onTap,
|
2021-12-02 13:44:17 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|