From 1a83cb65eda8d678178893e7f0b8e1833d53b223 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 4 Jun 2022 11:04:43 +0800 Subject: [PATCH 1/3] chore: click enter to exist edit state --- .../plugins/grid/src/grid_page.dart | 3 +- .../grid/src/widgets/cell/cell_accessory.dart | 6 +- .../grid/src/widgets/cell/cell_builder.dart | 27 +++++---- .../grid/src/widgets/cell/cell_shortcuts.dart | 47 +++++++++++++++ .../grid/src/widgets/cell/text_cell.dart | 1 + .../grid/src/widgets/row/row_detail.dart | 2 +- .../plugins/grid/src/widgets/shortcuts.dart | 58 +++++++++++++++++++ 7 files changed, 128 insertions(+), 16 deletions(-) create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart create mode 100644 frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/shortcuts.dart diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index b8591895e8..19c94817d8 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -15,6 +15,7 @@ import 'layout/sizes.dart'; import 'widgets/row/grid_row.dart'; import 'widgets/footer/grid_footer.dart'; import 'widgets/header/grid_header.dart'; +import 'widgets/shortcuts.dart'; import 'widgets/toolbar/grid_toolbar.dart'; class GridPage extends StatefulWidget { @@ -40,7 +41,7 @@ class _GridPageState extends State { return state.loadingState.map( loading: (_) => const Center(child: CircularProgressIndicator.adaptive()), finish: (result) => result.successOrFail.fold( - (_) => const FlowyGrid(), + (_) => const GridShortcuts(child: FlowyGrid()), (err) => FlowyErrorPage(err.toString()), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart index 41e22b8b98..bfd0a38909 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart @@ -18,8 +18,8 @@ abstract class GridCellAccessory implements Widget { typedef AccessoryBuilder = List Function(GridCellAccessoryBuildContext buildContext); -abstract class AccessoryWidget extends Widget { - const AccessoryWidget({Key? key}) : super(key: key); +abstract class CellAccessory extends Widget { + const CellAccessory({Key? key}) : super(key: key); // The hover will show if the onFocus's value is true ValueNotifier? get isFocus; @@ -28,7 +28,7 @@ abstract class AccessoryWidget extends Widget { } class AccessoryHover extends StatefulWidget { - final AccessoryWidget child; + final CellAccessory child; final EdgeInsets contentPadding; const AccessoryHover({ required this.child, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 05708e6198..894eed2ac8 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -8,6 +8,7 @@ import 'package:provider/provider.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:styled_widget/styled_widget.dart'; import 'cell_accessory.dart'; +import 'cell_shortcuts.dart'; import 'checkbox_cell.dart'; import 'date_cell/date_cell.dart'; import 'number_cell.dart'; @@ -48,7 +49,7 @@ class BlankCell extends StatelessWidget { } } -abstract class GridCellWidget extends StatefulWidget implements AccessoryWidget, CellContainerFocustable { +abstract class GridCellWidget extends StatefulWidget implements CellAccessory, CellFocustable, CellShortcuts { GridCellWidget({Key? key}) : super(key: key); @override @@ -58,27 +59,30 @@ abstract class GridCellWidget extends StatefulWidget implements AccessoryWidget, List Function(GridCellAccessoryBuildContext buildContext)? get accessoryBuilder => null; @override - final GridCellRequestBeginFocus requestBeginFocus = GridCellRequestBeginFocus(); + final GridCellFocusListener beginFocus = GridCellFocusListener(); + + @override + final Map keyboardActionHandlers = {}; } abstract class GridCellState extends State { @override void initState() { - widget.requestBeginFocus.setListener(() => requestBeginFocus()); + widget.beginFocus.setListener(() => requestBeginFocus()); super.initState(); } @override void didUpdateWidget(covariant T oldWidget) { if (oldWidget != this) { - widget.requestBeginFocus.setListener(() => requestBeginFocus()); + widget.beginFocus.setListener(() => requestBeginFocus()); } super.didUpdateWidget(oldWidget); } @override void dispose() { - widget.requestBeginFocus.removeAllListener(); + widget.beginFocus.removeAllListener(); super.dispose(); } @@ -90,6 +94,7 @@ abstract class GridFocusNodeCellState extends GridCell @override void initState() { + widget.keyboardActionHandlers[CellKeyboardKey.onEnter] = () => focusNode.unfocus(); _listenOnFocusNodeChanged(); super.initState(); } @@ -104,6 +109,7 @@ abstract class GridFocusNodeCellState extends GridCell @override void dispose() { + widget.keyboardActionHandlers.remove(CellKeyboardKey.onEnter); focusNode.removeAllListener(); focusNode.dispose(); super.dispose(); @@ -127,7 +133,7 @@ abstract class GridFocusNodeCellState extends GridCell Future focusChanged() async {} } -class GridCellRequestBeginFocus extends ChangeNotifier { +class GridCellFocusListener extends ChangeNotifier { VoidCallback? _listener; void setListener(VoidCallback listener) { @@ -194,9 +200,8 @@ class CellStateNotifier extends ChangeNotifier { bool get onEnter => _onEnter; } -abstract class CellContainerFocustable { - // Listen on the requestBeginFocus if the - GridCellRequestBeginFocus get requestBeginFocus; +abstract class CellFocustable { + GridCellFocusListener get beginFocus; } class CellContainer extends StatelessWidget { @@ -220,7 +225,7 @@ class CellContainer extends StatelessWidget { child: Selector( selector: (context, notifier) => notifier.isFocus, builder: (context, isFocus, _) { - Widget container = Center(child: child); + Widget container = Center(child: GridCellShortcuts(child: child)); child.isFocus.addListener(() { Provider.of(context, listen: false).isFocus = child.isFocus.value; }); @@ -235,7 +240,7 @@ class CellContainer extends StatelessWidget { return GestureDetector( behavior: HitTestBehavior.translucent, - onTap: () => child.requestBeginFocus.notify(), + onTap: () => child.beginFocus.notify(), child: Container( constraints: BoxConstraints(maxWidth: width, minHeight: 46), decoration: _makeBoxDecoration(context, isFocus), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart new file mode 100644 index 0000000000..7c122f17ba --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +typedef CellKeyboardAction = VoidCallback; + +enum CellKeyboardKey { + onEnter, +} + +abstract class CellShortcuts extends Widget { + const CellShortcuts({Key? key}) : super(key: key); + + Map get keyboardActionHandlers; +} + +class GridCellShortcuts extends StatelessWidget { + final CellShortcuts child; + const GridCellShortcuts({required this.child, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Shortcuts( + shortcuts: {LogicalKeySet(LogicalKeyboardKey.enter): const GridCellEnterIdent()}, + child: Actions( + actions: {GridCellEnterIdent: GridCellEnterAction(child: child)}, + child: child, + ), + ); + } +} + +class GridCellEnterIdent extends Intent { + const GridCellEnterIdent(); +} + +class GridCellEnterAction extends Action { + final CellShortcuts child; + GridCellEnterAction({required this.child}); + + @override + void invoke(covariant GridCellEnterIdent intent) { + final callback = child.keyboardActionHandlers[CellKeyboardKey.onEnter]; + if (callback != null) { + callback(); + } + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index 7e1333fff0..6a9fcde98f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -43,6 +43,7 @@ class _GridTextCellState extends GridFocusNodeCellState { _cellBloc = getIt(param1: cellContext); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); + super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index fbff4665d9..719e0082fb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -154,7 +154,7 @@ class _RowDetailCell extends StatelessWidget { final gesture = GestureDetector( behavior: HitTestBehavior.translucent, - onTap: () => cell.requestBeginFocus.notify(), + onTap: () => cell.beginFocus.notify(), child: AccessoryHover( child: cell, contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/shortcuts.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/shortcuts.dart new file mode 100644 index 0000000000..1e38c5647d --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/shortcuts.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class GridShortcuts extends StatelessWidget { + final Widget child; + const GridShortcuts({required this.child, Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Shortcuts( + shortcuts: bindKeys([]), + child: Actions( + dispatcher: LoggingActionDispatcher(), + actions: const {}, + child: child, + ), + ); + } +} + +Map bindKeys(List keys) { + return {for (var key in keys) LogicalKeySet(key): KeyboardKeyIdent(key)}; +} + +Map> bindActions() { + return { + KeyboardKeyIdent: KeyboardBindingAction(), + }; +} + +class KeyboardKeyIdent extends Intent { + final KeyboardKey key; + + const KeyboardKeyIdent(this.key); +} + +class KeyboardBindingAction extends Action { + KeyboardBindingAction(); + + @override + void invoke(covariant KeyboardKeyIdent intent) { + // print(intent); + } +} + +class LoggingActionDispatcher extends ActionDispatcher { + @override + Object? invokeAction( + covariant Action action, + covariant Intent intent, [ + BuildContext? context, + ]) { + // print('Action invoked: $action($intent) from $context'); + super.invokeAction(action, intent, context); + + return null; + } +} From bb22ca5d93138b7347c54c89a94cfae808a6ee9a Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 4 Jun 2022 11:44:38 +0800 Subject: [PATCH 2/3] chore: copy cell content --- .../grid/src/widgets/cell/cell_builder.dart | 6 +- .../grid/src/widgets/cell/cell_shortcuts.dart | 59 +++++++++++++++++-- .../grid/src/widgets/cell/checkbox_cell.dart | 9 ++- .../src/widgets/cell/date_cell/date_cell.dart | 2 + .../grid/src/widgets/cell/number_cell.dart | 4 ++ .../grid/src/widgets/cell/text_cell.dart | 2 + .../src/widgets/cell/url_cell/url_cell.dart | 3 + 7 files changed, 76 insertions(+), 9 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 894eed2ac8..9a1911f003 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -62,7 +62,7 @@ abstract class GridCellWidget extends StatefulWidget implements CellAccessory, C final GridCellFocusListener beginFocus = GridCellFocusListener(); @override - final Map keyboardActionHandlers = {}; + final Map shortcutHandlers = {}; } abstract class GridCellState extends State { @@ -94,7 +94,7 @@ abstract class GridFocusNodeCellState extends GridCell @override void initState() { - widget.keyboardActionHandlers[CellKeyboardKey.onEnter] = () => focusNode.unfocus(); + widget.shortcutHandlers[CellKeyboardKey.onEnter] = () => focusNode.unfocus(); _listenOnFocusNodeChanged(); super.initState(); } @@ -109,7 +109,7 @@ abstract class GridFocusNodeCellState extends GridCell @override void dispose() { - widget.keyboardActionHandlers.remove(CellKeyboardKey.onEnter); + widget.shortcutHandlers.clear(); focusNode.removeAllListener(); focusNode.dispose(); super.dispose(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart index 7c122f17ba..2146c939d2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart @@ -1,16 +1,18 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -typedef CellKeyboardAction = VoidCallback; +typedef CellKeyboardAction = dynamic Function(); enum CellKeyboardKey { onEnter, + onCopy, + onInsert, } abstract class CellShortcuts extends Widget { const CellShortcuts({Key? key}) : super(key: key); - Map get keyboardActionHandlers; + Map get shortcutHandlers; } class GridCellShortcuts extends StatelessWidget { @@ -20,9 +22,17 @@ class GridCellShortcuts extends StatelessWidget { @override Widget build(BuildContext context) { return Shortcuts( - shortcuts: {LogicalKeySet(LogicalKeyboardKey.enter): const GridCellEnterIdent()}, + shortcuts: { + LogicalKeySet(LogicalKeyboardKey.enter): const GridCellEnterIdent(), + LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyC): const GridCellCopyIntent(), + LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyV): const GridCellInsertIntent(), + }, child: Actions( - actions: {GridCellEnterIdent: GridCellEnterAction(child: child)}, + actions: { + GridCellEnterIdent: GridCellEnterAction(child: child), + GridCellCopyIntent: GridCellCopyAction(child: child), + GridCellInsertIntent: GridCellInsertAction(child: child), + }, child: child, ), ); @@ -39,7 +49,46 @@ class GridCellEnterAction extends Action { @override void invoke(covariant GridCellEnterIdent intent) { - final callback = child.keyboardActionHandlers[CellKeyboardKey.onEnter]; + final callback = child.shortcutHandlers[CellKeyboardKey.onEnter]; + if (callback != null) { + callback(); + } + } +} + +class GridCellCopyIntent extends Intent { + const GridCellCopyIntent(); +} + +class GridCellCopyAction extends Action { + final CellShortcuts child; + GridCellCopyAction({required this.child}); + + @override + void invoke(covariant GridCellCopyIntent intent) { + final callback = child.shortcutHandlers[CellKeyboardKey.onCopy]; + if (callback == null) { + return; + } + + final s = callback(); + if (s is String) { + Clipboard.setData(ClipboardData(text: s)); + } + } +} + +class GridCellInsertIntent extends Intent { + const GridCellInsertIntent(); +} + +class GridCellInsertAction extends Action { + final CellShortcuts child; + GridCellInsertAction({required this.child}); + + @override + void invoke(covariant GridCellInsertIntent intent) { + final callback = child.shortcutHandlers[CellKeyboardKey.onEnter]; if (callback != null) { callback(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 6f22a7d977..21f44bf2ab 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -5,6 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; +import 'cell_shortcuts.dart'; class CheckboxCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; @@ -24,7 +25,13 @@ class _CheckboxCellState extends GridCellState { void initState() { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const CheckboxCellEvent.initial()); - + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () { + if (_cellBloc.state.isSelected) { + return "Yes"; + } else { + return "No"; + } + }; super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index eed45464bf..ecc297e4c4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -45,6 +46,7 @@ class _DateCellState extends State { void initState() { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const DateCellEvent.initial()); + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.dateStr; super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 88aaf5cb3b..3983a7d3c3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; +import 'cell_shortcuts.dart'; class NumberCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; @@ -29,6 +30,9 @@ class _NumberCellState extends GridFocusNodeCellState { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () { + return _cellBloc.state.content.fold((content) => content, (r) => null); + }; super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index 6a9fcde98f..48b5628bbd 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'cell_builder.dart'; +import 'cell_shortcuts.dart'; class GridTextCellStyle extends GridCellStyle { String? placeholder; @@ -44,6 +45,7 @@ class _GridTextCellState extends GridFocusNodeCellState { _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.content; super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart index 5caa014df0..4b4e671901 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart @@ -3,6 +3,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/workspace/application/grid/cell/url_cell_bloc.dart'; import 'package:app_flowy/workspace/presentation/home/toast.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -86,6 +87,8 @@ class _GridURLCellState extends GridCellState { final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; _cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc.add(const URLCellEvent.initial()); + + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.content; super.initState(); } From a9a75230a26c7f05ca031495f5dfccb99075e818 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 4 Jun 2022 14:05:04 +0800 Subject: [PATCH 3/3] chore: insert cell content --- .../application/grid/cell/url_cell_bloc.dart | 4 ++++ .../grid/src/widgets/cell/cell_builder.dart | 14 ++++++++++++++ .../grid/src/widgets/cell/cell_shortcuts.dart | 2 +- .../grid/src/widgets/cell/checkbox_cell.dart | 17 +++++++++-------- .../src/widgets/cell/date_cell/date_cell.dart | 12 ++++++++---- .../grid/src/widgets/cell/number_cell.dart | 15 ++++++++++----- .../grid/src/widgets/cell/text_cell.dart | 11 ++++++++--- .../src/widgets/cell/url_cell/cell_editor.dart | 10 +++++++++- .../src/widgets/cell/url_cell/url_cell.dart | 18 +++++++++++++----- 9 files changed, 76 insertions(+), 27 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart index 609c625001..e1fe39c3bf 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart @@ -24,6 +24,9 @@ class URLCellBloc extends Bloc { url: cellData?.url ?? "", )); }, + updateURL: (String url) { + cellContext.saveCellData(url, deduplicate: true); + }, ); }, ); @@ -53,6 +56,7 @@ class URLCellBloc extends Bloc { @freezed class URLCellEvent with _$URLCellEvent { const factory URLCellEvent.initial() = _InitialCell; + const factory URLCellEvent.updateURL(String url) = _UpdateURL; const factory URLCellEvent.didReceiveCellUpdate(URLCellData? cell) = _DidReceiveCellUpdate; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 9a1911f003..8bfab28f65 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType; +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart'; import 'package:flowy_infra/theme.dart'; @@ -69,6 +70,15 @@ abstract class GridCellState extends State { @override void initState() { widget.beginFocus.setListener(() => requestBeginFocus()); + widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => onCopy(); + widget.shortcutHandlers[CellKeyboardKey.onInsert] = () { + Clipboard.getData("text/plain").then((data) { + final s = data?.text; + if (s is String) { + onInsert(s); + } + }); + }; super.initState(); } @@ -87,6 +97,10 @@ abstract class GridCellState extends State { } void requestBeginFocus(); + + String? onCopy() => null; + + void onInsert(String value) {} } abstract class GridFocusNodeCellState extends GridCellState { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart index 2146c939d2..f4f222f219 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart @@ -88,7 +88,7 @@ class GridCellInsertAction extends Action { @override void invoke(covariant GridCellInsertIntent intent) { - final callback = child.shortcutHandlers[CellKeyboardKey.onEnter]; + final callback = child.shortcutHandlers[CellKeyboardKey.onInsert]; if (callback != null) { callback(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 21f44bf2ab..384d85737f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -5,7 +5,6 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; -import 'cell_shortcuts.dart'; class CheckboxCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; @@ -25,13 +24,6 @@ class _CheckboxCellState extends GridCellState { void initState() { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const CheckboxCellEvent.initial()); - widget.shortcutHandlers[CellKeyboardKey.onCopy] = () { - if (_cellBloc.state.isSelected) { - return "Yes"; - } else { - return "No"; - } - }; super.initState(); } @@ -66,4 +58,13 @@ class _CheckboxCellState extends GridCellState { void requestBeginFocus() { _cellBloc.add(const CheckboxCellEvent.select()); } + + @override + String? onCopy() { + if (_cellBloc.state.isSelected) { + return "Yes"; + } else { + return "No"; + } + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index ecc297e4c4..eb382a0971 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -1,4 +1,3 @@ -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -36,17 +35,16 @@ class DateCell extends GridCellWidget { } @override - State createState() => _DateCellState(); + GridCellState createState() => _DateCellState(); } -class _DateCellState extends State { +class _DateCellState extends GridCellState { late DateCellBloc _cellBloc; @override void initState() { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const DateCellEvent.initial()); - widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.dateStr; super.initState(); } @@ -91,4 +89,10 @@ class _DateCellState extends State { _cellBloc.close(); super.dispose(); } + + @override + void requestBeginFocus() {} + + @override + String? onCopy() => _cellBloc.state.dateStr; } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 3983a7d3c3..7d16b16ef0 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -1,12 +1,10 @@ import 'dart:async'; - import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; -import 'cell_shortcuts.dart'; class NumberCell extends GridCellWidget { final GridCellContextBuilder cellContextBuilder; @@ -30,9 +28,6 @@ class _NumberCellState extends GridFocusNodeCellState { final cellContext = widget.cellContextBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); - widget.shortcutHandlers[CellKeyboardKey.onCopy] = () { - return _cellBloc.state.content.fold((content) => content, (r) => null); - }; super.initState(); } @@ -85,4 +80,14 @@ class _NumberCellState extends GridFocusNodeCellState { String contentFromState(NumberCellState state) { return state.content.fold((l) => l, (r) => ""); } + + @override + String? onCopy() { + return _cellBloc.state.content.fold((content) => content, (r) => null); + } + + @override + void onInsert(String value) { + _cellBloc.add(NumberCellEvent.updateCell(value)); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index 48b5628bbd..1bece5a3d7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -4,7 +4,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'cell_builder.dart'; -import 'cell_shortcuts.dart'; class GridTextCellStyle extends GridCellStyle { String? placeholder; @@ -44,8 +43,6 @@ class _GridTextCellState extends GridFocusNodeCellState { _cellBloc = getIt(param1: cellContext); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); - - widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.content; super.initState(); } @@ -95,4 +92,12 @@ class _GridTextCellState extends GridFocusNodeCellState { }); } } + + @override + String? onCopy() => _cellBloc.state.content; + + @override + void onInsert(String value) { + _cellBloc.add(TextCellEvent.updateText(value)); + } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart index 15af124749..f4da18be86 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart @@ -8,7 +8,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { final GridURLCellContext cellContext; - const URLCellEditor({required this.cellContext, Key? key}) : super(key: key); + final VoidCallback completed; + const URLCellEditor({required this.cellContext, required this.completed, Key? key}) : super(key: key); @override State createState() => _URLCellEditorState(); @@ -16,10 +17,12 @@ class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { static void show( BuildContext context, GridURLCellContext cellContext, + VoidCallback completed, ) { FlowyOverlay.of(context).remove(identifier()); final editor = URLCellEditor( cellContext: cellContext, + completed: completed, ); // @@ -46,6 +49,11 @@ class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { bool asBarrier() { return true; } + + @override + void didRemove() { + completed(); + } } class _URLCellEditorState extends State { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart index 4b4e671901..b3e9c3c919 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart @@ -3,7 +3,6 @@ import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:app_flowy/workspace/application/grid/cell/url_cell_bloc.dart'; import 'package:app_flowy/workspace/presentation/home/toast.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_accessory.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/cell_shortcuts.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -87,8 +86,6 @@ class _GridURLCellState extends GridCellState { final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; _cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc.add(const URLCellEvent.initial()); - - widget.shortcutHandlers[CellKeyboardKey.onCopy] = () => _cellBloc.state.content; super.initState(); } @@ -134,10 +131,13 @@ class _GridURLCellState extends GridCellState { Future _openUrlOrEdit(String url) async { final uri = Uri.parse(url); if (url.isNotEmpty && await canLaunchUrl(uri)) { + widget.isFocus.value = false; await launchUrl(uri); } else { final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; - URLCellEditor.show(context, cellContext); + URLCellEditor.show(context, cellContext, () { + widget.isFocus.value = false; + }); } } @@ -145,6 +145,14 @@ class _GridURLCellState extends GridCellState { void requestBeginFocus() { _openUrlOrEdit(_cellBloc.state.url); } + + @override + String? onCopy() => _cellBloc.state.content; + + @override + void onInsert(String value) { + _cellBloc.add(URLCellEvent.updateURL(value)); + } } class _EditURLAccessory extends StatelessWidget with GridCellAccessory { @@ -164,7 +172,7 @@ class _EditURLAccessory extends StatelessWidget with GridCellAccessory { @override void onTap() { - URLCellEditor.show(anchorContext, cellContext); + URLCellEditor.show(anchorContext, cellContext, () {}); } }