Skip to content

Commit acaeb76

Browse files
authored
Add custom keybindings support (#993)
1 parent 20907b1 commit acaeb76

33 files changed

+735
-411
lines changed

app/lib/actions/background.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
import 'package:butterfly/bloc/document_bloc.dart';
22
import 'package:butterfly/dialogs/background/dialog.dart';
33
import 'package:flutter/material.dart';
4+
import 'package:flutter/services.dart';
45
import 'package:flutter_bloc/flutter_bloc.dart';
6+
import 'package:keybinder/keybinder.dart';
57

68
class BackgroundIntent extends Intent {
7-
final BuildContext context;
8-
9-
const BackgroundIntent(this.context);
9+
const BackgroundIntent();
1010
}
1111

12+
final backgroundShortcut = ShortcutDefinition(
13+
id: 'background',
14+
intent: const BackgroundIntent(),
15+
defaultActivator: const SingleActivator(
16+
LogicalKeyboardKey.keyB,
17+
control: true,
18+
),
19+
);
20+
1221
class BackgroundAction extends Action<BackgroundIntent> {
13-
BackgroundAction();
22+
final BuildContext context;
23+
24+
BackgroundAction(this.context);
1425

1526
@override
1627
Future<void> invoke(BackgroundIntent intent) {
1728
return showDialog<void>(
18-
context: intent.context,
29+
context: context,
1930
builder: (context) => BlocProvider.value(
20-
value: intent.context.read<DocumentBloc>(),
31+
value: this.context.read<DocumentBloc>(),
2132
child: const BackgroundDialog(),
2233
),
2334
);

app/lib/actions/change_path.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,29 @@ import 'package:butterfly/api/file_system.dart';
22
import 'package:butterfly/bloc/document_bloc.dart';
33
import 'package:butterfly/dialogs/file_system/move.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:flutter/services.dart';
56
import 'package:flutter_bloc/flutter_bloc.dart';
7+
import 'package:keybinder/keybinder.dart';
68

79
import '../cubits/settings.dart';
810

911
class ChangePathIntent extends Intent {
10-
final BuildContext context;
11-
12-
const ChangePathIntent(this.context);
12+
const ChangePathIntent();
1313
}
1414

15+
final changePathShortcut = ShortcutDefinition(
16+
id: 'change_path',
17+
intent: const ChangePathIntent(),
18+
defaultActivator: const SingleActivator(LogicalKeyboardKey.keyS, alt: true),
19+
);
20+
1521
class ChangePathAction extends Action<ChangePathIntent> {
16-
ChangePathAction();
22+
final BuildContext context;
23+
24+
ChangePathAction(this.context);
1725

1826
@override
1927
Future<void> invoke(ChangePathIntent intent) async {
20-
final context = intent.context;
2128
final bloc = context.read<DocumentBloc>();
2229
final state = bloc.state;
2330
if (state is! DocumentLoadSuccess || state.location.path == '') return;

app/lib/actions/change_tool.dart

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
11
import 'package:butterfly/cubits/current_index.dart';
22
import 'package:flutter/material.dart';
3+
import 'package:flutter/services.dart';
34
import 'package:flutter_bloc/flutter_bloc.dart';
5+
import 'package:keybinder/keybinder.dart';
46

57
import '../bloc/document_bloc.dart';
68

79
class ChangeToolIntent extends Intent {
8-
final BuildContext context;
910
final int index;
1011

11-
const ChangeToolIntent(this.context, this.index);
12+
const ChangeToolIntent(this.index);
1213
}
1314

15+
final changeToolShortcuts = List.generate(10, (index) {
16+
final key = [
17+
LogicalKeyboardKey.digit1,
18+
LogicalKeyboardKey.digit2,
19+
LogicalKeyboardKey.digit3,
20+
LogicalKeyboardKey.digit4,
21+
LogicalKeyboardKey.digit5,
22+
LogicalKeyboardKey.digit6,
23+
LogicalKeyboardKey.digit7,
24+
LogicalKeyboardKey.digit8,
25+
LogicalKeyboardKey.digit9,
26+
LogicalKeyboardKey.digit0,
27+
][index];
28+
return ShortcutDefinition(
29+
id: 'tool_$index',
30+
intent: ChangeToolIntent(index),
31+
defaultActivator: SingleActivator(key, control: true),
32+
);
33+
});
34+
1435
class ChangeToolAction extends Action<ChangeToolIntent> {
15-
ChangeToolAction();
36+
final BuildContext context;
37+
38+
ChangeToolAction(this.context);
1639

1740
@override
1841
Future<void> invoke(ChangeToolIntent intent) async {
19-
final bloc = intent.context.read<DocumentBloc>();
20-
intent.context.read<CurrentIndexCubit>().changeTool(
42+
final bloc = context.read<DocumentBloc>();
43+
context.read<CurrentIndexCubit>().changeTool(
2144
bloc,
22-
context: intent.context,
45+
context: context,
2346
index: intent.index,
2447
);
2548
}

app/lib/actions/color_palette.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import 'package:flutter/material.dart';
44
import 'package:flutter_bloc/flutter_bloc.dart';
55

66
class ColorPaletteIntent extends Intent {
7-
final BuildContext context;
8-
9-
const ColorPaletteIntent(this.context);
7+
const ColorPaletteIntent();
108
}
119

1210
class ColorPaletteAction extends Action<ColorPaletteIntent> {
13-
ColorPaletteAction();
11+
final BuildContext context;
12+
13+
ColorPaletteAction(this.context);
1414

1515
@override
1616
Future<void> invoke(ColorPaletteIntent intent) {
1717
return showDialog<void>(
18-
context: intent.context,
18+
context: context,
1919
builder: (ctx) => ColorPalettePickerDialog(
2020
viewMode: true,
21-
bloc: intent.context.read<DocumentBloc>(),
21+
bloc: context.read<DocumentBloc>(),
2222
),
2323
);
2424
}

app/lib/actions/exit.dart

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
import 'package:butterfly/bloc/document_bloc.dart';
22
import 'package:butterfly_api/butterfly_api.dart';
33
import 'package:flutter/material.dart';
4+
import 'package:flutter/services.dart';
45
import 'package:flutter_bloc/flutter_bloc.dart';
6+
import 'package:keybinder/keybinder.dart';
57

68
class ExitIntent extends Intent {
7-
final BuildContext context;
8-
9-
const ExitIntent(this.context);
9+
const ExitIntent();
1010
}
1111

12+
final exitShortcut = ShortcutDefinition(
13+
id: 'exit',
14+
intent: const ExitIntent(),
15+
defaultActivator: const SingleActivator(LogicalKeyboardKey.escape),
16+
);
17+
1218
class ExitAction extends Action<ExitIntent> {
13-
ExitAction();
19+
final BuildContext context;
20+
21+
ExitAction(this.context);
1422

1523
@override
1624
void invoke(ExitIntent intent) {
17-
final bloc = intent.context.read<DocumentBloc>();
25+
final bloc = context.read<DocumentBloc>();
1826
bloc.add(const PresentationModeExited());
1927
}
2028
}

app/lib/actions/export.dart

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,46 @@
11
import 'package:butterfly/api/save.dart';
22
import 'package:butterfly/bloc/document_bloc.dart';
33
import 'package:flutter/material.dart';
4+
import 'package:flutter/services.dart';
45
import 'package:flutter_bloc/flutter_bloc.dart';
6+
import 'package:keybinder/keybinder.dart';
57

68
class ExportIntent extends Intent {
7-
final BuildContext context;
89
final bool isText;
910

10-
const ExportIntent(this.context, {this.isText = false});
11+
const ExportIntent({this.isText = false});
1112
}
1213

14+
final exportShortcut = ShortcutDefinition(
15+
id: 'export',
16+
intent: const ExportIntent(),
17+
defaultActivator: const SingleActivator(
18+
LogicalKeyboardKey.keyE,
19+
control: true,
20+
),
21+
);
22+
23+
final exportTextShortcut = ShortcutDefinition(
24+
id: 'export_text',
25+
intent: const ExportIntent(isText: true),
26+
defaultActivator: const SingleActivator(
27+
LogicalKeyboardKey.keyE,
28+
control: true,
29+
shift: true,
30+
),
31+
);
32+
1333
class ExportAction extends Action<ExportIntent> {
14-
ExportAction();
34+
final BuildContext context;
35+
36+
ExportAction(this.context);
1537

1638
@override
1739
Future<void> invoke(ExportIntent intent) async {
18-
final bloc = intent.context.read<DocumentBloc>();
40+
final bloc = context.read<DocumentBloc>();
1941
final state = bloc.state;
2042
if (state is! DocumentLoaded) return;
2143
final data = (await state.saveData());
22-
exportData(intent.context, data, isTextBased: intent.isText);
44+
exportData(context, data, isTextBased: intent.isText);
2345
}
2446
}

app/lib/actions/full_screen.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
import 'package:keybinder/keybinder.dart';
24
import 'package:material_leap/material_leap.dart';
35

46
class FullScreenIntent extends Intent {
5-
final BuildContext context;
6-
7-
const FullScreenIntent(this.context);
7+
const FullScreenIntent();
88
}
99

10+
final fullScreenShortcut = ShortcutDefinition(
11+
id: 'full_screen',
12+
intent: const FullScreenIntent(),
13+
defaultActivator: const SingleActivator(LogicalKeyboardKey.f11),
14+
);
15+
1016
class FullScreenAction extends Action<FullScreenIntent> {
11-
FullScreenAction();
17+
final BuildContext context;
18+
19+
FullScreenAction(this.context);
1220

1321
@override
1422
Future<void> invoke(FullScreenIntent intent) async {

app/lib/actions/hide_ui.dart

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
import 'package:butterfly/cubits/current_index.dart';
22
import 'package:flutter/material.dart';
3+
import 'package:flutter/services.dart';
34
import 'package:flutter_bloc/flutter_bloc.dart';
5+
import 'package:keybinder/keybinder.dart';
46

57
class HideUIIntent extends Intent {
6-
final BuildContext context;
7-
8-
const HideUIIntent(this.context);
8+
const HideUIIntent();
99
}
1010

11+
final hideUIShortcut = ShortcutDefinition(
12+
id: 'hide_ui',
13+
intent: const HideUIIntent(),
14+
defaultActivator: const SingleActivator(LogicalKeyboardKey.f12),
15+
);
16+
1117
class HideUIAction extends Action<HideUIIntent> {
12-
HideUIAction();
18+
final BuildContext context;
19+
20+
HideUIAction(this.context);
1321

1422
@override
1523
void invoke(HideUIIntent intent) {
16-
intent.context.read<CurrentIndexCubit>().toggleKeyboardHideUI();
24+
context.read<CurrentIndexCubit>().toggleKeyboardHideUI();
1725
}
1826
}

app/lib/actions/image_export.dart

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,34 @@ import 'package:butterfly/bloc/document_bloc.dart';
22
import 'package:butterfly/cubits/transform.dart';
33
import 'package:butterfly/dialogs/export/general.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:flutter/services.dart';
56
import 'package:flutter_bloc/flutter_bloc.dart';
7+
import 'package:keybinder/keybinder.dart';
68

79
class ImageExportIntent extends Intent {
8-
final BuildContext context;
9-
10-
const ImageExportIntent(this.context);
10+
const ImageExportIntent();
1111
}
1212

13+
final imageExportShortcut = ShortcutDefinition(
14+
id: 'image_export',
15+
intent: const ImageExportIntent(),
16+
defaultActivator: const SingleActivator(
17+
LogicalKeyboardKey.keyE,
18+
control: true,
19+
alt: true,
20+
shift: true,
21+
),
22+
);
23+
1324
class ImageExportAction extends Action<ImageExportIntent> {
14-
ImageExportAction();
25+
final BuildContext context;
26+
27+
ImageExportAction(this.context);
1528

1629
@override
1730
Future<void> invoke(ImageExportIntent intent) async {
18-
var bloc = intent.context.read<DocumentBloc>();
19-
var transform = intent.context.read<TransformCubit>().state;
31+
var bloc = context.read<DocumentBloc>();
32+
var transform = context.read<TransformCubit>().state;
2033
return showDialog<void>(
2134
builder: (context) => BlocProvider.value(
2235
value: bloc,
@@ -25,7 +38,7 @@ class ImageExportAction extends Action<ImageExportIntent> {
2538
options: getDefaultImageExportOptions(context, transform: transform),
2639
),
2740
),
28-
context: intent.context,
41+
context: context,
2942
);
3043
}
3144
}

0 commit comments

Comments
 (0)