feat: power checkbox shortcut (#553)

This commit is contained in:
Mathias Mogensen 2023-10-30 04:20:15 +01:00 • committed by GitHub
commit 5b9b6d80f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 2 deletions

View file

@ -1,5 +1,6 @@
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
const standardBlockComponentConfiguration = BlockComponentConfiguration(); const standardBlockComponentConfiguration = BlockComponentConfiguration();
@ -16,6 +17,11 @@ final Map<String, BlockComponentBuilder> standardBlockComponentBuilderMap = {
configuration: standardBlockComponentConfiguration.copyWith( configuration: standardBlockComponentConfiguration.copyWith(
placeholderText: (_) => 'To-do', placeholderText: (_) => 'To-do',
), ),
toggleChildrenTriggers: [
LogicalKeyboardKey.shift,
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
],
), ),
BulletedListBlockKeys.type: BulletedListBlockComponentBuilder( BulletedListBlockKeys.type: BulletedListBlockComponentBuilder(
configuration: standardBlockComponentConfiguration.copyWith( configuration: standardBlockComponentConfiguration.copyWith(

View file

@ -1,6 +1,7 @@
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart'; import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TodoListBlockKeys { class TodoListBlockKeys {
const TodoListBlockKeys._(); const TodoListBlockKeys._();
@ -43,6 +44,7 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
super.configuration, super.configuration,
this.textStyleBuilder, this.textStyleBuilder,
this.iconBuilder, this.iconBuilder,
this.toggleChildrenTriggers,
}); });
/// The text style of the todo list block. /// The text style of the todo list block.
@ -50,6 +52,8 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
final BlockIconBuilder? iconBuilder; final BlockIconBuilder? iconBuilder;
final List<LogicalKeyboardKey>? toggleChildrenTriggers;
@override @override
BlockComponentWidget build(BlockComponentContext blockComponentContext) { BlockComponentWidget build(BlockComponentContext blockComponentContext) {
final node = blockComponentContext.node; final node = blockComponentContext.node;
@ -64,6 +68,7 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
blockComponentContext, blockComponentContext,
state, state,
), ),
toggleChildrenTriggers: toggleChildrenTriggers,
); );
} }
@ -83,10 +88,12 @@ class TodoListBlockComponentWidget extends BlockComponentStatefulWidget {
super.configuration = const BlockComponentConfiguration(), super.configuration = const BlockComponentConfiguration(),
this.textStyleBuilder, this.textStyleBuilder,
this.iconBuilder, this.iconBuilder,
this.toggleChildrenTriggers,
}); });
final TextStyle Function(bool checked)? textStyleBuilder; final TextStyle Function(bool checked)? textStyleBuilder;
final BlockIconBuilder? iconBuilder; final BlockIconBuilder? iconBuilder;
final List<LogicalKeyboardKey>? toggleChildrenTriggers;
@override @override
State<TodoListBlockComponentWidget> createState() => State<TodoListBlockComponentWidget> createState() =>
@ -203,12 +210,40 @@ class _TodoListBlockComponentWidgetState
return child; return child;
} }
Future<void> checkOrUncheck() async { void checkOrUncheck() {
final transaction = editorState.transaction final transaction = editorState.transaction
..updateNode(widget.node, { ..updateNode(widget.node, {
TodoListBlockKeys.checked: !checked, TodoListBlockKeys.checked: !checked,
}); });
return editorState.apply(transaction);
if (widget.toggleChildrenTriggers != null &&
RawKeyboard.instance.keysPressed.any(
(element) => widget.toggleChildrenTriggers!.contains(element),
)) {
checkOrUncheckChildren(!checked, widget.node);
}
editorState.apply(transaction);
}
void checkOrUncheckChildren(
bool checked,
Node node,
) {
for (final child in node.children) {
if (child.children.isNotEmpty) {
checkOrUncheckChildren(checked, child);
}
if (child.type == TodoListBlockKeys.type) {
final transaction = editorState.transaction
..updateNode(child, {
TodoListBlockKeys.checked: checked,
});
editorState.apply(transaction);
}
}
} }
TextStyle? defaultTextStyle() { TextStyle? defaultTextStyle() {

View file

@ -0,0 +1,62 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../infra/testable_editor.dart';
void main() async {
group('todo list power toggle', () {
const text = 'Welcome to AppFlowy Editor 🔥!';
// - [] Welcome to AppFlowy Editor 🔥!
// - [] Welcome to AppFlowy Editor 🔥!
// - [] Welcome to AppFlowy Editor 🔥!
testWidgets('use power toggle', (tester) async {
final editor = tester.editor
..addNode(
todoListNode(
delta: Delta()..insert(text),
checked: false,
children: [
todoListNode(
delta: Delta()..insert(text),
checked: false,
children: [
todoListNode(
delta: Delta()..insert(text),
checked: false,
children: [],
),
],
),
],
),
);
await editor.startTesting();
Node n1 = editor.document.root.children.first;
Node n2 = n1.children.first;
Node n3 = n2.children.first;
expect(n1.attributes[TodoListBlockKeys.checked], false);
expect(n2.attributes[TodoListBlockKeys.checked], false);
expect(n3.attributes[TodoListBlockKeys.checked], false);
final finder = find.byType(EditorSvg).first;
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tap(finder);
await tester.pumpAndSettle();
n1 = editor.document.root.children.first;
n2 = n1.children.first;
n3 = n2.children.first;
expect(n1.attributes[TodoListBlockKeys.checked], true);
expect(n2.attributes[TodoListBlockKeys.checked], true);
expect(n3.attributes[TodoListBlockKeys.checked], true);
await editor.dispose();
});
});
}