Add and use showMessage for SnackBars.

This commit is contained in:
Dain Nilsson 2022-03-25 15:43:32 +01:00
parent 53699612f4
commit 4b5ea2fdd7
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
16 changed files with 63 additions and 160 deletions

View File

@ -7,6 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'app/logging.dart'; import 'app/logging.dart';
import 'app/message.dart';
import 'app/views/responsive_dialog.dart'; import 'app/views/responsive_dialog.dart';
import 'core/state.dart'; import 'core/state.dart';
import 'desktop/state.dart'; import 'desktop/state.dart';
@ -42,12 +43,7 @@ class AboutPage extends ConsumerWidget {
final data = response['diagnostics']; final data = response['diagnostics'];
final text = const JsonEncoder.withIndent(' ').convert(data); final text = const JsonEncoder.withIndent(' ').convert(data);
await Clipboard.setData(ClipboardData(text: text)); await Clipboard.setData(ClipboardData(text: text));
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Diagnostic data copied to clipboard');
const SnackBar(
content: Text('Diagnostic data copied to clipboard'),
duration: Duration(seconds: 2),
),
);
}, },
child: const Text('Run diagnostics...'), child: const Text('Run diagnostics...'),
), ),
@ -79,12 +75,7 @@ class LoggingPanel extends ConsumerWidget {
onChanged: (level) { onChanged: (level) {
ref.read(logLevelProvider.notifier).setLogLevel(level!); ref.read(logLevelProvider.notifier).setLogLevel(level!);
_log.config('Log level set to $level'); _log.config('Log level set to $level');
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Log level set to $level');
SnackBar(
content: Text('Log level set to $level'),
duration: const Duration(seconds: 2),
),
);
}, },
), ),
const SizedBox(width: 8.0), const SizedBox(width: 8.0),
@ -94,12 +85,7 @@ class LoggingPanel extends ConsumerWidget {
_log.info('Copying log to clipboard...'); _log.info('Copying log to clipboard...');
final logs = LogBuffer.of(context).getLogs().join('\n'); final logs = LogBuffer.of(context).getLogs().join('\n');
await Clipboard.setData(ClipboardData(text: logs)); await Clipboard.setData(ClipboardData(text: logs));
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Log copied to clipboard');
const SnackBar(
content: Text('Log copied to clipboard'),
duration: Duration(seconds: 2),
),
);
}, },
), ),
], ],

