fix: unable to update selection sometimes when the editor lost focus (#509)
This commit is contained in:
parent
fbee8e3a6a
commit
d1b9084ffb
4 changed files with 115 additions and 3 deletions
|
|
@ -6,6 +6,7 @@ import 'dart:math';
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:example/pages/customize_theme_for_editor.dart';
|
||||
import 'package:example/pages/editor.dart';
|
||||
import 'package:example/pages/focus_example_for_editor.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -154,7 +155,7 @@ class _HomePageState extends State<HomePage> {
|
|||
}),
|
||||
|
||||
// Theme Demo
|
||||
_buildSeparator(context, 'Theme Demo'),
|
||||
_buildSeparator(context, 'Showcases'),
|
||||
_buildListTile(context, 'Custom Theme', () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
|
@ -173,6 +174,14 @@ class _HomePageState extends State<HomePage> {
|
|||
textDirection: TextDirection.rtl,
|
||||
);
|
||||
}),
|
||||
_buildListTile(context, 'Focus Example', () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const FocusExampleForEditor(),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
// Encoder Demo
|
||||
_buildSeparator(context, 'Export To X Demo'),
|
||||
|
|
|
|||
69
example/lib/pages/focus_example_for_editor.dart
Normal file
69
example/lib/pages/focus_example_for_editor.dart
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class FocusExampleForEditor extends StatefulWidget {
|
||||
const FocusExampleForEditor({super.key});
|
||||
|
||||
@override
|
||||
State<FocusExampleForEditor> createState() => _FocusExampleForEditorState();
|
||||
}
|
||||
|
||||
class _FocusExampleForEditorState extends State<FocusExampleForEditor> {
|
||||
late final Future<EditorState> editorState;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final jsonString = PlatformExtension.isDesktopOrWeb
|
||||
? rootBundle.loadString('assets/example.json')
|
||||
: rootBundle.loadString('assets/mobile_example.json');
|
||||
editorState = jsonString.then((value) {
|
||||
return EditorState(
|
||||
document: Document.fromJson(
|
||||
Map<String, Object>.from(
|
||||
json.decode(value),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
title: const Text('Custom Theme For Editor'),
|
||||
titleTextStyle: const TextStyle(color: Colors.white),
|
||||
iconTheme: const IconThemeData(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 400,
|
||||
child: FutureBuilder(
|
||||
future: editorState,
|
||||
builder: (context, snapshot) {
|
||||
return !snapshot.hasData
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: AppFlowyEditor(editorState: snapshot.data!);
|
||||
},
|
||||
),
|
||||
),
|
||||
const TextField(
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Please input something ...',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -306,7 +306,12 @@ class _DesktopSelectionServiceWidgetState
|
|||
editorState.service.scrollService?.stopAutoScroll();
|
||||
}
|
||||
|
||||
void _updateSelection() {}
|
||||
void _updateSelection() {
|
||||
final selection = editorState.selectionNotifier.value;
|
||||
if (selection == null) {
|
||||
clearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void _showContextMenu(TapDownDetails details) {
|
||||
_clearContextMenu();
|
||||
|
|
|
|||
|
|
@ -30,16 +30,45 @@ void main() async {
|
|||
expect(widget.focusNode.hasFocus, false);
|
||||
expect(widget.editorFocusNode.hasFocus, true);
|
||||
});
|
||||
|
||||
testWidgets('text field + editor, focus issue', (tester) async {
|
||||
final editorState = EditorState.blank();
|
||||
final widget = TextFieldAndEditor(
|
||||
editorState: editorState,
|
||||
);
|
||||
await tester.pumpWidget(widget);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final selection = Selection.collapsed(Position(path: [0]));
|
||||
editorState.selection = selection;
|
||||
|
||||
final textField = find.byType(TextField);
|
||||
await tester.tap(textField);
|
||||
await tester.pumpAndSettle();
|
||||
expect(widget.focusNode.hasFocus, true);
|
||||
expect(widget.editorFocusNode.hasFocus, false);
|
||||
expect(editorState.selection, null);
|
||||
|
||||
await tester.tapAt(
|
||||
tester.getTopLeft(find.byType(TextBlockComponentWidget)),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(widget.focusNode.hasFocus, false);
|
||||
expect(widget.editorFocusNode.hasFocus, true);
|
||||
expect(editorState.selection, selection);
|
||||
});
|
||||
}
|
||||
|
||||
class TextFieldAndEditor extends StatelessWidget {
|
||||
TextFieldAndEditor({
|
||||
super.key,
|
||||
this.editorState,
|
||||
});
|
||||
|
||||
final controller = TextEditingController();
|
||||
final focusNode = FocusNode();
|
||||
final editorFocusNode = FocusNode();
|
||||
final EditorState? editorState;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -61,7 +90,7 @@ class TextFieldAndEditor extends StatelessWidget {
|
|||
),
|
||||
child: AppFlowyEditor(
|
||||
focusNode: editorFocusNode,
|
||||
editorState: EditorState.blank(),
|
||||
editorState: editorState ?? EditorState.blank(),
|
||||
editorStyle: const EditorStyle.mobile(),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue