mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: board shortcuts conflict with textfield (#5487)
* fix: board shortcuts conflict with text field * fix: typo * fix: favorite icon issue in dark mode
This commit is contained in:
parent
bb3e9d5bd8
commit
38d2bd7ee8
@ -14,7 +14,6 @@ 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/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/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/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/shared/conditional_listenable_builder.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
@ -29,7 +28,6 @@ import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
|||||||
import 'package:flutter/material.dart' hide Card;
|
import 'package:flutter/material.dart' hide Card;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
import '../../widgets/card/card.dart';
|
import '../../widgets/card/card.dart';
|
||||||
import '../../widgets/cell/card_cell_builder.dart';
|
import '../../widgets/cell/card_cell_builder.dart';
|
||||||
@ -322,67 +320,64 @@ class _BoardContentState extends State<_BoardContent> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: Provider(
|
child: FocusScope(
|
||||||
create: (context) => AFCallbackShortcutsProvider(),
|
autofocus: true,
|
||||||
child: FocusScope(
|
child: BoardShortcutContainer(
|
||||||
autofocus: true,
|
focusScope: widget.focusScope,
|
||||||
child: BoardShortcutContainer(
|
child: Padding(
|
||||||
focusScope: widget.focusScope,
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
child: Padding(
|
child: AppFlowyBoard(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
boardScrollController: scrollManager,
|
||||||
child: AppFlowyBoard(
|
scrollController: scrollController,
|
||||||
boardScrollController: scrollManager,
|
controller: context.read<BoardBloc>().boardController,
|
||||||
scrollController: scrollController,
|
groupConstraints: const BoxConstraints.tightFor(width: 256),
|
||||||
controller: context.read<BoardBloc>().boardController,
|
config: config,
|
||||||
groupConstraints: const BoxConstraints.tightFor(width: 256),
|
leading: HiddenGroupsColumn(margin: config.groupHeaderPadding),
|
||||||
config: config,
|
trailing: context
|
||||||
leading: HiddenGroupsColumn(margin: config.groupHeaderPadding),
|
.read<BoardBloc>()
|
||||||
trailing: context
|
.groupingFieldType
|
||||||
.read<BoardBloc>()
|
?.canCreateNewGroup ??
|
||||||
.groupingFieldType
|
false
|
||||||
?.canCreateNewGroup ??
|
? BoardTrailing(scrollController: scrollController)
|
||||||
false
|
: const HSpace(40),
|
||||||
? BoardTrailing(scrollController: scrollController)
|
headerBuilder: (_, groupData) => BlocProvider<BoardBloc>.value(
|
||||||
: const HSpace(40),
|
value: context.read<BoardBloc>(),
|
||||||
headerBuilder: (_, groupData) => BlocProvider<BoardBloc>.value(
|
child: BoardColumnHeader(
|
||||||
value: context.read<BoardBloc>(),
|
groupData: groupData,
|
||||||
child: BoardColumnHeader(
|
margin: config.groupHeaderPadding,
|
||||||
groupData: groupData,
|
|
||||||
margin: config.groupHeaderPadding,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
footerBuilder: (_, groupData) => MultiBlocProvider(
|
),
|
||||||
providers: [
|
footerBuilder: (_, groupData) => MultiBlocProvider(
|
||||||
BlocProvider.value(
|
providers: [
|
||||||
value: context.read<BoardBloc>(),
|
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}"),
|
cardBuilder: (_, column, columnItem) => MultiBlocProvider(
|
||||||
providers: [
|
key: ValueKey("board_card_${column.id}_${columnItem.id}"),
|
||||||
BlocProvider<BoardBloc>.value(
|
providers: [
|
||||||
value: context.read<BoardBloc>(),
|
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,7 +3,6 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/plugins/database/board/application/board_bloc.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/layout/sizes.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/widgets/header/field_type_extension.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/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:appflowy_board/appflowy_board.dart';
|
import 'package:appflowy_board/appflowy_board.dart';
|
||||||
@ -32,7 +31,6 @@ class BoardColumnHeader extends StatefulWidget {
|
|||||||
class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
||||||
final FocusNode _focusNode = FocusNode();
|
final FocusNode _focusNode = FocusNode();
|
||||||
final FocusNode _keyboardListenerFocusNode = FocusNode();
|
final FocusNode _keyboardListenerFocusNode = FocusNode();
|
||||||
late final AFCallbackShortcutsProvider _shortcutsProvider;
|
|
||||||
|
|
||||||
late final TextEditingController _controller =
|
late final TextEditingController _controller =
|
||||||
TextEditingController.fromValue(
|
TextEditingController.fromValue(
|
||||||
@ -47,21 +45,15 @@ class _BoardColumnHeaderState extends State<BoardColumnHeader> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_shortcutsProvider = context.read<AFCallbackShortcutsProvider>();
|
|
||||||
_focusNode.addListener(() {
|
_focusNode.addListener(() {
|
||||||
if (!_focusNode.hasFocus) {
|
if (!_focusNode.hasFocus) {
|
||||||
_saveEdit();
|
_saveEdit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_keyboardListenerFocusNode.addListener(() {
|
|
||||||
_shortcutsProvider.isShortcutsEnabled.value =
|
|
||||||
!_keyboardListenerFocusNode.hasFocus;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_shortcutsProvider.isShortcutsEnabled.value = true;
|
|
||||||
_focusNode.dispose();
|
_focusNode.dispose();
|
||||||
_keyboardListenerFocusNode.dispose();
|
_keyboardListenerFocusNode.dispose();
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
|
@ -39,14 +39,14 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void focusNext() {
|
bool focusNext() {
|
||||||
_deepCopy();
|
_deepCopy();
|
||||||
|
|
||||||
// if no card is focused, focus on the first card in the board
|
// if no card is focused, focus on the first card in the board
|
||||||
if (_focusedCards.isEmpty) {
|
if (_focusedCards.isEmpty) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final lastFocusedCard = _focusedCards.last;
|
final lastFocusedCard = _focusedCards.last;
|
||||||
@ -58,7 +58,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (iterable == null || iterable.isEmpty) {
|
if (iterable == null || iterable.isEmpty) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iterable.length == 1) {
|
if (iterable.length == 1) {
|
||||||
@ -90,16 +90,18 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void focusPrevious() {
|
bool focusPrevious() {
|
||||||
_deepCopy();
|
_deepCopy();
|
||||||
|
|
||||||
// if no card is focused, focus on the last card in the board
|
// if no card is focused, focus on the last card in the board
|
||||||
if (_focusedCards.isEmpty) {
|
if (_focusedCards.isEmpty) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final lastFocusedCard = _focusedCards.last;
|
final lastFocusedCard = _focusedCards.last;
|
||||||
@ -111,7 +113,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (iterable == null || iterable.isEmpty) {
|
if (iterable == null || iterable.isEmpty) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iterable.length == 1) {
|
if (iterable.length == 1) {
|
||||||
@ -143,16 +145,18 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustRangeDown() {
|
bool adjustRangeDown() {
|
||||||
_deepCopy();
|
_deepCopy();
|
||||||
|
|
||||||
// if no card is focused, focus on the first card in the board
|
// if no card is focused, focus on the first card in the board
|
||||||
if (_focusedCards.isEmpty) {
|
if (_focusedCards.isEmpty) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final firstFocusedCard = _focusedCards.first;
|
final firstFocusedCard = _focusedCards.first;
|
||||||
@ -171,7 +175,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (firstGroupIndex == -1 || lastGroupIndex == -1) {
|
if (firstGroupIndex == -1 || lastGroupIndex == -1) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstGroupIndex < lastGroupIndex) {
|
if (firstGroupIndex < lastGroupIndex) {
|
||||||
@ -189,7 +193,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (firstCardIndex == -1 || lastCardIndex == -1) {
|
if (firstCardIndex == -1 || lastCardIndex == -1) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isExpand = firstCardIndex < lastCardIndex;
|
isExpand = firstCardIndex < lastCardIndex;
|
||||||
@ -203,7 +207,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (groupController == null) {
|
if (groupController == null) {
|
||||||
_focusFirstCard();
|
_focusFirstCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final iterable = groupController.items
|
final iterable = groupController.items
|
||||||
@ -236,16 +240,17 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustRangeUp() {
|
bool adjustRangeUp() {
|
||||||
_deepCopy();
|
_deepCopy();
|
||||||
|
|
||||||
// if no card is focused, focus on the first card in the board
|
// if no card is focused, focus on the first card in the board
|
||||||
if (_focusedCards.isEmpty) {
|
if (_focusedCards.isEmpty) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final firstFocusedCard = _focusedCards.first;
|
final firstFocusedCard = _focusedCards.first;
|
||||||
@ -264,7 +269,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (firstGroupIndex == -1 || lastGroupIndex == -1) {
|
if (firstGroupIndex == -1 || lastGroupIndex == -1) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstGroupIndex < lastGroupIndex) {
|
if (firstGroupIndex < lastGroupIndex) {
|
||||||
@ -282,7 +287,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (firstCardIndex == -1 || lastCardIndex == -1) {
|
if (firstCardIndex == -1 || lastCardIndex == -1) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isExpand = firstCardIndex > lastCardIndex;
|
isExpand = firstCardIndex > lastCardIndex;
|
||||||
@ -296,7 +301,7 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
if (groupController == null) {
|
if (groupController == null) {
|
||||||
_focusLastCard();
|
_focusLastCard();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final iterable = groupController.items.reversed
|
final iterable = groupController.items.reversed
|
||||||
@ -329,12 +334,15 @@ class BoardFocusScope extends ChangeNotifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
bool clear() {
|
||||||
_deepCopy();
|
_deepCopy();
|
||||||
_focusedCards.clear();
|
_focusedCards.clear();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _focusFirstCard() {
|
void _focusFirstCard() {
|
||||||
|
@ -22,56 +22,7 @@ class BoardShortcutContainer extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AFCallbackShortcuts(
|
return AFCallbackShortcuts(
|
||||||
canAcceptEvent: (_, __) =>
|
bindings: _shortcutBindings(context),
|
||||||
context.read<AFCallbackShortcutsProvider>().isShortcutsEnabled.value,
|
|
||||||
bindings: {
|
|
||||||
const SingleActivator(LogicalKeyboardKey.arrowUp):
|
|
||||||
focusScope.focusPrevious,
|
|
||||||
const SingleActivator(LogicalKeyboardKey.arrowDown):
|
|
||||||
focusScope.focusNext,
|
|
||||||
const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true):
|
|
||||||
focusScope.adjustRangeUp,
|
|
||||||
const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true):
|
|
||||||
focusScope.adjustRangeDown,
|
|
||||||
const SingleActivator(LogicalKeyboardKey.escape): focusScope.clear,
|
|
||||||
const SingleActivator(LogicalKeyboardKey.keyE): () {
|
|
||||||
if (focusScope.value.length != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context
|
|
||||||
.read<BoardActionsCubit>()
|
|
||||||
.startEditingRow(focusScope.value.first);
|
|
||||||
},
|
|
||||||
const SingleActivator(LogicalKeyboardKey.keyN): () {
|
|
||||||
if (focusScope.value.length != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context
|
|
||||||
.read<BoardActionsCubit>()
|
|
||||||
.startCreateBottomRow(focusScope.value.first.groupId);
|
|
||||||
focusScope.clear();
|
|
||||||
},
|
|
||||||
const SingleActivator(LogicalKeyboardKey.delete): () =>
|
|
||||||
_removeHandler(context),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.backspace): () =>
|
|
||||||
_removeHandler(context),
|
|
||||||
SingleActivator(
|
|
||||||
LogicalKeyboardKey.arrowUp,
|
|
||||||
shift: true,
|
|
||||||
meta: Platform.isMacOS,
|
|
||||||
control: !Platform.isMacOS,
|
|
||||||
): () => _shiftCmdUpHandler(context),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.enter): () =>
|
|
||||||
_enterHandler(context),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.numpadEnter): () =>
|
|
||||||
_enterHandler(context),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.enter, shift: true): () =>
|
|
||||||
_shitEnterHandler(context),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.comma): () =>
|
|
||||||
_moveGroupToAdjacentGroup(context, true),
|
|
||||||
const SingleActivator(LogicalKeyboardKey.period): () =>
|
|
||||||
_moveGroupToAdjacentGroup(context, false),
|
|
||||||
},
|
|
||||||
child: FocusScope(
|
child: FocusScope(
|
||||||
child: Focus(
|
child: Focus(
|
||||||
child: Builder(
|
child: Builder(
|
||||||
@ -92,16 +43,75 @@ class BoardShortcutContainer extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _enterHandler(BuildContext context) {
|
Map<ShortcutActivator, AFBindingCallback> _shortcutBindings(
|
||||||
|
BuildContext context,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
const SingleActivator(LogicalKeyboardKey.arrowUp):
|
||||||
|
focusScope.focusPrevious,
|
||||||
|
const SingleActivator(LogicalKeyboardKey.arrowDown): focusScope.focusNext,
|
||||||
|
const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true):
|
||||||
|
focusScope.adjustRangeUp,
|
||||||
|
const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true):
|
||||||
|
focusScope.adjustRangeDown,
|
||||||
|
const SingleActivator(LogicalKeyboardKey.escape): focusScope.clear,
|
||||||
|
const SingleActivator(LogicalKeyboardKey.delete): () =>
|
||||||
|
_removeHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.backspace): () =>
|
||||||
|
_removeHandler(context),
|
||||||
|
SingleActivator(
|
||||||
|
LogicalKeyboardKey.arrowUp,
|
||||||
|
shift: true,
|
||||||
|
meta: Platform.isMacOS,
|
||||||
|
control: !Platform.isMacOS,
|
||||||
|
): () => _shiftCmdUpHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.enter): () =>
|
||||||
|
_enterHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.numpadEnter): () =>
|
||||||
|
_enterHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.enter, shift: true): () =>
|
||||||
|
_shiftEnterHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.comma): () =>
|
||||||
|
_moveGroupToAdjacentGroup(context, true),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.period): () =>
|
||||||
|
_moveGroupToAdjacentGroup(context, false),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.keyE): () =>
|
||||||
|
_keyEHandler(context),
|
||||||
|
const SingleActivator(LogicalKeyboardKey.keyN): () =>
|
||||||
|
_keyNHandler(context),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _keyEHandler(BuildContext context) {
|
||||||
if (focusScope.value.length != 1) {
|
if (focusScope.value.length != 1) {
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
context.read<BoardActionsCubit>().startEditingRow(focusScope.value.first);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _keyNHandler(BuildContext context) {
|
||||||
|
if (focusScope.value.length != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
context
|
||||||
|
.read<BoardActionsCubit>()
|
||||||
|
.startCreateBottomRow(focusScope.value.first.groupId);
|
||||||
|
focusScope.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _enterHandler(BuildContext context) {
|
||||||
|
if (focusScope.value.length != 1) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
context
|
context
|
||||||
.read<BoardActionsCubit>()
|
.read<BoardActionsCubit>()
|
||||||
.openCardWithRowId(focusScope.value.first.rowId);
|
.openCardWithRowId(focusScope.value.first.rowId);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _shitEnterHandler(BuildContext context) {
|
bool _shiftEnterHandler(BuildContext context) {
|
||||||
if (focusScope.value.isEmpty) {
|
if (focusScope.value.isEmpty) {
|
||||||
context
|
context
|
||||||
.read<BoardActionsCubit>()
|
.read<BoardActionsCubit>()
|
||||||
@ -111,10 +121,13 @@ class BoardShortcutContainer extends StatelessWidget {
|
|||||||
focusScope.value.first,
|
focusScope.value.first,
|
||||||
CreateBoardCardRelativePosition.after,
|
CreateBoardCardRelativePosition.after,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _shiftCmdUpHandler(BuildContext context) {
|
bool _shiftCmdUpHandler(BuildContext context) {
|
||||||
if (focusScope.value.isEmpty) {
|
if (focusScope.value.isEmpty) {
|
||||||
context
|
context
|
||||||
.read<BoardActionsCubit>()
|
.read<BoardActionsCubit>()
|
||||||
@ -124,19 +137,23 @@ class BoardShortcutContainer extends StatelessWidget {
|
|||||||
focusScope.value.first,
|
focusScope.value.first,
|
||||||
CreateBoardCardRelativePosition.before,
|
CreateBoardCardRelativePosition.before,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _removeHandler(BuildContext context) {
|
bool _removeHandler(BuildContext context) {
|
||||||
if (focusScope.value.isEmpty) {
|
if (focusScope.value.length != 1) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
context.read<BoardBloc>().add(BoardEvent.deleteCards(focusScope.value));
|
context.read<BoardBloc>().add(BoardEvent.deleteCards(focusScope.value));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _moveGroupToAdjacentGroup(BuildContext context, bool toPrevious) {
|
bool _moveGroupToAdjacentGroup(BuildContext context, bool toPrevious) {
|
||||||
if (focusScope.value.length != 1) {
|
if (focusScope.value.length != 1) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
context.read<BoardBloc>().add(
|
context.read<BoardBloc>().add(
|
||||||
BoardEvent.moveGroupToAdjacentGroup(
|
BoardEvent.moveGroupToAdjacentGroup(
|
||||||
@ -145,5 +162,6 @@ class BoardShortcutContainer extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
focusScope.clear();
|
focusScope.clear();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
class AFCallbackShortcutsProvider {
|
typedef AFBindingCallback = bool Function();
|
||||||
final ValueNotifier<bool> isShortcutsEnabled = ValueNotifier(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
class AFCallbackShortcuts extends StatelessWidget {
|
class AFCallbackShortcuts extends StatelessWidget {
|
||||||
const AFCallbackShortcuts({
|
const AFCallbackShortcuts({
|
||||||
super.key,
|
super.key,
|
||||||
required this.bindings,
|
required this.bindings,
|
||||||
required this.canAcceptEvent,
|
|
||||||
required this.child,
|
required this.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Map<ShortcutActivator, VoidCallback> bindings;
|
// The bindings for the shortcuts
|
||||||
final bool Function(FocusNode node, KeyEvent event) canAcceptEvent;
|
//
|
||||||
|
// The result of the callback will be used to determine if the event is handled
|
||||||
|
final Map<ShortcutActivator, AFBindingCallback> bindings;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
bool _applyKeyEventBinding(ShortcutActivator activator, KeyEvent event) {
|
bool _applyKeyEventBinding(ShortcutActivator activator, KeyEvent event) {
|
||||||
if (activator.accepts(event, HardwareKeyboard.instance)) {
|
if (activator.accepts(event, HardwareKeyboard.instance)) {
|
||||||
bindings[activator]!.call();
|
return bindings[activator]?.call() ?? false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -31,9 +29,6 @@ class AFCallbackShortcuts extends StatelessWidget {
|
|||||||
canRequestFocus: false,
|
canRequestFocus: false,
|
||||||
skipTraversal: true,
|
skipTraversal: true,
|
||||||
onKeyEvent: (FocusNode node, KeyEvent event) {
|
onKeyEvent: (FocusNode node, KeyEvent event) {
|
||||||
if (!canAcceptEvent(node, event)) {
|
|
||||||
return KeyEventResult.ignored;
|
|
||||||
}
|
|
||||||
KeyEventResult result = KeyEventResult.ignored;
|
KeyEventResult result = KeyEventResult.ignored;
|
||||||
for (final ShortcutActivator activator in bindings.keys) {
|
for (final ShortcutActivator activator in bindings.keys) {
|
||||||
result = _applyKeyEventBinding(activator, event)
|
result = _applyKeyEventBinding(activator, event)
|
||||||
|
@ -60,7 +60,8 @@ class FavoriteBloc extends Bloc<FavoriteEvent, FavoriteState> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
toggle: (view) async {
|
toggle: (view) async {
|
||||||
if (view.isFavorite) {
|
final isFavorited = state.views.any((v) => v.item.id == view.id);
|
||||||
|
if (isFavorited) {
|
||||||
await _service.unpinFavorite(view);
|
await _service.unpinFavorite(view);
|
||||||
} else if (state.pinnedViews.length < 3) {
|
} else if (state.pinnedViews.length < 3) {
|
||||||
// pin the view if there are less than 3 pinned views
|
// pin the view if there are less than 3 pinned views
|
||||||
|
@ -35,7 +35,7 @@ class ViewFavoriteButton extends StatelessWidget {
|
|||||||
child: FlowySvg(
|
child: FlowySvg(
|
||||||
isFavorite ? FlowySvgs.favorited_s : FlowySvgs.favorite_s,
|
isFavorite ? FlowySvgs.favorited_s : FlowySvgs.favorite_s,
|
||||||
size: const Size.square(18),
|
size: const Size.square(18),
|
||||||
blendMode: null,
|
blendMode: isFavorite ? null : BlendMode.srcIn,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user