integrate board plugin into document (#1675)
* fix: cursor doesn't blink when opening selection menu * feat: add board plugin * feat: integrate board plugin into document * feat: add i10n and fix known bugs * feat: support jump to board page on document * feat: disable editor scroll only when the board plugin is selected * chore: dart fix * chore: remove unused files * fix: dart lint
This commit is contained in:
parent
2c28123f59
commit
be640c0cc5
9 changed files with 20 additions and 23 deletions
|
|
@ -23,6 +23,7 @@
|
|||
]
|
||||
},
|
||||
{ "type": "text", "delta": [] },
|
||||
{ "type": "board" },
|
||||
{
|
||||
"type": "text",
|
||||
"delta": [
|
||||
|
|
|
|||
|
|
@ -44,3 +44,4 @@ export 'src/plugins/markdown/document_markdown.dart';
|
|||
export 'src/plugins/quill_delta/delta_document_encoder.dart';
|
||||
export 'src/commands/text/text_commands.dart';
|
||||
export 'src/render/toolbar/toolbar_item.dart';
|
||||
export 'src/extensions/node_extensions.dart';
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
|
|||
Attributes _attributes;
|
||||
|
||||
// Renderable
|
||||
GlobalKey? key;
|
||||
final key = GlobalKey();
|
||||
final layerLink = LayerLink();
|
||||
|
||||
Attributes get attributes => {..._attributes};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import 'package:appflowy_editor/src/core/document/node.dart';
|
||||
import 'package:appflowy_editor/src/core/document/path.dart';
|
||||
import 'package:appflowy_editor/src/core/location/selection.dart';
|
||||
import 'package:appflowy_editor/src/editor_state.dart';
|
||||
import 'package:appflowy_editor/src/extensions/object_extensions.dart';
|
||||
import 'package:appflowy_editor/src/render/selection/selectable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension NodeExtensions on Node {
|
||||
RenderBox? get renderBox =>
|
||||
key?.currentContext?.findRenderObject()?.unwrapOrNull<RenderBox>();
|
||||
key.currentContext?.findRenderObject()?.unwrapOrNull<RenderBox>();
|
||||
|
||||
BuildContext? get context => key?.currentContext;
|
||||
BuildContext? get context => key.currentContext;
|
||||
SelectableMixin? get selectable =>
|
||||
key?.currentState?.unwrapOrNull<SelectableMixin>();
|
||||
key.currentState?.unwrapOrNull<SelectableMixin>();
|
||||
|
||||
bool inSelection(Selection selection) {
|
||||
if (selection.start.path <= selection.end.path) {
|
||||
|
|
@ -28,4 +29,11 @@ extension NodeExtensions on Node {
|
|||
}
|
||||
return Rect.zero;
|
||||
}
|
||||
|
||||
bool isSelected(EditorState editorState) {
|
||||
final currentSelectedNodes =
|
||||
editorState.service.selectionService.currentSelectedNodes;
|
||||
return currentSelectedNodes.length == 1 &&
|
||||
currentSelectedNodes.first == this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/extensions/node_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
ShortcutEventHandler cursorLeftSelect = (editorState, event) {
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ class AppFlowyRenderPlugin extends AppFlowyRenderPluginService {
|
|||
node.subtype == null ? node.type : '${node.type}/${node.subtype!}';
|
||||
final builder = _builders[name];
|
||||
if (builder != null && builder.nodeValidator(node)) {
|
||||
final key = GlobalKey(debugLabel: name);
|
||||
node.key = key;
|
||||
return _autoUpdateNodeWidget(builder, context);
|
||||
} else {
|
||||
// Returns a SizeBox with 0 height if no builder found.
|
||||
|
|
|
|||
|
|
@ -1,28 +1,18 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:appflowy_editor/src/extensions/node_extensions.dart';
|
||||
|
||||
class MockNode extends Mock implements Node {}
|
||||
|
||||
void main() {
|
||||
final mockNode = MockNode();
|
||||
|
||||
group('NodeExtensions::', () {
|
||||
final selection = Selection(
|
||||
start: Position(path: [0]),
|
||||
end: Position(path: [1]),
|
||||
);
|
||||
|
||||
test('rect - renderBox is null', () {
|
||||
when(mockNode.renderBox).thenReturn(null);
|
||||
final result = mockNode.rect;
|
||||
expect(result, Rect.zero);
|
||||
});
|
||||
|
||||
test('inSelection', () {
|
||||
// I use an empty implementation instead of mock, because the mocked
|
||||
// version throws error trying to access the path.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void main() async {
|
|||
final selection =
|
||||
Selection.single(path: [0], startOffset: 0, endOffset: text.length);
|
||||
var node = editor.nodeAtPath([0]) as TextNode;
|
||||
var state = node.key?.currentState as DefaultSelectable;
|
||||
var state = node.key.currentState as DefaultSelectable;
|
||||
var checkboxWidget = find.byKey(state.iconKey!);
|
||||
await tester.tap(checkboxWidget);
|
||||
await tester.pumpAndSettle();
|
||||
|
|
@ -56,7 +56,7 @@ void main() async {
|
|||
expect(node.allSatisfyStrikethroughInSelection(selection), true);
|
||||
|
||||
node = editor.nodeAtPath([0]) as TextNode;
|
||||
state = node.key?.currentState as DefaultSelectable;
|
||||
state = node.key.currentState as DefaultSelectable;
|
||||
await tester.ensureVisible(find.byKey(state.iconKey!));
|
||||
await tester.tap(find.byKey(state.iconKey!));
|
||||
await tester.pump();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ void main() async {
|
|||
await editor.startTesting();
|
||||
|
||||
final secondTextNode = editor.nodeAtPath([1]);
|
||||
final finder = find.byKey(secondTextNode!.key!);
|
||||
final finder = find.byKey(secondTextNode!.key);
|
||||
|
||||
final rect = tester.getRect(finder);
|
||||
// tap at the beginning
|
||||
|
|
@ -48,7 +48,7 @@ void main() async {
|
|||
await editor.startTesting();
|
||||
|
||||
final secondTextNode = editor.nodeAtPath([1]);
|
||||
final finder = find.byKey(secondTextNode!.key!);
|
||||
final finder = find.byKey(secondTextNode!.key);
|
||||
|
||||
final rect = tester.getRect(finder);
|
||||
// double tap
|
||||
|
|
@ -70,7 +70,7 @@ void main() async {
|
|||
await editor.startTesting();
|
||||
|
||||
final secondTextNode = editor.nodeAtPath([1]);
|
||||
final finder = find.byKey(secondTextNode!.key!);
|
||||
final finder = find.byKey(secondTextNode!.key);
|
||||
|
||||
final rect = tester.getRect(finder);
|
||||
// triple tap
|
||||
|
|
@ -93,7 +93,7 @@ void main() async {
|
|||
await editor.startTesting();
|
||||
|
||||
final secondTextNode = editor.nodeAtPath([1]) as TextNode;
|
||||
final finder = find.byKey(secondTextNode.key!);
|
||||
final finder = find.byKey(secondTextNode.key);
|
||||
|
||||
final rect = tester.getRect(finder);
|
||||
// secondary tap
|
||||
|
|
|
|||
Loading…
Reference in a new issue