mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-26 22:03:55 +03:00
AppPage improvements.
- Make AppPage content scrollable. - Add optional FAB (with extra padding for FAB). - Add bottomMenu.
This commit is contained in:
parent
2f13399b09
commit
40d616c8bd
@ -1,4 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'models.dart';
|
||||||
|
import 'state.dart';
|
||||||
|
|
||||||
ScaffoldFeatureController showMessage(
|
ScaffoldFeatureController showMessage(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
@ -14,3 +18,43 @@ ScaffoldFeatureController showMessage(
|
|||||||
width: narrow ? null : 400,
|
width: narrow ? null : 400,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showBottomMenu(
|
||||||
|
BuildContext context, List<MenuAction> actions) async {
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
constraints: MediaQuery.of(context).size.width > 540
|
||||||
|
? const BoxConstraints(maxWidth: 380)
|
||||||
|
: null,
|
||||||
|
builder: (context) => _BottomMenu(actions),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BottomMenu extends ConsumerWidget {
|
||||||
|
final List<MenuAction> actions;
|
||||||
|
const _BottomMenu(this.actions);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
// If current device changes, we need to pop back to the main Page.
|
||||||
|
ref.listen<DeviceNode?>(currentDeviceProvider, (previous, next) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: actions
|
||||||
|
.map((a) => ListTile(
|
||||||
|
leading: a.icon,
|
||||||
|
title: Text(a.text),
|
||||||
|
onTap: a.action == null
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
a.action?.call(context);
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -93,6 +93,9 @@ class DevicePath {
|
|||||||
int get hashCode => Object.hashAll(segments);
|
int get hashCode => Object.hashAll(segments);
|
||||||
|
|
||||||
String get key => segments.join('/');
|
String get key => segments.join('/');
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -9,13 +9,13 @@ class AppPage extends ConsumerWidget {
|
|||||||
final Widget? title;
|
final Widget? title;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Widget? floatingActionButton;
|
final Widget? floatingActionButton;
|
||||||
final void Function()? onBack;
|
final bool centered;
|
||||||
AppPage(
|
AppPage(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
this.title,
|
this.title,
|
||||||
required this.child,
|
required this.child,
|
||||||
this.onBack,
|
this.floatingActionButton,
|
||||||
this.floatingActionButton})
|
this.centered = false})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -45,21 +45,24 @@ class AppPage extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget _buildScrollView() => SingleChildScrollView(
|
||||||
|
// Make sure FAB doesn't block content
|
||||||
|
padding: floatingActionButton != null
|
||||||
|
? const EdgeInsets.only(bottom: 72)
|
||||||
|
: null,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
|
||||||
Scaffold _buildScaffold(BuildContext context, WidgetRef ref, bool hasDrawer) {
|
Scaffold _buildScaffold(BuildContext context, WidgetRef ref, bool hasDrawer) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: onBack != null
|
|
||||||
? BackButton(
|
|
||||||
onPressed: onBack,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
title: title,
|
title: title,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
actions: const [DeviceButton()],
|
actions: const [DeviceButton()],
|
||||||
),
|
),
|
||||||
drawer: hasDrawer ? const MainPageDrawer() : null,
|
drawer: hasDrawer ? const MainPageDrawer() : null,
|
||||||
body: child,
|
body: centered ? Center(child: _buildScrollView()) : _buildScrollView(),
|
||||||
floatingActionButton: floatingActionButton,
|
floatingActionButton: floatingActionButton,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,9 @@ class DeviceInfoScreen extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppPage(
|
return AppPage(
|
||||||
child: Center(
|
title: const Text('Coming soon!'),
|
||||||
child: Column(
|
centered: true,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: const Text('This page intentionally left blank (for now)'),
|
||||||
children: const [
|
|
||||||
Text('This page intentionally left blank (for now)'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class MainPage extends ConsumerWidget {
|
|||||||
|
|
||||||
switch (app) {
|
switch (app) {
|
||||||
case Application.oath:
|
case Application.oath:
|
||||||
return OathScreen(deviceData);
|
return OathScreen(deviceData.node.path);
|
||||||
case Application.management:
|
case Application.management:
|
||||||
return ManagementScreen(deviceData);
|
return ManagementScreen(deviceData);
|
||||||
case Application.fido:
|
case Application.fido:
|
||||||
|
@ -58,22 +58,21 @@ class NoDeviceScreen extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return AppPage(
|
return AppPage(
|
||||||
child: Center(
|
centered: true,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: node?.map(usbYubiKey: (node) {
|
children: node?.map(usbYubiKey: (node) {
|
||||||
return _buildUsbPid(context, ref, node.pid);
|
return _buildUsbPid(context, ref, node.pid);
|
||||||
}, nfcReader: (node) {
|
}, nfcReader: (node) {
|
||||||
return const [
|
return const [
|
||||||
DeviceAvatar(child: Icon(Icons.wifi)),
|
DeviceAvatar(child: Icon(Icons.wifi)),
|
||||||
Text('Place your YubiKey on the NFC reader'),
|
Text('Place your YubiKey on the NFC reader'),
|
||||||
];
|
];
|
||||||
}) ??
|
}) ??
|
||||||
const [
|
const [
|
||||||
DeviceAvatar(child: Icon(Icons.usb)),
|
DeviceAvatar(child: Icon(Icons.usb)),
|
||||||
Text('Insert your YubiKey'),
|
Text('Insert your YubiKey'),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user