mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-12-23 10:11:52 +03:00
Change various MessagePage
views.
This commit is contained in:
parent
2198f02184
commit
5fdb34f343
@ -65,6 +65,18 @@ enum Application {
|
||||
_ => name.substring(0, 1).toUpperCase() + name.substring(1),
|
||||
};
|
||||
|
||||
Capability? getCapability() => switch (this) {
|
||||
Application.accounts => Capability.oath,
|
||||
Application.webauthn => Capability.u2f,
|
||||
Application.passkeys => Capability.fido2,
|
||||
Application.fingerprints => Capability.fido2,
|
||||
Application.certificates => Capability.piv,
|
||||
Application.slots => Capability.otp,
|
||||
Application.hsmauth => Capability.hsmauth,
|
||||
Application.openpgp => Capability.openpgp,
|
||||
_ => null
|
||||
};
|
||||
|
||||
Availability getAvailability(YubiKeyData data) {
|
||||
if (this == Application.management) {
|
||||
final version = data.info.version;
|
||||
|
@ -44,7 +44,7 @@ class AppPage extends StatelessWidget {
|
||||
final Widget Function(BuildContext context)? actionButtonBuilder;
|
||||
final Widget? fileDropOverlay;
|
||||
final Function(File file)? onFileDropped;
|
||||
final List<Capability>? capabilities;
|
||||
final Capability? capability;
|
||||
const AppPage({
|
||||
super.key,
|
||||
this.title,
|
||||
@ -55,7 +55,7 @@ class AppPage extends StatelessWidget {
|
||||
this.detailViewBuilder,
|
||||
this.actionButtonBuilder,
|
||||
this.fileDropOverlay,
|
||||
this.capabilities,
|
||||
this.capability,
|
||||
this.onFileDropped,
|
||||
this.delayedContent = false,
|
||||
this.keyActionsBadge = false,
|
||||
@ -169,12 +169,7 @@ class AppPage extends StatelessWidget {
|
||||
.colorScheme
|
||||
.primary
|
||||
.withOpacity(0.9))),
|
||||
if (capabilities != null)
|
||||
Wrap(
|
||||
spacing: 4.0,
|
||||
runSpacing: 8.0,
|
||||
children: [...capabilities!.map((c) => _CapabilityBadge(c))],
|
||||
)
|
||||
if (capability != null) _CapabilityBadge(capability!)
|
||||
])
|
||||
],
|
||||
);
|
||||
@ -182,7 +177,8 @@ class AppPage extends StatelessWidget {
|
||||
|
||||
Widget _buildMainContent(BuildContext context, bool expanded) {
|
||||
final content = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
centered ? CrossAxisAlignment.center : CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (title != null)
|
||||
Padding(
|
||||
|
@ -25,7 +25,6 @@ import '../../desktop/state.dart';
|
||||
import '../message.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import 'device_avatar.dart';
|
||||
import 'message_page.dart';
|
||||
|
||||
class DeviceErrorScreen extends ConsumerWidget {
|
||||
@ -72,8 +71,13 @@ class DeviceErrorScreen extends ConsumerWidget {
|
||||
}
|
||||
return MessagePage(
|
||||
centered: true,
|
||||
graphic: const DeviceAvatar(child: Icon(Icons.usb_off)),
|
||||
message: l10n.l_yk_no_access,
|
||||
graphic: Image.asset(
|
||||
'assets/product-images/generic.png',
|
||||
filterQuality: FilterQuality.medium,
|
||||
scale: 3,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
header: l10n.l_yk_no_access,
|
||||
);
|
||||
}
|
||||
|
||||
@ -86,11 +90,11 @@ class DeviceErrorScreen extends ConsumerWidget {
|
||||
'unknown-device' => MessagePage(
|
||||
centered: true,
|
||||
graphic: Icon(
|
||||
Icons.help_outline,
|
||||
Icons.help_outlined,
|
||||
size: 96,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
message: l10n.s_unknown_device,
|
||||
header: l10n.s_unknown_device,
|
||||
),
|
||||
_ => MessagePage(
|
||||
centered: true,
|
||||
|
@ -26,10 +26,12 @@ import '../../exception/cancellation_exception.dart';
|
||||
import '../../fido/views/fingerprints_screen.dart';
|
||||
import '../../fido/views/passkeys_screen.dart';
|
||||
import '../../fido/views/webauthn_page.dart';
|
||||
import '../../management/views/management_screen.dart';
|
||||
import '../../oath/views/oath_screen.dart';
|
||||
import '../../otp/views/otp_screen.dart';
|
||||
import '../../piv/views/piv_screen.dart';
|
||||
import '../../widgets/custom_icons.dart';
|
||||
import '../message.dart';
|
||||
import '../models.dart';
|
||||
import '../state.dart';
|
||||
import 'device_error_screen.dart';
|
||||
@ -131,21 +133,48 @@ class MainPage extends ConsumerWidget {
|
||||
return ref.watch(currentDeviceDataProvider).when(
|
||||
data: (data) {
|
||||
final app = ref.watch(currentAppProvider);
|
||||
final capability = app.getCapability();
|
||||
if (data.info.supportedCapabilities.isEmpty &&
|
||||
data.name == 'Unrecognized device') {
|
||||
return MessagePage(
|
||||
centered: true,
|
||||
graphic: Icon(
|
||||
Icons.help_outlined,
|
||||
size: 96,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
header: l10n.s_yk_not_recognized,
|
||||
);
|
||||
} else if (app.getAvailability(data) ==
|
||||
Availability.unsupported) {
|
||||
return MessagePage(
|
||||
title: app.getDisplayName(l10n),
|
||||
capability: capability,
|
||||
header: l10n.s_app_not_supported,
|
||||
message: l10n.l_app_not_supported_on_yk(app.name),
|
||||
message: l10n.l_app_not_supported_on_yk(
|
||||
capability?.getDisplayName(l10n) ?? app.name),
|
||||
);
|
||||
} else if (app.getAvailability(data) != Availability.enabled) {
|
||||
return MessagePage(
|
||||
title: app.getDisplayName(l10n),
|
||||
capability: capability,
|
||||
header: l10n.s_app_disabled,
|
||||
message: l10n.l_app_disabled_desc(app.name),
|
||||
message: l10n.l_app_disabled_desc(
|
||||
capability?.getDisplayName(l10n) ?? app.name),
|
||||
actions: [
|
||||
ActionChip(
|
||||
label: Text(data.info.version.major > 4
|
||||
? l10n.s_toggle_applications
|
||||
: l10n.s_toggle_interfaces),
|
||||
onPressed: () async {
|
||||
await showBlurDialog(
|
||||
context: context,
|
||||
builder: (context) => ManagementScreen(data),
|
||||
);
|
||||
},
|
||||
avatar: const Icon(Icons.construction),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -32,9 +32,9 @@ class MessagePage extends StatelessWidget {
|
||||
final Widget Function(BuildContext context)? actionButtonBuilder;
|
||||
final Widget? fileDropOverlay;
|
||||
final Function(File file)? onFileDropped;
|
||||
final List<Capability>? capabilities;
|
||||
final Capability? capability;
|
||||
final bool keyActionsBadge;
|
||||
final bool? centered;
|
||||
final bool centered;
|
||||
|
||||
const MessagePage({
|
||||
super.key,
|
||||
@ -49,15 +49,15 @@ class MessagePage extends StatelessWidget {
|
||||
this.onFileDropped,
|
||||
this.delayedContent = false,
|
||||
this.keyActionsBadge = false,
|
||||
this.capabilities,
|
||||
this.centered,
|
||||
this.capability,
|
||||
this.centered = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => AppPage(
|
||||
title: title,
|
||||
capabilities: capabilities,
|
||||
centered: centered ?? false,
|
||||
capability: capability,
|
||||
centered: centered,
|
||||
actions: actions,
|
||||
keyActionsBuilder: keyActionsBuilder,
|
||||
keyActionsBadge: keyActionsBadge,
|
||||
@ -70,11 +70,11 @@ class MessagePage extends StatelessWidget {
|
||||
left: 16.0,
|
||||
top: 0.0,
|
||||
right: 16.0,
|
||||
bottom: centered ?? false ? 96 : 0),
|
||||
bottom: centered && actions.isEmpty ? 96 : 0),
|
||||
child: SizedBox(
|
||||
width: 350,
|
||||
child: Column(
|
||||
crossAxisAlignment: centered ?? false
|
||||
crossAxisAlignment: centered
|
||||
? CrossAxisAlignment.center
|
||||
: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -84,17 +84,14 @@ class MessagePage extends StatelessWidget {
|
||||
],
|
||||
if (header != null)
|
||||
Text(header!,
|
||||
textAlign:
|
||||
centered ?? false ? TextAlign.center : TextAlign.left,
|
||||
textAlign: centered ? TextAlign.center : TextAlign.left,
|
||||
style: Theme.of(context).textTheme.titleLarge),
|
||||
if (message != null) ...[
|
||||
const SizedBox(height: 12.0),
|
||||
Container(
|
||||
constraints: const BoxConstraints(maxWidth: 300),
|
||||
child: Text(message!,
|
||||
textAlign: centered ?? false
|
||||
? TextAlign.center
|
||||
: TextAlign.left,
|
||||
textAlign: centered ? TextAlign.center : TextAlign.left,
|
||||
style: Theme.of(context).textTheme.titleSmall?.apply(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
|
@ -61,7 +61,7 @@ class FingerprintsScreen extends ConsumerWidget {
|
||||
if (Capability.fido2.value & enabled == 0) {
|
||||
return MessagePage(
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.s_fido_disabled,
|
||||
message: l10n.l_webauthn_req_fido2,
|
||||
);
|
||||
@ -105,7 +105,7 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
)
|
||||
],
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: '${l10n.s_fingerprints_get_started} (1/2)',
|
||||
message: l10n.p_set_fingerprints_desc,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
@ -116,17 +116,28 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
if (state.forcePinChange) {
|
||||
return MessagePage(
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.s_pin_change_required,
|
||||
message: l10n.l_pin_change_required_desc,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
keyActionsBadge: fidoShowActionsNotifier(state),
|
||||
actions: [
|
||||
ActionChip(
|
||||
label: Text(l10n.s_change_pin),
|
||||
onPressed: () async {
|
||||
await showBlurDialog(
|
||||
context: context,
|
||||
builder: (context) => FidoPinDialog(node.path, state));
|
||||
},
|
||||
avatar: const Icon(Icons.pin_outlined),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return AppPage(
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
builder: (context, _) => Column(
|
||||
children: [
|
||||
@ -179,7 +190,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
|
||||
)
|
||||
],
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: '${l10n.s_fingerprints_get_started} (2/2)',
|
||||
message: l10n.l_add_one_or_more_fps,
|
||||
keyActionsBuilder: hasActions
|
||||
@ -239,7 +250,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
|
||||
},
|
||||
builder: (context) => AppPage(
|
||||
title: l10n.s_fingerprints,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
detailViewBuilder: fingerprint != null
|
||||
? (context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -37,6 +37,7 @@ import '../state.dart';
|
||||
import 'actions.dart';
|
||||
import 'credential_dialog.dart';
|
||||
import 'key_actions.dart';
|
||||
import 'pin_dialog.dart';
|
||||
import 'pin_entry_form.dart';
|
||||
|
||||
class PasskeysScreen extends ConsumerWidget {
|
||||
@ -56,10 +57,11 @@ class PasskeysScreen extends ConsumerWidget {
|
||||
final enabled = deviceData
|
||||
.info.config.enabledCapabilities[deviceData.node.transport] ??
|
||||
0;
|
||||
|
||||
if (Capability.fido2.value & enabled == 0) {
|
||||
return MessagePage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.s_fido_disabled,
|
||||
message: l10n.l_webauthn_req_fido2,
|
||||
);
|
||||
@ -92,7 +94,7 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
if (!state.hasPin) {
|
||||
return MessagePage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: state.credMgmt
|
||||
? l10n.l_no_discoverable_accounts
|
||||
: l10n.l_ready_to_use,
|
||||
@ -105,7 +107,7 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
if (!state.credMgmt && state.bioEnroll == null) {
|
||||
return MessagePage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.l_ready_to_use,
|
||||
message: l10n.l_register_sk_on_websites,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
@ -115,8 +117,19 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
|
||||
if (state.forcePinChange) {
|
||||
return MessagePage(
|
||||
actions: [
|
||||
ActionChip(
|
||||
label: Text(l10n.s_change_pin),
|
||||
onPressed: () async {
|
||||
await showBlurDialog(
|
||||
context: context,
|
||||
builder: (context) => FidoPinDialog(node.path, state));
|
||||
},
|
||||
avatar: const Icon(Icons.pin_outlined),
|
||||
)
|
||||
],
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.s_pin_change_required,
|
||||
message: l10n.l_pin_change_required_desc,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
@ -126,7 +139,7 @@ class _FidoLockedPage extends ConsumerWidget {
|
||||
|
||||
return AppPage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
keyActionsBuilder: hasActions ? _buildActions : null,
|
||||
builder: (context, _) => Column(
|
||||
children: [
|
||||
@ -164,7 +177,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
|
||||
// TODO: Special handling for credMgmt not supported
|
||||
return MessagePage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.l_no_discoverable_accounts,
|
||||
message: l10n.l_register_sk_on_websites,
|
||||
keyActionsBuilder: hasActions
|
||||
@ -184,7 +197,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
|
||||
if (credentials.isEmpty) {
|
||||
return MessagePage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
header: l10n.l_no_discoverable_accounts,
|
||||
message: l10n.l_register_sk_on_websites,
|
||||
keyActionsBuilder: hasActions
|
||||
@ -233,7 +246,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> {
|
||||
},
|
||||
builder: (context) => AppPage(
|
||||
title: l10n.s_passkeys,
|
||||
capabilities: const [Capability.fido2],
|
||||
capability: Capability.fido2,
|
||||
detailViewBuilder: credential != null
|
||||
? (context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -28,7 +28,7 @@ class WebAuthnScreen extends StatelessWidget {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return MessagePage(
|
||||
title: l10n.s_webauthn,
|
||||
capabilities: const [Capability.u2f],
|
||||
capability: Capability.u2f,
|
||||
header: l10n.l_ready_to_use,
|
||||
message: l10n.l_register_sk_on_websites,
|
||||
);
|
||||
|
@ -83,7 +83,7 @@ class _LockedView extends ConsumerWidget {
|
||||
final hasActions = ref.watch(featureProvider)(features.actions);
|
||||
return AppPage(
|
||||
title: AppLocalizations.of(context)!.s_accounts,
|
||||
capabilities: const [Capability.oath],
|
||||
capability: Capability.oath,
|
||||
keyActionsBuilder: hasActions
|
||||
? (context) => oathBuildActions(context, devicePath, oathState, ref)
|
||||
: null,
|
||||
@ -175,7 +175,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
)
|
||||
],
|
||||
title: l10n.s_accounts,
|
||||
capabilities: const [Capability.oath],
|
||||
capability: Capability.oath,
|
||||
key: keys.noAccountsView,
|
||||
header: l10n.l_authenticator_get_started,
|
||||
message: l10n.p_no_accounts_desc,
|
||||
@ -249,7 +249,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> {
|
||||
},
|
||||
builder: (context) => AppPage(
|
||||
title: l10n.s_accounts,
|
||||
capabilities: const [Capability.oath],
|
||||
capability: Capability.oath,
|
||||
keyActionsBuilder: hasActions
|
||||
? (context) => oathBuildActions(
|
||||
context,
|
||||
|
@ -93,7 +93,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
|
||||
},
|
||||
child: AppPage(
|
||||
title: l10n.s_slots,
|
||||
capabilities: const [Capability.otp],
|
||||
capability: Capability.otp,
|
||||
detailViewBuilder: selected != null
|
||||
? (context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -106,7 +106,7 @@ class _PivScreenState extends ConsumerState<PivScreen> {
|
||||
},
|
||||
child: AppPage(
|
||||
title: l10n.s_certificates,
|
||||
capabilities: const [Capability.piv],
|
||||
capability: Capability.piv,
|
||||
detailViewBuilder: selected != null
|
||||
? (context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
Loading…
Reference in New Issue
Block a user