mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: some keys conflict with board shortcuts (#5460)
This commit is contained in:
parent
1e485188eb
commit
57d4652824
@ -14,6 +14,7 @@ import 'package:appflowy/plugins/database/tab_bar/tab_bar_view.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/card/card_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/card_cell_style_maps/desktop_board_card_cell_style.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/row_detail.dart';
|
||||
import 'package:appflowy/plugins/shared/callback_shortcuts.dart';
|
||||
import 'package:appflowy/shared/conditional_listenable_builder.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||
@ -28,6 +29,7 @@ import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||
import 'package:flutter/material.dart' hide Card;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../widgets/card/card.dart';
|
||||
import '../../widgets/cell/card_cell_builder.dart';
|
||||
@ -320,64 +322,67 @@ class _BoardContentState extends State<_BoardContent> {
|
||||
},
|
||||
),
|
||||
],
|
||||
child: FocusScope(
|
||||
autofocus: true,
|
||||
child: BoardShortcutContainer(
|
||||
focusScope: widget.focusScope,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: AppFlowyBoard(
|
||||
boardScrollController: scrollManager,
|
||||
scrollController: scrollController,
|
||||
controller: context.read<BoardBloc>().boardController,
|
||||
groupConstraints: const BoxConstraints.tightFor(width: 256),
|
||||
config: config,
|
||||
leading: HiddenGroupsColumn(margin: config.groupHeaderPadding),
|
||||
trailing: context
|
||||
.read<BoardBloc>()
|
||||
.groupingFieldType
|
||||
?.canCreateNewGroup ??
|
||||
false
|
||||
? BoardTrailing(scrollController: scrollController)
|
||||
: const HSpace(40),
|
||||
headerBuilder: (_, groupData) => BlocProvider<BoardBloc>.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
child: BoardColumnHeader(
|
||||
groupData: groupData,
|
||||
margin: config.groupHeaderPadding,
|
||||
child: Provider(
|
||||
create: (context) => AFCallbackShortcutsProvider(),
|
||||
child: FocusScope(
|
||||
autofocus: true,
|
||||
child: BoardShortcutContainer(
|
||||
focusScope: widget.focusScope,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: AppFlowyBoard(
|
||||
boardScrollController: scrollManager,
|
||||
scrollController: scrollController,
|
||||
controller: context.read<BoardBloc>().boardController,
|
||||
groupConstraints: const BoxConstraints.tightFor(width: 256),
|
||||
config: config,
|
||||
leading: HiddenGroupsColumn(margin: config.groupHeaderPadding),
|
||||
trailing: context
|
||||
.read<BoardBloc>()
|
||||
.groupingFieldType
|
||||
?.canCreateNewGroup ??
|
||||
false
|
||||
? BoardTrailing(scrollController: scrollController)
|
||||
: const HSpace(40),
|
||||
headerBuilder: (_, groupData) => BlocProvider<BoardBloc>.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
child: BoardColumnHeader(
|
||||
groupData: groupData,
|
||||
margin: config.groupHeaderPadding,
|
||||
),
|
||||
),
|
||||
),
|
||||
footerBuilder: (_, groupData) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
footerBuilder: (_, groupData) => MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
),
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardActionsCubit>(),
|
||||
),
|
||||
],
|
||||
child: BoardColumnFooter(
|
||||
columnData: groupData,
|
||||
boardConfig: config,
|
||||
scrollManager: scrollManager,
|
||||
),
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardActionsCubit>(),
|
||||
),
|
||||
],
|
||||
child: BoardColumnFooter(
|
||||
columnData: groupData,
|
||||
boardConfig: config,
|
||||
scrollManager: scrollManager,
|
||||
),
|
||||
),
|
||||
cardBuilder: (_, column, columnItem) => MultiBlocProvider(
|
||||
key: ValueKey("board_card_${column.id}_${columnItem.id}"),
|
||||
providers: [
|
||||
BlocProvider<BoardBloc>.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
cardBuilder: (_, column, columnItem) => MultiBlocProvider(
|
||||
key: ValueKey("board_card_${column.id}_${columnItem.id}"),
|
||||
providers: [
|
||||
BlocProvider<BoardBloc>.value(
|
||||
value: context.read<BoardBloc>(),
|
||||
),
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardActionsCubit>(),
|
||||
),
|
||||
],
|
||||
child: _BoardCard(
|
||||
afGroupData: column,
|
||||
groupItem: columnItem as GroupItem,
|
||||
boardConfig: config,
|
||||
notifier: widget.focusScope,
|
||||
cellBuilder: cellBuilder,
|
||||
),
|
||||
BlocProvider.value(
|
||||
value: context.read<BoardActionsCubit>(),
|
||||
),
|
||||
],
|
||||
child: _BoardCard(
|
||||
afGroupData: column,
|
||||
groupItem: columnItem as GroupItem,
|
||||
boardConfig: config,
|
||||
notifier: widget.focusScope,
|
||||
cellBuilder: cellBuilder,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -3,6 +3,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/database/board/application/board_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/field_type_extension.dart';
|
||||
import 'package:appflowy/plugins/shared/callback_shortcuts.dart';
|
||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||
import 'package:appflowy_board/appflowy_board.dart';
|
||||
@ -30,6 +31,8 @@ class BoardColumnHeader extends StatefulWidget {
|
||||
|
||||
class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final FocusNode _keyboardListenerFocusNode = FocusNode();
|
||||
late final AFCallbackShortcutsProvider _shortcutsProvider;
|
||||
|
||||
late final TextEditingController _controller =
|
||||
TextEditingController.fromValue(
|
||||
@ -44,16 +47,23 @@ class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_shortcutsProvider = context.read<AFCallbackShortcutsProvider>();
|
||||
_focusNode.addListener(() {
|
||||
if (!_focusNode.hasFocus) {
|
||||
_saveEdit();
|
||||
}
|
||||
});
|
||||
_keyboardListenerFocusNode.addListener(() {
|
||||
_shortcutsProvider.isShortcutsEnabled.value =
|
||||
!_keyboardListenerFocusNode.hasFocus;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_shortcutsProvider.isShortcutsEnabled.value = true;
|
||||
_focusNode.dispose();
|
||||
_keyboardListenerFocusNode.dispose();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@ -149,7 +159,7 @@ class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
||||
Widget _buildTextField(BuildContext context) {
|
||||
return Expanded(
|
||||
child: KeyboardListener(
|
||||
focusNode: FocusNode(),
|
||||
focusNode: _keyboardListenerFocusNode,
|
||||
onKeyEvent: (event) {
|
||||
if ([LogicalKeyboardKey.enter, LogicalKeyboardKey.escape]
|
||||
.contains(event.logicalKey)) {
|
||||
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:appflowy/plugins/database/board/application/board_actions_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/board/application/board_bloc.dart';
|
||||
import 'package:appflowy/plugins/shared/callback_shortcuts.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -20,7 +21,9 @@ class BoardShortcutContainer extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CallbackShortcuts(
|
||||
return AFCallbackShortcuts(
|
||||
canAcceptEvent: (_, __) =>
|
||||
context.read<AFCallbackShortcutsProvider>().isShortcutsEnabled.value,
|
||||
bindings: {
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp):
|
||||
focusScope.focusPrevious,
|
||||
@ -93,9 +96,9 @@ class BoardShortcutContainer extends StatelessWidget {
|
||||
if (focusScope.value.length != 1) {
|
||||
return;
|
||||
}
|
||||
context
|
||||
.read<BoardActionsCubit>()
|
||||
.openCardWithRowId(focusScope.value.first.rowId);
|
||||
context
|
||||
.read<BoardActionsCubit>()
|
||||
.openCardWithRowId(focusScope.value.first.rowId);
|
||||
}
|
||||
|
||||
void _shitEnterHandler(BuildContext context) {
|
||||
|
@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class AFCallbackShortcutsProvider {
|
||||
final ValueNotifier<bool> isShortcutsEnabled = ValueNotifier(true);
|
||||
}
|
||||
|
||||
class AFCallbackShortcuts extends StatelessWidget {
|
||||
const AFCallbackShortcuts({
|
||||
super.key,
|
||||
required this.bindings,
|
||||
required this.canAcceptEvent,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
final Map<ShortcutActivator, VoidCallback> bindings;
|
||||
final bool Function(FocusNode node, KeyEvent event) canAcceptEvent;
|
||||
final Widget child;
|
||||
|
||||
bool _applyKeyEventBinding(ShortcutActivator activator, KeyEvent event) {
|
||||
if (activator.accepts(event, HardwareKeyboard.instance)) {
|
||||
bindings[activator]!.call();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Focus(
|
||||
canRequestFocus: false,
|
||||
skipTraversal: true,
|
||||
onKeyEvent: (FocusNode node, KeyEvent event) {
|
||||
if (!canAcceptEvent(node, event)) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
KeyEventResult result = KeyEventResult.ignored;
|
||||
for (final ShortcutActivator activator in bindings.keys) {
|
||||
result = _applyKeyEventBinding(activator, event)
|
||||
? KeyEventResult.handled
|
||||
: result;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user