fix: selection race condition (#1194)

* fix: guard debounced desktop selection update

Avoid dereferencing a cleared selection from the delayed
macOS metrics callback and add a regression test that
covers the stale-timer path.

* chore: clean up analyzer warnings

Remove redundant default arguments in tests and apply the
missing trailing comma required by the current lint rules.
This commit is contained in:
Lucas 2026-03-31 17:33:40 +08:00 • committed by GitHub
commit 6fbe7ba442
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 5 deletions

View file

@ -54,7 +54,6 @@ void main() {
scroller.startAutoScroll(
offset,
edgeOffset: edgeOffset,
direction: AxisDirection.up,
);
@ -96,7 +95,6 @@ void main() {
scroller.startAutoScroll(
offset,
edgeOffset: edgeOffset,
direction: AxisDirection.down,
);

View file

@ -0,0 +1,42 @@
import 'dart:ui';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import '../../../test_helper.dart';
void main() {
group('DesktopSelectionServiceWidget', () {
testWidgets(
'does not crash when selection is cleared before metric debounce fires',
(tester) async {
final editorState = EditorState(document: Document.blank());
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
tester.view.devicePixelRatio = 1.0;
await tester.buildAndPump(
AppFlowyEditor(
editorState: editorState,
),
);
editorState.selectionService.updateSelection(
Selection.collapsed(Position(path: [0])),
);
await tester.pump();
tester.view.physicalSize = const Size(1600, 1200);
await tester.pump();
editorState.selection = null;
await tester.pump(const Duration(milliseconds: 101));
expect(tester.takeException(), isNull);
expect(editorState.selectionService.currentSelection.value, isNull);
},
);
});
}

View file

@ -427,7 +427,6 @@ void main() async {
transaction,
options: const ApplyOptions(
recordUndo: false,
recordRedo: false,
source: TransactionSource.none,
),
);

View file

@ -203,7 +203,7 @@ void main() async {
// Place cursor at [0] offset 0
await editor.updateSelection(
Selection.collapsed(Position(path: [0], offset: 0)),
Selection.collapsed(Position(path: [0])),
);
// Type 4 characters with pumpAndSettle between each