fix: editor will crash if deleting all nodes (#1037)
* fix: editor will crash if deleting all nodes * chore: disable windows ci
This commit is contained in:
parent
8868c50aef
commit
1df3cb1a1f
6 changed files with 41 additions and 9 deletions
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
desktop:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,9 +105,7 @@ class _DesktopEditorState extends State<DesktopEditor> {
|
|||
height: 150,
|
||||
),
|
||||
),
|
||||
footer: const SizedBox(
|
||||
height: 100,
|
||||
),
|
||||
footer: _buildFooter(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -216,6 +214,32 @@ class _DesktopEditorState extends State<DesktopEditor> {
|
|||
];
|
||||
}
|
||||
|
||||
Widget _buildFooter() {
|
||||
return SizedBox(
|
||||
height: 100,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () async {
|
||||
// check if the document is empty, if so, add a new paragraph block.
|
||||
if (editorState.document.root.children.isEmpty) {
|
||||
final transaction = editorState.transaction;
|
||||
transaction.insertNode(
|
||||
[0],
|
||||
paragraphNode(),
|
||||
);
|
||||
await editorState.apply(transaction);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
editorState.selection = Selection.collapsed(
|
||||
Position(path: [0]),
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? _buildAutoCompleteTextProvider(
|
||||
BuildContext context,
|
||||
Node node,
|
||||
|
|
|
|||
|
|
@ -192,10 +192,11 @@ class EditorScrollController {
|
|||
|
||||
final index = offset.toInt();
|
||||
final (start, end) = visibleRangeNotifier.value;
|
||||
|
||||
if (index < start || index > end) {
|
||||
itemScrollController.jumpTo(
|
||||
index: max(0, index),
|
||||
alignment: 0.5,
|
||||
alignment: 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,11 @@ class _ScrollServiceWidgetState extends State<ScrollServiceWidget>
|
|||
return;
|
||||
}
|
||||
if (endTouchPoint == null) {
|
||||
// check if the selection is valid
|
||||
final node = editorState.getNodeAtPath(selection.end.path);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
jumpTo(selection.end.path.first);
|
||||
} else {
|
||||
startAutoScroll(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/editor/editor_component/service/selection/mobile_selection_service.dart';
|
||||
import 'package:appflowy_editor/src/editor/editor_component/service/selection/shared.dart';
|
||||
import 'package:appflowy_editor/src/service/selection/selection_gesture.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class DesktopSelectionServiceWidget extends StatefulWidget {
|
||||
|
|
@ -153,6 +152,10 @@ class _DesktopSelectionServiceWidgetState
|
|||
context.read<EditorScrollController>(),
|
||||
);
|
||||
|
||||
if (sortedNodes.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return editorState.getNodeInOffset(
|
||||
sortedNodes,
|
||||
offset,
|
||||
|
|
|
|||
|
|
@ -258,7 +258,6 @@ class EditorState {
|
|||
|
||||
// only used for testing
|
||||
bool disableSealTimer = false;
|
||||
bool disableRules = false;
|
||||
|
||||
@Deprecated('use editorState.selection instead')
|
||||
Selection? _cursorSelection;
|
||||
|
|
|
|||
Loading…
Reference in a new issue