From d7bf271bd0f3daa58defe076a8aaf3bba39339c5 Mon Sep 17 00:00:00 2001 From: joahyan Date: Tue, 19 Jul 2022 20:16:48 +0800 Subject: [PATCH] add shortcuts --- example/lib/main.dart | 13 ++ example/lib/pages/home_page.dart | 5 +- lib/src/widgets/editor.dart | 25 ++-- lib/src/widgets/shortcuts/edit_shortcuts.dart | 129 ++++++++++++++++++ lib/src/widgets/toolbar/emoji_button.dart | 7 +- .../widgets/toolbar/toggle_style_button.dart | 1 + 6 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 lib/src/widgets/shortcuts/edit_shortcuts.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 5b4feb2b..ad60c095 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,9 +1,22 @@ +/* + * @Author: joahyan joahyan@163.com + * @Date: 2022-07-18 10:10:08 + * @LastEditors: joahyan joahyan@163.com + * @LastEditTime: 2022-07-19 10:16:42 + * @FilePath: \flutter-quill\example\lib\main.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'pages/home_page.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); + if (Platform.isMacOS) { + + } runApp(MyApp()); } diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index e0857ca5..4c3c7202 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -71,6 +71,7 @@ class _HomePageState extends State { body: RawKeyboardListener( focusNode: FocusNode(), onKey: (event) { + // print(event); if (event.data.isControlPressed && event.character == 'b') { if (_controller! .getSelectionStyle() @@ -84,7 +85,9 @@ class _HomePageState extends State { } } }, - child: _buildWelcomeEditor(context), + child: + // GridEditShortcuts + _buildWelcomeEditor(context), ), ); } diff --git a/lib/src/widgets/editor.dart b/lib/src/widgets/editor.dart index 74faf5b6..445ed1ec 100644 --- a/lib/src/widgets/editor.dart +++ b/lib/src/widgets/editor.dart @@ -22,6 +22,7 @@ import 'embeds/default_embed_builder.dart'; import 'float_cursor.dart'; import 'link.dart'; import 'raw_editor.dart'; +import 'shortcuts/edit_shortcuts.dart'; import 'text_selection.dart'; /// Base interface for the editor state which defines contract used by @@ -468,21 +469,21 @@ class QuillEditorState extends State initialLocale: widget.locale, child: _selectionGestureDetectorBuilder.build( behavior: HitTestBehavior.translucent, - child: child, + child: GridEditShortcuts(child: child,controller: widget.controller,), )); if (kIsWeb) { - // Intercept RawKeyEvent on Web to prevent it from propagating to parents - // that might interfere with the editor key behavior, such as - // SingleChildScrollView. Thanks to @wliumelb for the workaround. - // See issue https://github.com/singerdmx/flutter-quill/issues/304 - return RawKeyboardListener( - onKey: (_) {}, - focusNode: FocusNode( - onKey: (node, event) => KeyEventResult.skipRemainingHandlers, - ), - child: editor, - ); + // Intercept RawKeyEvent on Web to prevent it from propagating to parents + // that might interfere with the editor key behavior, such as + // SingleChildScrollView. Thanks to @wliumelb for the workaround. + // See issue https://github.com/singerdmx/flutter-quill/issues/304 + return RawKeyboardListener( + onKey: (_) {}, + focusNode: FocusNode( + onKey: (node, event) => KeyEventResult.skipRemainingHandlers, + ), + child: editor, + ); } return editor; diff --git a/lib/src/widgets/shortcuts/edit_shortcuts.dart b/lib/src/widgets/shortcuts/edit_shortcuts.dart new file mode 100644 index 00000000..504a112d --- /dev/null +++ b/lib/src/widgets/shortcuts/edit_shortcuts.dart @@ -0,0 +1,129 @@ +/* + * @Author: joahyan joahyan@163.com + * @Date: 2022-07-19 14:26:22 + * @LastEditors: joahyan joahyan@163.com + * @LastEditTime: 2022-07-19 17:05:52 + * @FilePath: \flutter-quill\lib\src\widgets\shortcuts\edit_shortcuts.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../../flutter_quill.dart'; + +typedef EditKeyboardAction = dynamic Function(); + +enum EditKeyboardKey { + onEnter, + onOverstriking, + onRecover, +} + +abstract class EditShortcuts extends Widget { + const EditShortcuts({Key? key}) : super(key: key); + + Map get shortcutHandlers; +} + +class GridEditShortcuts extends StatelessWidget { + final Widget child; + final QuillController controller; + + LogicalKeyboardKey controlKey = + Platform.isMacOS ? LogicalKeyboardKey.meta : LogicalKeyboardKey.control; + + GridEditShortcuts({ + required this.child, + required this.controller, + }); + + @override + Widget build(BuildContext context) { + return Shortcuts( + shortcuts: { + // Ctrl + B + LogicalKeySet( + controlKey, + LogicalKeyboardKey.keyB, + ): const OverstrikingIntent(), + // Ctrl + Z + LogicalKeySet( + controlKey, + LogicalKeyboardKey.keyZ, + ): const RecoverIntent(), + // Ctrl + Alt + Z + LogicalKeySet( + controlKey, + LogicalKeyboardKey.alt, + LogicalKeyboardKey.keyZ, + ): const UnRecoverIntent(), + }, + child: Actions( + actions: { + OverstrikingIntent: OverstrikingAction(controller: controller), + RecoverIntent: RecoverAction(controller: controller), + UnRecoverIntent: UnRecoverAction(controller: controller), + }, + child: child, + ), + ); + } +} + +// 加粗 +class OverstrikingIntent extends Intent { + const OverstrikingIntent(); +} + +class OverstrikingAction extends Action { + OverstrikingAction({required this.controller}); + + final QuillController controller; + @override + void invoke(covariant OverstrikingIntent intent) { + if (controller.getSelectionStyle().attributes.keys.contains('bold')) { + controller.formatSelection(Attribute.clone(Attribute.bold, null)); + } else { + controller.formatSelection(Attribute.bold); + } + } +} + +// 恢复 +class RecoverIntent extends Intent { + const RecoverIntent(); +} + +class RecoverAction extends Action { + RecoverAction({required this.controller}); + + final QuillController controller; + + @override + void invoke(covariant RecoverIntent intent) { + if (controller.hasUndo) { + controller.undo(); + } + } +} + +// 恢复反操作 +class UnRecoverIntent extends Intent { + const UnRecoverIntent(); +} + +class UnRecoverAction extends Action { + UnRecoverAction({required this.controller}); + + final QuillController controller; + + @override + void invoke(covariant UnRecoverIntent intent) { + if (controller.hasRedo) { + controller.redo(); + } + } +} diff --git a/lib/src/widgets/toolbar/emoji_button.dart b/lib/src/widgets/toolbar/emoji_button.dart index 7b087183..d737e6e7 100644 --- a/lib/src/widgets/toolbar/emoji_button.dart +++ b/lib/src/widgets/toolbar/emoji_button.dart @@ -2,7 +2,7 @@ * @Author: joahyan joahyan@163.com * @Date: 2022-07-18 12:34:30 * @LastEditors: joahyan joahyan@163.com - * @LastEditTime: 2022-07-18 16:39:08 + * @LastEditTime: 2022-07-19 16:41:46 * @FilePath: \flutter-quill\lib\src\widgets\toolbar\emoji_button.dart * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -102,10 +102,7 @@ class _EmojiButtonState extends State { Widget build(BuildContext context) { return QuillIconButton( icon: Icon(widget.icon, size: widget.iconSize), - onPressed: () { - _showEmojiDialog(); - print('aa'); - }, + onPressed: _showEmojiDialog, ); } } diff --git a/lib/src/widgets/toolbar/toggle_style_button.dart b/lib/src/widgets/toolbar/toggle_style_button.dart index 0b654deb..e8af1338 100644 --- a/lib/src/widgets/toolbar/toggle_style_button.dart +++ b/lib/src/widgets/toolbar/toggle_style_button.dart @@ -108,6 +108,7 @@ class _ToggleStyleButtonState extends State { widget.controller.formatSelection(_isToggled! ? Attribute.clone(widget.attribute, null) : widget.attribute); + print(widget.controller.document.toDelta().toJson()); } }