feat: power checkbox shortcut (#553)
This commit is contained in:
parent
2dacd74dc0
commit
5b9b6d80f5
3 changed files with 105 additions and 2 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
const standardBlockComponentConfiguration = BlockComponentConfiguration();
|
||||
|
||||
|
|
@ -16,6 +17,11 @@ final Map<String, BlockComponentBuilder> standardBlockComponentBuilderMap = {
|
|||
configuration: standardBlockComponentConfiguration.copyWith(
|
||||
placeholderText: (_) => 'To-do',
|
||||
),
|
||||
toggleChildrenTriggers: [
|
||||
LogicalKeyboardKey.shift,
|
||||
LogicalKeyboardKey.shiftLeft,
|
||||
LogicalKeyboardKey.shiftRight,
|
||||
],
|
||||
),
|
||||
BulletedListBlockKeys.type: BulletedListBlockComponentBuilder(
|
||||
configuration: standardBlockComponentConfiguration.copyWith(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class TodoListBlockKeys {
|
||||
const TodoListBlockKeys._();
|
||||
|
|
@ -43,6 +44,7 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
|
|||
super.configuration,
|
||||
this.textStyleBuilder,
|
||||
this.iconBuilder,
|
||||
this.toggleChildrenTriggers,
|
||||
});
|
||||
|
||||
/// The text style of the todo list block.
|
||||
|
|
@ -50,6 +52,8 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
|
|||
|
||||
final BlockIconBuilder? iconBuilder;
|
||||
|
||||
final List<LogicalKeyboardKey>? toggleChildrenTriggers;
|
||||
|
||||
@override
|
||||
BlockComponentWidget build(BlockComponentContext blockComponentContext) {
|
||||
final node = blockComponentContext.node;
|
||||
|
|
@ -64,6 +68,7 @@ class TodoListBlockComponentBuilder extends BlockComponentBuilder {
|
|||
blockComponentContext,
|
||||
state,
|
||||
),
|
||||
toggleChildrenTriggers: toggleChildrenTriggers,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -83,10 +88,12 @@ class TodoListBlockComponentWidget extends BlockComponentStatefulWidget {
|
|||
super.configuration = const BlockComponentConfiguration(),
|
||||
this.textStyleBuilder,
|
||||
this.iconBuilder,
|
||||
this.toggleChildrenTriggers,
|
||||
});
|
||||
|
||||
final TextStyle Function(bool checked)? textStyleBuilder;
|
||||
final BlockIconBuilder? iconBuilder;
|
||||
final List<LogicalKeyboardKey>? toggleChildrenTriggers;
|
||||
|
||||
@override
|
||||
State<TodoListBlockComponentWidget> createState() =>
|
||||
|
|
@ -203,12 +210,40 @@ class _TodoListBlockComponentWidgetState
|
|||
return child;
|
||||
}
|
||||
|
||||
Future<void> checkOrUncheck() async {
|
||||
void checkOrUncheck() {
|
||||
final transaction = editorState.transaction
|
||||
..updateNode(widget.node, {
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue