Add basic device picker.

This commit is contained in:
Dain Nilsson 2021-11-23 14:51:36 +01:00
parent 2cd9ff2283
commit 94687f37f8
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
3 changed files with 82 additions and 6 deletions

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../core/rpc.dart'; import '../../core/rpc.dart';
import '../../core/state.dart'; import '../../core/state.dart';
@ -57,24 +58,35 @@ class AttachedDeviceNotifier extends StateNotifier<List<DeviceNode>> {
final currentDeviceProvider = final currentDeviceProvider =
StateNotifierProvider<CurrentDeviceNotifier, DeviceNode?>((ref) { StateNotifierProvider<CurrentDeviceNotifier, DeviceNode?>((ref) {
final provider = CurrentDeviceNotifier(); final provider = CurrentDeviceNotifier(ref.watch(prefProvider));
ref.listen(attachedDevicesProvider, provider._updateAttachedDevices); ref.listen(attachedDevicesProvider, provider._updateAttachedDevices);
return provider; return provider;
}); });
class CurrentDeviceNotifier extends StateNotifier<DeviceNode?> { class CurrentDeviceNotifier extends StateNotifier<DeviceNode?> {
CurrentDeviceNotifier() : super(null); static const String _lastDeviceSerial = 'APP_STATE_LAST_SERIAL';
final SharedPreferences _prefs;
CurrentDeviceNotifier(this._prefs) : super(null);
_updateAttachedDevices(List<DeviceNode>? previous, List<DeviceNode> devices) { _updateAttachedDevices(List<DeviceNode>? previous, List<DeviceNode> devices) {
if (devices.isEmpty) { if (devices.isEmpty) {
state = null; state = null;
} else if (!devices.contains(state)) { } else if (!devices.contains(state)) {
state = devices.first; // Prefer last selected device
final serial = _prefs.getInt(_lastDeviceSerial) ?? -1;
state = devices.firstWhere(
(element) => element.info.serial == serial,
orElse: () => devices.first,
);
} }
} }
setCurrentDevice(DeviceNode device) { setCurrentDevice(DeviceNode device) {
state = device; state = device;
final serial = device.info.serial;
if (serial != null) {
_prefs.setInt(_lastDeviceSerial, serial);
}
} }
} }

View File

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../about_page.dart';
import '../models.dart';
import '../state.dart';
class DevicePickerDialog extends ConsumerWidget {
const DevicePickerDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final device = ref.watch(currentDeviceProvider);
final devices = ref.watch(attachedDevicesProvider);
Widget _buildDeviceInfo(DeviceNode device) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
const CircleAvatar(child: Text('YK')),
const SizedBox(width: 16.0),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(device.name),
Text(
'Version: ${device.info.version} Serial: ${device.info.serial}'),
],
),
],
),
const Divider(),
],
),
);
}
return SimpleDialog(
//title: Text(device?.name ?? 'No YubiKey'),
children: [
if (device != null) _buildDeviceInfo(device),
...devices.where((e) => e != device).map((e) => TextButton(
child: Text(e.name),
onPressed: () {
ref.read(currentDeviceProvider.notifier).setCurrentDevice(e);
Navigator.of(context).pop();
},
)),
const Divider(),
TextButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => const AboutPage()),
);
},
child: const Text('About Yubico Authenticator...'))
],
);
}
}

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'device_picker_dialog.dart';
import 'main_drawer.dart'; import 'main_drawer.dart';
import 'no_device_screen.dart'; import 'no_device_screen.dart';
import 'device_info_screen.dart'; import 'device_info_screen.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
import '../../about_page.dart';
import '../../oath/views/oath_screen.dart'; import '../../oath/views/oath_screen.dart';
class MainPage extends ConsumerWidget { class MainPage extends ConsumerWidget {
@ -34,8 +34,9 @@ class MainPage extends ConsumerWidget {
IconButton( IconButton(
icon: const Icon(Icons.info), icon: const Icon(Icons.info),
onPressed: () { onPressed: () {
Navigator.of(context).push( showDialog(
MaterialPageRoute(builder: (context) => const AboutPage()), context: context,
builder: (context) => const DevicePickerDialog(),
); );
}, },
) )