15
lib/app/message.dart Executable file
View File

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
ScaffoldFeatureController showMessage(
BuildContext context,
String message, {
Duration duration = const Duration(seconds: 1),
}) {
final width = MediaQuery.of(context).size.width;
return ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message),
duration: duration,
behavior: SnackBarBehavior.floating,
width: width < 540 ? null : 400,
));
}

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
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 '../../app/message.dart';
import '../state.dart'; import '../state.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../../fido/models.dart'; import '../../fido/models.dart';
@ -89,12 +90,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
}, onError: (error, stacktrace) { }, onError: (error, stacktrace) {
_log.severe('Error adding fingerprint', error, stacktrace); _log.severe('Error adding fingerprint', error, stacktrace);
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Error adding fingerprint');
const SnackBar(
content: Text('Error adding fingerprint'),
duration: Duration(seconds: 2),
),
);
}); });
} }
@ -180,12 +176,7 @@ class _AddFingerprintDialogState extends ConsumerState<AddFingerprintDialog>
.read(fingerprintProvider(widget.node.path).notifier) .read(fingerprintProvider(widget.node.path).notifier)
.renameFingerprint(_fingerprint!, _label); .renameFingerprint(_fingerprint!, _label);
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Fingerprint added');
const SnackBar(
content: Text('Fingerprint added'),
duration: Duration(seconds: 2),
),
);
} }
: null, : null,
child: const Text('Save'), child: const Text('Save'),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
@ -43,12 +44,7 @@ class DeleteCredentialDialog extends ConsumerWidget {
.read(credentialProvider(device.path).notifier) .read(credentialProvider(device.path).notifier)
.deleteCredential(credential); .deleteCredential(credential);
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Credential deleted');
const SnackBar(
content: Text('Credential deleted'),
duration: Duration(seconds: 2),
),
);
}, },
child: const Text('Delete'), child: const Text('Delete'),
), ),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
@ -43,12 +44,7 @@ class DeleteFingerprintDialog extends ConsumerWidget {
.read(fingerprintProvider(device.path).notifier) .read(fingerprintProvider(device.path).notifier)
.deleteFingerprint(fingerprint); .deleteFingerprint(fingerprint);
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Fingerprint deleted');
const SnackBar(
content: Text('Fingerprint deleted'),
duration: Duration(seconds: 2),
),
);
}, },
child: const Text('Delete'), child: const Text('Delete'),
), ),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/state.dart'; import '../../app/state.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
@ -121,12 +122,7 @@ class _FidoPinDialogState extends ConsumerState<FidoPinDialog> {
.setPin(_newPin, oldPin: oldPin); .setPin(_newPin, oldPin: oldPin);
result.when(success: () { result.when(success: () {
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'PIN set');
const SnackBar(
content: Text('PIN set'),
duration: Duration(seconds: 2),
),
);
}, failed: (retries, authBlocked) { }, failed: (retries, authBlocked) {
setState(() { setState(() {
if (authBlocked) { if (authBlocked) {

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
@ -72,12 +73,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameFingerprintDialog> {
.read(fingerprintProvider(widget.device.path).notifier) .read(fingerprintProvider(widget.device.path).notifier)
.renameFingerprint(fingerprint, _label); .renameFingerprint(fingerprint, _label);
Navigator.of(context).pop(renamed); Navigator.of(context).pop(renamed);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Fingerprint renamed');
const SnackBar(
content: Text('Fingerprint renamed'),
duration: Duration(seconds: 2),
),
);
} }
: null, : null,
child: const Text('Save'), child: const Text('Save'),

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
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 '../../app/message.dart';
import '../../core/models.dart'; import '../../core/models.dart';
import '../state.dart'; import '../state.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
@ -90,21 +91,11 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
}, onDone: () { }, onDone: () {
_subscription = null; _subscription = null;
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'FIDO application reset');
const SnackBar(
content: Text('FIDO application reset'),
duration: Duration(seconds: 2),
),
);
}, onError: (e) { }, onError: (e) {
_log.severe('Error performing FIDO reset', e); _log.severe('Error performing FIDO reset', e);
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Error performing reset');
const SnackBar(
content: Text('Error performing reset'),
duration: Duration(seconds: 2),
),
);
}); });
} }
: null, : null,

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import '../../app/message.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/state.dart'; import '../../app/state.dart';
import '../../app/views/app_failure_screen.dart'; import '../../app/views/app_failure_screen.dart';
@ -193,12 +194,11 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
try { try {
if (reboot) { if (reboot) {
// This will take longer, show a message // This will take longer, show a message
close = ScaffoldMessenger.of(context) close = showMessage(
.showSnackBar(const SnackBar( context,
content: Text('Reconfiguring YubiKey...'), 'Reconfiguring YubiKey...',
duration: Duration(seconds: 8), duration: const Duration(seconds: 8),
)) ).close;
.close;
} }
await ref await ref
.read(managementStateProvider(widget.deviceData.node.path).notifier) .read(managementStateProvider(widget.deviceData.node.path).notifier)
@ -207,10 +207,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
.copyWith(enabledCapabilities: _enabled), .copyWith(enabledCapabilities: _enabled),
reboot: reboot, reboot: reboot,
); );
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( showMessage(context, 'Configuration updated');
content: Text('Configuration updated'),
duration: Duration(seconds: 2),
));
} finally { } finally {
close?.call(); close?.call();
} }
@ -221,10 +218,7 @@ class _ManagementScreenState extends ConsumerState<ManagementScreen> {
UsbInterfaces.forCapabilites( UsbInterfaces.forCapabilites(
info.config.enabledCapabilities[Transport.usb] ?? 0), info.config.enabledCapabilities[Transport.usb] ?? 0),
onSubmit: (enabledInterfaces) { onSubmit: (enabledInterfaces) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar( showMessage(context, 'Not yet implemented!');
content: Text('Not yet implemented!'),
duration: Duration(seconds: 1),
));
}); });
@override @override

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../app/message.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/state.dart'; import '../../app/state.dart';
import '../models.dart'; import '../models.dart';
@ -92,23 +93,13 @@ mixin AccountMixin {
Future<OathCode> calculateCode(BuildContext context, WidgetRef ref) async { Future<OathCode> calculateCode(BuildContext context, WidgetRef ref) async {
Function? close; Function? close;
if (credential.touchRequired) { if (credential.touchRequired) {
close = ScaffoldMessenger.of(context) close = showMessage(context, 'Touch your YubiKey',
.showSnackBar( duration: const Duration(seconds: 30))
const SnackBar(
content: Text('Touch your YubiKey'),
duration: Duration(seconds: 30),
),
)
.close; .close;
} else if (credential.oathType == OathType.hotp) { } else if (credential.oathType == OathType.hotp) {
final showPrompt = Timer(const Duration(milliseconds: 500), () { final showPrompt = Timer(const Duration(milliseconds: 500), () {
close = ScaffoldMessenger.of(context) close = showMessage(context, 'Touch your YubiKey',
.showSnackBar( duration: const Duration(seconds: 30))
const SnackBar(
content: Text('Touch your YubiKey'),
duration: Duration(seconds: 30),
),
)
.close; .close;
}); });
close = showPrompt.cancel; close = showPrompt.cancel;
@ -129,12 +120,7 @@ mixin AccountMixin {
final code = getCode(ref); final code = getCode(ref);
if (code != null) { if (code != null) {
Clipboard.setData(ClipboardData(text: code.value)); Clipboard.setData(ClipboardData(text: code.value));
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Code copied to clipboard');
const SnackBar(
content: Text('Code copied to clipboard'),
duration: Duration(seconds: 2),
),
);
} }
} }
@ -189,12 +175,7 @@ mixin AccountMixin {
? null ? null
: (context) { : (context) {
Clipboard.setData(ClipboardData(text: code.value)); Clipboard.setData(ClipboardData(text: code.value));
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Code copied to clipboard');
const SnackBar(
content: Text('Code copied to clipboard'),
duration: Duration(seconds: 2),
),
);
}, },
), ),
MenuAction( MenuAction(

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../app/message.dart';
import '../../app/state.dart'; import '../../app/state.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
@ -322,12 +323,7 @@ class _OathAddAccountPageState extends ConsumerState<OathAddAccountPage> {
credentialListProvider(widget.device.path).notifier) credentialListProvider(widget.device.path).notifier)
.addAccount(cred.toUri(), requireTouch: _touch); .addAccount(cred.toUri(), requireTouch: _touch);
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Account added');
const SnackBar(
content: Text('Account added'),
duration: Duration(seconds: 2),
),
);
} else { } else {
setState(() { setState(() {
_validateSecretLength = true; _validateSecretLength = true;

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
@ -50,12 +51,7 @@ class DeleteAccountDialog extends ConsumerWidget {
.read(credentialListProvider(device.path).notifier) .read(credentialListProvider(device.path).notifier)
.deleteAccount(credential); .deleteAccount(credential);
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Account deleted');
const SnackBar(
content: Text('Account deleted'),
duration: Duration(seconds: 2),
),
);
}, },
child: const Text('Delete'), child: const Text('Delete'),
), ),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/state.dart'; import '../../app/state.dart';
@ -66,12 +67,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
.unsetPassword(_currentPassword); .unsetPassword(_currentPassword);
if (result) { if (result) {
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Password removed');
const SnackBar(
content: Text('Password removed'),
duration: Duration(seconds: 2),
),
);
} else { } else {
setState(() { setState(() {
_currentIsWrong = true; _currentIsWrong = true;
@ -88,12 +84,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
.read(oathStateProvider(widget.path).notifier) .read(oathStateProvider(widget.path).notifier)
.forgetPassword(); .forgetPassword();
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Password forgotten');
const SnackBar(
content: Text('Password forgotten'),
duration: Duration(seconds: 2),
),
);
}, },
), ),
], ],
@ -149,12 +140,7 @@ class _ManagePasswordDialogState extends ConsumerState<ManagePasswordDialog> {
.setPassword(_currentPassword, _newPassword); .setPassword(_currentPassword, _newPassword);
if (result) { if (result) {
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Password set');
const SnackBar(
content: Text('Password set'),
duration: Duration(seconds: 2),
),
);
} else { } else {
setState(() { setState(() {
_currentIsWrong = true; _currentIsWrong = true;

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:yubico_authenticator/oath/models.dart'; import 'package:yubico_authenticator/oath/models.dart';
import '../../app/message.dart';
import '../../app/models.dart'; import '../../app/models.dart';
import '../../app/views/app_failure_screen.dart'; import '../../app/views/app_failure_screen.dart';
import '../../app/views/app_loading_screen.dart'; import '../../app/views/app_loading_screen.dart';
@ -29,19 +30,9 @@ class OathScreen extends ConsumerWidget {
oathStateProvider(deviceData.node.path).notifier) oathStateProvider(deviceData.node.path).notifier)
.unlock(password, remember: remember); .unlock(password, remember: remember);
if (!result.first) { if (!result.first) {
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Wrong password');
const SnackBar(
content: Text('Wrong password'),
duration: Duration(seconds: 1),
),
);
} else if (remember && !result.second) { } else if (remember && !result.second) {
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Failed to remember password');
const SnackBar(
content: Text('Failed to remember password'),
duration: Duration(seconds: 1),
),
);
} }
}, },
), ),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../models.dart'; import '../models.dart';
import '../state.dart'; import '../state.dart';
@ -107,12 +108,7 @@ class _RenameAccountDialogState extends ConsumerState<RenameAccountDialog> {
.renameAccount(credential, .renameAccount(credential,
_issuer.isNotEmpty ? _issuer : null, _account); _issuer.isNotEmpty ? _issuer : null, _account);
Navigator.of(context).pop(renamed); Navigator.of(context).pop(renamed);
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'Account renamed');
const SnackBar(
content: Text('Account renamed'),
duration: Duration(seconds: 2),
),
);
} }
: null, : null,
child: const Text('Save'), child: const Text('Save'),

View File

@ -1,6 +1,7 @@
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 '../../app/message.dart';
import '../../app/views/responsive_dialog.dart'; import '../../app/views/responsive_dialog.dart';
import '../state.dart'; import '../state.dart';
import '../../app/models.dart'; import '../../app/models.dart';
@ -39,12 +40,7 @@ class ResetDialog extends ConsumerWidget {
onPressed: () async { onPressed: () async {
await ref.read(oathStateProvider(device.path).notifier).reset(); await ref.read(oathStateProvider(device.path).notifier).reset();
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( showMessage(context, 'OATH application reset');
const SnackBar(
content: Text('OATH application reset'),
duration: Duration(seconds: 2),
),
);
}, },
child: const Text('Reset'), child: const Text('Reset'),
), ),