Skip to content

Commit 31934d7

Browse files
authored
feat: divider toolbar item in mobile (AppFlowy-IO#281)
1 parent f6584b9 commit 31934d7

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

example/lib/pages/simple_editor.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ class SimpleEditor extends StatelessWidget {
7575
listMobileToolbarItem,
7676
linkMobileToolbarItem,
7777
quoteMobileToolbarItem,
78+
dividerMobileToolbarItem,
7879
codeMobileToolbarItem,
79-
// dividerMobileToolbarItem,
8080
],
8181
textColorOptions: [
8282
ColorOption(

lib/src/editor/toolbar/mobile/toolbar_items/divider_mobile_toolbar_item.dart

+17-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@ import 'package:appflowy_editor/appflowy_editor.dart';
33
final dividerMobileToolbarItem = MobileToolbarItem.action(
44
itemIcon: const AFMobileIcon(afMobileIcons: AFMobileIcons.divider),
55
actionHandler: ((editorState, selection) {
6-
// TODO(yijing): Implement the divider toolbar item.
6+
// same as the [handler] of [dividerMenuItem] in Desktop
7+
final selection = editorState.selection;
8+
if (selection == null || !selection.isCollapsed) {
9+
return;
10+
}
11+
final path = selection.end.path;
12+
final node = editorState.getNodeAtPath(path);
13+
final delta = node?.delta;
14+
if (node == null || delta == null) {
15+
return;
16+
}
17+
final insertedPath = delta.isEmpty ? path : path.next;
18+
final transaction = editorState.transaction
19+
..insertNode(insertedPath, dividerNode())
20+
..insertNode(insertedPath, paragraphNode())
21+
..afterSelection = Selection.collapse(insertedPath.next, 0);
22+
editorState.apply(transaction);
723
}),
824
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:appflowy_editor/appflowy_editor.dart';
4+
import '../../../../new/infra/testable_editor.dart';
5+
import '../test_helpers/mobile_app_with_toolbar_widget.dart';
6+
7+
void main() {
8+
group('dividerMobileToolbarItem\n', () {
9+
testWidgets(
10+
'If the user tries to insert a divider while some text is selected, no action should be taken',
11+
(WidgetTester tester) async {
12+
const text = 'Welcome to Appflowy 😁';
13+
final editor = tester.editor..addParagraphs(3, initialText: text);
14+
await editor.startTesting();
15+
16+
var selection = Selection.single(
17+
path: [1],
18+
startOffset: 2,
19+
endOffset: text.length - 2,
20+
);
21+
22+
await editor.updateSelection(selection);
23+
await tester.pumpWidget(
24+
Material(
25+
child: MobileAppWithToolbarWidget(
26+
editorState: editor.editorState,
27+
toolbarItems: [
28+
dividerMobileToolbarItem,
29+
],
30+
),
31+
),
32+
);
33+
34+
// Tap divider toolbar item
35+
final dividerBtn = find.byType(IconButton).first;
36+
await tester.tap(dividerBtn);
37+
await tester.pumpAndSettle(const Duration(milliseconds: 500));
38+
// Check if the text becomes quote node
39+
final node = editor.editorState.getNodeAtPath([1]);
40+
expect(
41+
node?.type == ParagraphBlockKeys.type,
42+
true,
43+
);
44+
});
45+
testWidgets(
46+
'Insert a divider if nothing is selected(selection is collapsed)',
47+
(WidgetTester tester) async {
48+
const text = 'Welcome to Appflowy 😁';
49+
final editor = tester.editor..addParagraphs(3, initialText: text);
50+
await editor.startTesting();
51+
52+
const originalPath = 1;
53+
54+
var selection =
55+
Selection.collapsed(Position(path: [originalPath], offset: 2));
56+
57+
await editor.updateSelection(selection);
58+
await tester.pumpWidget(
59+
Material(
60+
child: MobileAppWithToolbarWidget(
61+
editorState: editor.editorState,
62+
toolbarItems: [
63+
dividerMobileToolbarItem,
64+
],
65+
),
66+
),
67+
);
68+
69+
// Tap divider toolbar item
70+
final dividerBtn = find.byType(IconButton).first;
71+
await tester.tap(dividerBtn);
72+
await tester.pumpAndSettle(const Duration(milliseconds: 500));
73+
// Check if the node in the next path become a divider node
74+
final node = editor.editorState.getNodeAtPath([originalPath + 1]);
75+
expect(
76+
node?.type == DividerBlockKeys.type,
77+
true,
78+
);
79+
});
80+
});
81+
}

0 commit comments

Comments
 (0)