mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 10:11:52 +03:00
Remember last used app
This also disables Home functionality on Android.
This commit is contained in:
parent
908d2352dd
commit
6f3137752b
@ -23,7 +23,7 @@ import com.yubico.authenticator.device.Info
|
|||||||
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
|
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
|
||||||
|
|
||||||
enum class OperationContext(val value: Int) {
|
enum class OperationContext(val value: Int) {
|
||||||
Oath(0), Yubikey(1), Invalid(-1);
|
Home(0), Oath(1), Yubikey(2), Invalid(-1);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getByValue(value: Int) = values().firstOrNull { it.value == value } ?: Invalid
|
fun getByValue(value: Int) = values().firstOrNull { it.value == value } ?: Invalid
|
||||||
|
@ -64,8 +64,8 @@ Future<Widget> initialize() async {
|
|||||||
oathStateProvider.overrideWithProvider(androidOathStateProvider.call),
|
oathStateProvider.overrideWithProvider(androidOathStateProvider.call),
|
||||||
credentialListProvider
|
credentialListProvider
|
||||||
.overrideWithProvider(androidCredentialListProvider.call),
|
.overrideWithProvider(androidCredentialListProvider.call),
|
||||||
currentAppProvider.overrideWith(
|
currentAppProvider.overrideWith((ref) => AndroidSubPageNotifier(
|
||||||
(ref) => AndroidSubPageNotifier(ref.watch(supportedAppsProvider))),
|
ref.watch(supportedAppsProvider), ref.watch(prefProvider))),
|
||||||
managementStateProvider.overrideWithProvider(androidManagementState.call),
|
managementStateProvider.overrideWithProvider(androidManagementState.call),
|
||||||
currentDeviceProvider.overrideWith(
|
currentDeviceProvider.overrideWith(
|
||||||
() => AndroidCurrentDeviceNotifier(),
|
() => AndroidCurrentDeviceNotifier(),
|
||||||
@ -95,6 +95,7 @@ Future<Widget> initialize() async {
|
|||||||
..setFeature(features.fido, false)
|
..setFeature(features.fido, false)
|
||||||
..setFeature(features.piv, false)
|
..setFeature(features.piv, false)
|
||||||
..setFeature(features.otp, false)
|
..setFeature(features.otp, false)
|
||||||
|
..setFeature(features.home, false)
|
||||||
..setFeature(features.management, false);
|
..setFeature(features.management, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ final androidSupportedThemesProvider = StateProvider<List<ThemeMode>>((ref) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
class AndroidSubPageNotifier extends CurrentAppNotifier {
|
class AndroidSubPageNotifier extends CurrentAppNotifier {
|
||||||
AndroidSubPageNotifier(super.supportedApps) {
|
AndroidSubPageNotifier(super.supportedApps, super.prefs) {
|
||||||
_handleSubPage(state);
|
_handleSubPage(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,8 @@ abstract class CurrentDeviceNotifier extends Notifier<DeviceNode?> {
|
|||||||
|
|
||||||
final currentAppProvider =
|
final currentAppProvider =
|
||||||
StateNotifierProvider<CurrentAppNotifier, Application>((ref) {
|
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) {
|
ref.listen<AsyncValue<YubiKeyData>>(currentDeviceDataProvider, (_, data) {
|
||||||
notifier._notifyDeviceChanged(data.whenOrNull(data: ((data) => data)));
|
notifier._notifyDeviceChanged(data.whenOrNull(data: ((data) => data)));
|
||||||
}, fireImmediately: true);
|
}, fireImmediately: true);
|
||||||
@ -212,16 +213,29 @@ final currentAppProvider =
|
|||||||
|
|
||||||
class CurrentAppNotifier extends StateNotifier<Application> {
|
class CurrentAppNotifier extends StateNotifier<Application> {
|
||||||
final List<Application> _supportedApps;
|
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) {
|
void setCurrentApp(Application app) {
|
||||||
state = app;
|
state = app;
|
||||||
|
_prefs.setString(_key, app.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _notifyDeviceChanged(YubiKeyData? data) {
|
void _notifyDeviceChanged(YubiKeyData? data) {
|
||||||
if (data == null ||
|
if (data == null) {
|
||||||
state.getAvailability(data) != Availability.unsupported) {
|
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
|
// Keep current app
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -231,6 +245,10 @@ class CurrentAppNotifier extends StateNotifier<Application> {
|
|||||||
orElse: () => _supportedApps.first,
|
orElse: () => _supportedApps.first,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Application _fromName(String? name, List<Application> supportedApps) =>
|
||||||
|
supportedApps.firstWhere((element) => element.name == name,
|
||||||
|
orElse: () => supportedApps.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class QrScanner {
|
abstract class QrScanner {
|
||||||
|
@ -19,6 +19,7 @@ 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:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
|
||||||
|
import '../../core/state.dart';
|
||||||
import '../models.dart';
|
import '../models.dart';
|
||||||
import '../state.dart';
|
import '../state.dart';
|
||||||
import 'device_picker.dart';
|
import 'device_picker.dart';
|
||||||
@ -126,7 +127,9 @@ class NavigationContent extends ConsumerWidget {
|
|||||||
.where(
|
.where(
|
||||||
(app) => app.getAvailability(data) != Availability.unsupported)
|
(app) => app.getAvailability(data) != Availability.unsupported)
|
||||||
.toList()
|
.toList()
|
||||||
: [Application.home];
|
: !isAndroid // TODO: Remove check when Home is implemented on Android
|
||||||
|
? [Application.home]
|
||||||
|
: <Application>[];
|
||||||
availableApps.remove(Application.management);
|
availableApps.remove(Application.management);
|
||||||
final currentApp = ref.watch(currentAppProvider);
|
final currentApp = ref.watch(currentAppProvider);
|
||||||
|
|
||||||
@ -138,9 +141,7 @@ class NavigationContent extends ConsumerWidget {
|
|||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 150),
|
||||||
child: DevicePickerContent(extended: extended),
|
child: DevicePickerContent(extended: extended),
|
||||||
),
|
),
|
||||||
|
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
|
|
||||||
AnimatedSize(
|
AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 150),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -153,7 +154,7 @@ class NavigationContent extends ConsumerWidget {
|
|||||||
Icon(app._icon, fill: app == currentApp ? 1.0 : 0.0),
|
Icon(app._icon, fill: app == currentApp ? 1.0 : 0.0),
|
||||||
collapsed: !extended,
|
collapsed: !extended,
|
||||||
selected: app == currentApp,
|
selected: app == currentApp,
|
||||||
onTap: currentApp == Application.home ||
|
onTap: data == null && currentApp == Application.home ||
|
||||||
data != null &&
|
data != null &&
|
||||||
app.getAvailability(data) ==
|
app.getAvailability(data) ==
|
||||||
Availability.enabled
|
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());
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -21,6 +21,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import '../../app/views/message_page.dart';
|
import '../../app/views/message_page.dart';
|
||||||
|
import '../../core/state.dart';
|
||||||
import '../../management/models.dart';
|
import '../../management/models.dart';
|
||||||
import 'key_actions.dart';
|
import 'key_actions.dart';
|
||||||
|
|
||||||
@ -59,13 +60,15 @@ class HomeMessagePage extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final l10n = AppLocalizations.of(context)!;
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
|
// TODO: Remove Android check when Home is implemented on Android
|
||||||
return MessagePage(
|
return MessagePage(
|
||||||
title: l10n.s_home,
|
title: !isAndroid ? l10n.s_home : null,
|
||||||
graphic: graphic,
|
graphic: graphic,
|
||||||
header: header,
|
header: header,
|
||||||
message: message,
|
message: message,
|
||||||
footnote: footnote,
|
footnote: footnote,
|
||||||
keyActionsBuilder: (context) => homeBuildActions(context, null, ref),
|
keyActionsBuilder:
|
||||||
|
!isAndroid ? (context) => homeBuildActions(context, null, ref) : null,
|
||||||
actionButtonBuilder: actionButtonBuilder,
|
actionButtonBuilder: actionButtonBuilder,
|
||||||
actionsBuilder: actionsBuilder,
|
actionsBuilder: actionsBuilder,
|
||||||
fileDropOverlay: fileDropOverlay,
|
fileDropOverlay: fileDropOverlay,
|
||||||
|
Loading…
Reference in New Issue
Block a user