Keyboard shortcuts
This commit is contained in:
parent
9a67ce6c17
commit
5da257b390
|
|
@ -10,33 +10,15 @@ class AppBuilder extends StatefulWidget {
|
|||
|
||||
static AppBuilderState of(BuildContext context) {
|
||||
return context.findAncestorStateOfType<AppBuilderState>();
|
||||
//return context.ancestorStateOfType(const TypeMatcher<AppBuilderState>());
|
||||
}
|
||||
}
|
||||
|
||||
class AppBuilderState extends State<AppBuilder> {
|
||||
FocusNode _focusNode;
|
||||
String _command = '';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_focusNode = new FocusNode();
|
||||
_focusNode.requestFocus(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void rebuild() {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void runCommand(BuildContext context) {
|
||||
print('### RUN COMMAND: $_command ###');
|
||||
/*
|
||||
final store = StoreProvider.of<AppState>(context);
|
||||
final company = store.state.company;
|
||||
|
|
@ -120,22 +102,6 @@ class AppBuilderState extends State<AppBuilder> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RawKeyboardListener(
|
||||
child: widget.builder(context),
|
||||
focusNode: _focusNode,
|
||||
onKey: (event) {
|
||||
if (kReleaseMode) {
|
||||
return;
|
||||
}
|
||||
_command = '';
|
||||
/*
|
||||
_command += event.logicalKey.keyLabel;
|
||||
print(
|
||||
'onKey: ${event.logicalKey.keyLabel}, hasFoucs: ${_focusNode.hasFocus}, hasPrimaryFocus: ${_focusNode.hasPrimaryFocus}');
|
||||
runCommand(context);
|
||||
Timer(Duration(seconds: 1), () => _command = '');
|
||||
*/
|
||||
},
|
||||
);
|
||||
return widget.builder(context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:invoiceninja_flutter/data/models/entities.dart';
|
||||
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
|
||||
|
||||
class AppShortcuts extends StatefulWidget {
|
||||
const AppShortcuts({Key key, this.child}) : super(key: key);
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
AppShortcutsState createState() => new AppShortcutsState();
|
||||
|
||||
static AppShortcutsState of(BuildContext context) {
|
||||
return context.findAncestorStateOfType<AppShortcutsState>();
|
||||
}
|
||||
}
|
||||
|
||||
class AppShortcutsState extends State<AppShortcuts> {
|
||||
final _shortcuts = <LogicalKeySet, _ShortcutIntent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyI):
|
||||
_ShortcutIntent.create(EntityType.invoice),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyI):
|
||||
_ShortcutIntent.list(EntityType.invoice),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyC):
|
||||
_ShortcutIntent.create(EntityType.client),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyC):
|
||||
_ShortcutIntent.list(EntityType.client),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyT):
|
||||
_ShortcutIntent.create(EntityType.task),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyT):
|
||||
_ShortcutIntent.list(EntityType.task),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyE):
|
||||
_ShortcutIntent.create(EntityType.expense),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyE):
|
||||
_ShortcutIntent.list(EntityType.expense),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyP):
|
||||
_ShortcutIntent.create(EntityType.payment),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyP):
|
||||
_ShortcutIntent.list(EntityType.payment),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyN, LogicalKeyboardKey.keyQ):
|
||||
_ShortcutIntent.create(EntityType.quote),
|
||||
LogicalKeySet(LogicalKeyboardKey.keyL, LogicalKeyboardKey.keyQ):
|
||||
_ShortcutIntent.list(EntityType.quote),
|
||||
if (!kIsWeb)
|
||||
LogicalKeySet(LogicalKeyboardKey.alt, LogicalKeyboardKey.arrowLeft):
|
||||
_ShortcutIntent.back(),
|
||||
};
|
||||
|
||||
void rebuild() {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _actions = <Type, Action<Intent>>{
|
||||
_ShortcutIntent: CallbackAction<_ShortcutIntent>(
|
||||
onInvoke: (_ShortcutIntent intent) {
|
||||
switch (intent.intentType) {
|
||||
case _ShortcutIntentType.create:
|
||||
createEntityByType(
|
||||
context: context, entityType: intent.entityType);
|
||||
break;
|
||||
case _ShortcutIntentType.list:
|
||||
viewEntitiesByType(
|
||||
context: context, entityType: intent.entityType);
|
||||
break;
|
||||
case _ShortcutIntentType.back:
|
||||
Navigator.of(context).maybePop();
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
return widget.child;
|
||||
|
||||
return FocusableActionDetector(
|
||||
child: widget.child,
|
||||
actions: _actions,
|
||||
shortcuts: _shortcuts,
|
||||
autofocus: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ShortcutIntent extends Intent {
|
||||
const _ShortcutIntent({this.intentType, this.entityType});
|
||||
|
||||
const _ShortcutIntent.create(this.entityType)
|
||||
: intentType = _ShortcutIntentType.create;
|
||||
|
||||
const _ShortcutIntent.list(this.entityType)
|
||||
: intentType = _ShortcutIntentType.list;
|
||||
|
||||
const _ShortcutIntent.back()
|
||||
: intentType = _ShortcutIntentType.back,
|
||||
entityType = null;
|
||||
|
||||
final _ShortcutIntentType intentType;
|
||||
final EntityType entityType;
|
||||
}
|
||||
|
||||
enum _ShortcutIntentType {
|
||||
create,
|
||||
back,
|
||||
list,
|
||||
}
|
||||
|
|
@ -56,7 +56,8 @@ class EditScaffold extends StatelessWidget {
|
|||
onSavePressed: (context) {
|
||||
// Clear focus now to prevent un-focus after save from
|
||||
// marking the form as changed and to hide the keyboard
|
||||
FocusScope.of(context).unfocus();
|
||||
FocusScope.of(context).unfocus(
|
||||
disposition: UnfocusDisposition.previouslyFocusedChild);
|
||||
|
||||
onSavePressed(context);
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ class _ListFilterState extends State<ListFilter> {
|
|||
),
|
||||
onPressed: () {
|
||||
_filterController.text = '';
|
||||
_focusNode.unfocus();
|
||||
_focusNode.unfocus(
|
||||
disposition: UnfocusDisposition.previouslyFocusedChild);
|
||||
widget.onFilterChanged(null);
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:invoiceninja_flutter/redux/dashboard/dashboard_actions.dart';
|
|||
import 'package:invoiceninja_flutter/redux/reports/reports_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/settings/settings_actions.dart';
|
||||
import 'package:invoiceninja_flutter/redux/ui/pref_state.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/app_shortcuts.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/blank_screen.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/change_layout_banner.dart';
|
||||
import 'package:invoiceninja_flutter/ui/app/history_drawer_vm.dart';
|
||||
|
|
@ -324,20 +325,22 @@ class MainScreen extends StatelessWidget {
|
|||
|
||||
return false;
|
||||
},
|
||||
child: SafeArea(
|
||||
child: FocusTraversalGroup(
|
||||
policy: WidgetOrderTraversalPolicy(),
|
||||
child: ChangeLayoutBanner(
|
||||
appLayout: prefState.appLayout,
|
||||
suggestedLayout: AppLayout.desktop,
|
||||
child: Row(children: <Widget>[
|
||||
if (prefState.showMenu) MenuDrawerBuilder(),
|
||||
Expanded(
|
||||
child: AppBorder(
|
||||
child: screen,
|
||||
isLeft: prefState.showMenu,
|
||||
)),
|
||||
]),
|
||||
child: AppShortcuts(
|
||||
child: SafeArea(
|
||||
child: FocusTraversalGroup(
|
||||
policy: WidgetOrderTraversalPolicy(),
|
||||
child: ChangeLayoutBanner(
|
||||
appLayout: prefState.appLayout,
|
||||
suggestedLayout: AppLayout.desktop,
|
||||
child: Row(children: <Widget>[
|
||||
if (prefState.showMenu) MenuDrawerBuilder(),
|
||||
Expanded(
|
||||
child: AppBorder(
|
||||
child: screen,
|
||||
isLeft: prefState.showMenu,
|
||||
)),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in New Issue