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:
Lucas 2025-02-18 16:22:05 +08:00 • committed by GitHub
commit 1df3cb1a1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 41 additions and 9 deletions

View file

@ -23,7 +23,7 @@ jobs:
desktop:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
os: [macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}

View file

@ -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,

View file

@ -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,
);
}
}

View file

@ -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(

View file

@ -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,

View file

@ -258,7 +258,6 @@ class EditorState {
// only used for testing
bool disableSealTimer = false;
bool disableRules = false;
@Deprecated('use editorState.selection instead')
Selection? _cursorSelection;