mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-26 10:33:15 +03:00
Merge PR #962.
This commit is contained in:
commit
ee6dbdf4db
@ -30,9 +30,9 @@ class YubicoAuthenticatorApp extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return LogWarningOverlay(
|
||||
child: Shortcuts(
|
||||
shortcuts: globalShortcuts,
|
||||
return registerGlobalShortcuts(
|
||||
ref: ref,
|
||||
child: LogWarningOverlay(
|
||||
child: MaterialApp(
|
||||
title: 'Yubico Authenticator',
|
||||
theme: AppTheme.lightTheme,
|
||||
|
@ -18,19 +18,127 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../about_page.dart';
|
||||
import '../android/views/android_settings_page.dart';
|
||||
import '../core/state.dart';
|
||||
import '../oath/keys.dart';
|
||||
import '../settings_page.dart';
|
||||
import 'message.dart';
|
||||
import 'models.dart';
|
||||
import 'state.dart';
|
||||
|
||||
class CopyIntent extends Intent {
|
||||
const CopyIntent();
|
||||
}
|
||||
|
||||
class CloseIntent extends Intent {
|
||||
const CloseIntent();
|
||||
}
|
||||
|
||||
class SearchIntent extends Intent {
|
||||
const SearchIntent();
|
||||
}
|
||||
|
||||
class NextDeviceIntent extends Intent {
|
||||
const NextDeviceIntent();
|
||||
}
|
||||
|
||||
class SettingsIntent extends Intent {
|
||||
const SettingsIntent();
|
||||
}
|
||||
|
||||
class AboutIntent extends Intent {
|
||||
const AboutIntent();
|
||||
}
|
||||
|
||||
final ctrlOrCmd =
|
||||
Platform.isMacOS ? LogicalKeyboardKey.meta : LogicalKeyboardKey.control;
|
||||
|
||||
final globalShortcuts = {
|
||||
LogicalKeySet(ctrlOrCmd, LogicalKeyboardKey.keyC): const CopyIntent(),
|
||||
LogicalKeySet(ctrlOrCmd, LogicalKeyboardKey.keyF): const SearchIntent(),
|
||||
};
|
||||
Widget registerGlobalShortcuts(
|
||||
{required WidgetRef ref, required Widget child}) =>
|
||||
Actions(
|
||||
actions: {
|
||||
CloseIntent: CallbackAction<CloseIntent>(onInvoke: (_) {
|
||||
windowManager.close();
|
||||
return null;
|
||||
}),
|
||||
SearchIntent: CallbackAction<SearchIntent>(onInvoke: (intent) {
|
||||
// If the OATH view doesn't have focus, but is shown, find and select the search bar.
|
||||
final searchContext = searchAccountsField.currentContext;
|
||||
if (searchContext != null) {
|
||||
if (!Navigator.of(searchContext).canPop()) {
|
||||
return Actions.maybeInvoke(searchContext, intent);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
NextDeviceIntent: CallbackAction<NextDeviceIntent>(onInvoke: (_) {
|
||||
ref.read(withContextProvider)((context) async {
|
||||
if (!Navigator.of(context).canPop()) {
|
||||
final attached = ref
|
||||
.read(attachedDevicesProvider)
|
||||
.whereType<UsbYubiKeyNode>()
|
||||
.toList();
|
||||
if (attached.length > 1) {
|
||||
final current = ref.read(currentDeviceProvider);
|
||||
if (current != null && current is UsbYubiKeyNode) {
|
||||
final index = attached.indexOf(current);
|
||||
ref.read(currentDeviceProvider.notifier).setCurrentDevice(
|
||||
attached[(index + 1) % attached.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}),
|
||||
SettingsIntent: CallbackAction<SettingsIntent>(onInvoke: (_) {
|
||||
ref.read(withContextProvider)((context) async {
|
||||
if (!Navigator.of(context).canPop()) {
|
||||
await showBlurDialog(
|
||||
context: context,
|
||||
builder: (context) => Platform.isAndroid
|
||||
? const AndroidSettingsPage()
|
||||
: const SettingsPage(),
|
||||
routeSettings: const RouteSettings(name: 'settings'),
|
||||
);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}),
|
||||
AboutIntent: CallbackAction<AboutIntent>(onInvoke: (_) {
|
||||
ref.read(withContextProvider)((context) async {
|
||||
if (!Navigator.of(context).canPop()) {
|
||||
await showBlurDialog(
|
||||
context: context,
|
||||
builder: (context) => const AboutPage(),
|
||||
routeSettings: const RouteSettings(name: 'about'),
|
||||
);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}),
|
||||
},
|
||||
child: Shortcuts(
|
||||
shortcuts: {
|
||||
LogicalKeySet(ctrlOrCmd, LogicalKeyboardKey.keyC): const CopyIntent(),
|
||||
LogicalKeySet(ctrlOrCmd, LogicalKeyboardKey.keyW):
|
||||
const CloseIntent(),
|
||||
LogicalKeySet(ctrlOrCmd, LogicalKeyboardKey.keyF):
|
||||
const SearchIntent(),
|
||||
if (isDesktop) ...{
|
||||
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.tab):
|
||||
const NextDeviceIntent(),
|
||||
},
|
||||
if (Platform.isMacOS) ...{
|
||||
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.keyQ):
|
||||
const CloseIntent(),
|
||||
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.comma):
|
||||
const SettingsIntent(),
|
||||
},
|
||||
},
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
@ -14,18 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../about_page.dart';
|
||||
import '../../android/views/android_settings_page.dart';
|
||||
import '../../management/views/management_screen.dart';
|
||||
import '../../settings_page.dart';
|
||||
import '../message.dart';
|
||||
import '../models.dart';
|
||||
import '../shortcuts.dart';
|
||||
import '../state.dart';
|
||||
import 'keys.dart';
|
||||
|
||||
@ -76,7 +72,7 @@ class MainPageDrawer extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final supportedApps = ref.watch(supportedAppsProvider);
|
||||
final data = ref.watch(currentDeviceDataProvider).value;
|
||||
final data = ref.watch(currentDeviceDataProvider).valueOrNull;
|
||||
final color =
|
||||
Theme.of(context).brightness == Brightness.dark ? 'white' : 'green';
|
||||
|
||||
@ -105,30 +101,21 @@ class MainPageDrawer extends ConsumerWidget {
|
||||
index++;
|
||||
}
|
||||
|
||||
Widget Function(BuildContext) dialogBuilder;
|
||||
RouteSettings? routeSettings;
|
||||
switch (index) {
|
||||
case 0:
|
||||
dialogBuilder = (context) => ManagementScreen(data!);
|
||||
showBlurDialog(
|
||||
context: context,
|
||||
// data must be non-null when index == 0
|
||||
builder: (context) => ManagementScreen(data!),
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
dialogBuilder = (context) => Platform.isAndroid
|
||||
? const AndroidSettingsPage()
|
||||
: const SettingsPage();
|
||||
routeSettings = const RouteSettings(name: 'settings');
|
||||
Actions.maybeInvoke(context, const SettingsIntent());
|
||||
break;
|
||||
case 2:
|
||||
dialogBuilder = (context) => const AboutPage();
|
||||
routeSettings = const RouteSettings(name: 'about');
|
||||
Actions.maybeInvoke(context, const AboutIntent());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
showBlurDialog(
|
||||
context: context,
|
||||
builder: dialogBuilder,
|
||||
routeSettings: routeSettings,
|
||||
);
|
||||
}
|
||||
},
|
||||
children: [
|
||||
|
@ -24,7 +24,9 @@ const resetAction = Key('$_prefix.reset');
|
||||
|
||||
const noAccountsView = Key('$_prefix.no_accounts');
|
||||
|
||||
const searchAccountsField = Key('$_prefix.search_accounts');
|
||||
// This is global so we can access it from the global Ctrl+F shortcut.
|
||||
final searchAccountsField = GlobalKey();
|
||||
|
||||
const passwordField = Key('$_prefix.password');
|
||||
const currentPasswordField = Key('$_prefix.current_password');
|
||||
const newPasswordField = Key('$_prefix.new_password');
|
||||
|
Loading…
Reference in New Issue
Block a user