Remember last used app

This also disables Home functionality on Android.
This commit is contained in:
Elias Bonnici 2024-03-07 12:43:06 +01:00
parent 908d2352dd
commit 6f3137752b
No known key found for this signature in database
GPG Key ID: 5EAC28EA3F980CCF
6 changed files with 37 additions and 40 deletions

View File

@ -23,7 +23,7 @@ import com.yubico.authenticator.device.Info
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
enum class OperationContext(val value: Int) {
Oath(0), Yubikey(1), Invalid(-1);
Home(0), Oath(1), Yubikey(2), Invalid(-1);
companion object {
fun getByValue(value: Int) = values().firstOrNull { it.value == value } ?: Invalid

View File

@ -64,8 +64,8 @@ Future<Widget> initialize() async {
oathStateProvider.overrideWithProvider(androidOathStateProvider.call),
credentialListProvider
.overrideWithProvider(androidCredentialListProvider.call),
currentAppProvider.overrideWith(
(ref) => AndroidSubPageNotifier(ref.watch(supportedAppsProvider))),
currentAppProvider.overrideWith((ref) => AndroidSubPageNotifier(
ref.watch(supportedAppsProvider), ref.watch(prefProvider))),
managementStateProvider.overrideWithProvider(androidManagementState.call),
currentDeviceProvider.overrideWith(
() => AndroidCurrentDeviceNotifier(),
@ -95,6 +95,7 @@ Future<Widget> initialize() async {
..setFeature(features.fido, false)
..setFeature(features.piv, false)
..setFeature(features.otp, false)
..setFeature(features.home, false)
..setFeature(features.management, false);
});

View File

@ -91,7 +91,7 @@ final androidSupportedThemesProvider = StateProvider<List<ThemeMode>>((ref) {
});
class AndroidSubPageNotifier extends CurrentAppNotifier {
AndroidSubPageNotifier(super.supportedApps) {
AndroidSubPageNotifier(super.supportedApps, super.prefs) {
_handleSubPage(state);
}

View File

@ -203,7 +203,8 @@ abstract class CurrentDeviceNotifier extends Notifier<DeviceNode?> {
final currentAppProvider =
StateNotifierProvider<CurrentAppNotifier, Application>((ref) {
final notifier = CurrentAppNotifier(ref.watch(supportedAppsProvider));
final notifier = CurrentAppNotifier(
ref.watch(supportedAppsProvider), ref.watch(prefProvider));
ref.listen<AsyncValue<YubiKeyData>>(currentDeviceDataProvider, (_, data) {
notifier._notifyDeviceChanged(data.whenOrNull(data: ((data) => data)));
}, fireImmediately: true);
@ -212,16 +213,29 @@ final currentAppProvider =
class CurrentAppNotifier extends StateNotifier<Application> {
final List<Application> _supportedApps;
static const String _key = 'APP_STATE_LAST_APP';
final SharedPreferences _prefs;
CurrentAppNotifier(this._supportedApps) : super(_supportedApps.first);
CurrentAppNotifier(this._supportedApps, this._prefs)
: super(_fromName(_prefs.getString(_key), _supportedApps));
void setCurrentApp(Application app) {
state = app;
_prefs.setString(_key, app.name);
}
void _notifyDeviceChanged(YubiKeyData? data) {
if (data == null ||
state.getAvailability(data) != Availability.unsupported) {
if (data == null) {
state = _supportedApps.first;
return;
}
String? lastAppName = _prefs.getString(_key);
if (lastAppName != null && lastAppName != state.name) {
// Try switching to saved app
state = Application.values.firstWhere((app) => app.name == lastAppName);
}
if (state.getAvailability(data) != Availability.unsupported) {
// Keep current app
return;
}
@ -231,6 +245,10 @@ class CurrentAppNotifier extends StateNotifier<Application> {
orElse: () => _supportedApps.first,
);
}
static Application _fromName(String? name, List<Application> supportedApps) =>
supportedApps.firstWhere((element) => element.name == name,
orElse: () => supportedApps.first);
}
abstract class QrScanner {

View File

@ -19,6 +19,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:material_symbols_icons/symbols.dart';
import '../../core/state.dart';
import '../models.dart';
import '../state.dart';
import 'device_picker.dart';
@ -126,7 +127,9 @@ class NavigationContent extends ConsumerWidget {
.where(
(app) => app.getAvailability(data) != Availability.unsupported)
.toList()
: [Application.home];
: !isAndroid // TODO: Remove check when Home is implemented on Android
? [Application.home]
: <Application>[];
availableApps.remove(Application.management);
final currentApp = ref.watch(currentAppProvider);
@ -138,9 +141,7 @@ class NavigationContent extends ConsumerWidget {
duration: const Duration(milliseconds: 150),
child: DevicePickerContent(extended: extended),
),
const SizedBox(height: 32),
AnimatedSize(
duration: const Duration(milliseconds: 150),
child: Column(
@ -153,7 +154,7 @@ class NavigationContent extends ConsumerWidget {
Icon(app._icon, fill: app == currentApp ? 1.0 : 0.0),
collapsed: !extended,
selected: app == currentApp,
onTap: currentApp == Application.home ||
onTap: data == null && currentApp == Application.home ||
data != null &&
app.getAvailability(data) ==
Availability.enabled
@ -171,32 +172,6 @@ class NavigationContent extends ConsumerWidget {
],
),
),
// // Non-YubiKey pages
// NavigationItem(
// leading: const Icon(Icons.settings_outlined),
// key: settingDrawerIcon,
// title: l10n.s_settings,
// collapsed: !extended,
// onTap: () {
// if (shouldPop) {
// Navigator.of(context).pop();
// }
// Actions.maybeInvoke(context, const SettingsIntent());
// },
// ),
// NavigationItem(
// leading: const Icon(Icons.help_outline),
// key: helpDrawerIcon,
// title: l10n.s_help_and_about,
// collapsed: !extended,
// onTap: () {
// if (shouldPop) {
// Navigator.of(context).pop();
// }
// Actions.maybeInvoke(context, const AboutIntent());
// },
// ),
],
),
);

View File

@ -21,6 +21,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../app/views/message_page.dart';
import '../../core/state.dart';
import '../../management/models.dart';
import 'key_actions.dart';
@ -59,13 +60,15 @@ class HomeMessagePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context)!;
// TODO: Remove Android check when Home is implemented on Android
return MessagePage(
title: l10n.s_home,
title: !isAndroid ? l10n.s_home : null,
graphic: graphic,
header: header,
message: message,
footnote: footnote,
keyActionsBuilder: (context) => homeBuildActions(context, null, ref),
keyActionsBuilder:
!isAndroid ? (context) => homeBuildActions(context, null, ref) : null,
actionButtonBuilder: actionButtonBuilder,
actionsBuilder: actionsBuilder,
fileDropOverlay: fileDropOverlay,