mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-04-24 06:37:14 -04:00
feat: optimize text insertion
This commit is contained in:
parent
19b1c84ea3
commit
c11904c2e9
3 changed files with 81 additions and 24 deletions
|
@ -1,4 +1,8 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:synchronized/synchronized.dart';
|
||||
|
||||
enum TextRobotInputType {
|
||||
character,
|
||||
|
@ -7,12 +11,35 @@ enum TextRobotInputType {
|
|||
}
|
||||
|
||||
class TextRobot {
|
||||
const TextRobot({
|
||||
TextRobot({
|
||||
required this.editorState,
|
||||
});
|
||||
|
||||
final EditorState editorState;
|
||||
final Lock lock = Lock();
|
||||
|
||||
/// This function is used to insert text in a synchronized way
|
||||
///
|
||||
/// It is suitable for inserting text in a loop.
|
||||
Future<void> autoInsertTextSync(
|
||||
String text, {
|
||||
TextRobotInputType inputType = TextRobotInputType.word,
|
||||
Duration delay = const Duration(milliseconds: 10),
|
||||
String separator = '\n',
|
||||
}) async {
|
||||
await lock.synchronized(() async {
|
||||
await autoInsertText(
|
||||
text,
|
||||
inputType: inputType,
|
||||
delay: delay,
|
||||
separator: separator,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// This function is used to insert text in an asynchronous way
|
||||
///
|
||||
/// It is suitable for inserting a long paragraph or a long sentence.
|
||||
Future<void> autoInsertText(
|
||||
String text, {
|
||||
TextRobotInputType inputType = TextRobotInputType.word,
|
||||
|
@ -20,15 +47,13 @@ class TextRobot {
|
|||
String separator = '\n',
|
||||
}) async {
|
||||
if (text == separator) {
|
||||
await editorState.insertNewLine();
|
||||
await Future.delayed(delay);
|
||||
await insertNewParagraph(delay);
|
||||
return;
|
||||
}
|
||||
final lines = _splitText(text, separator);
|
||||
for (final line in lines) {
|
||||
if (line.isEmpty) {
|
||||
await editorState.insertNewLine();
|
||||
await Future.delayed(delay);
|
||||
await insertNewParagraph(delay);
|
||||
continue;
|
||||
}
|
||||
switch (inputType) {
|
||||
|
@ -48,10 +73,7 @@ class TextRobot {
|
|||
Future<void> insertCharacter(String line, Duration delay) async {
|
||||
final iterator = line.runes.iterator;
|
||||
while (iterator.moveNext()) {
|
||||
await editorState.insertTextAtCurrentSelection(
|
||||
iterator.currentAsString,
|
||||
);
|
||||
await Future.delayed(delay);
|
||||
await insertText(iterator.currentAsString, delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,22 +81,60 @@ class TextRobot {
|
|||
final words = line.split(' ');
|
||||
if (words.length == 1 ||
|
||||
(words.length == 2 && (words.first.isEmpty || words.last.isEmpty))) {
|
||||
await editorState.insertTextAtCurrentSelection(
|
||||
line,
|
||||
);
|
||||
await insertText(line, delay);
|
||||
} else {
|
||||
for (final word in words.map((e) => '$e ')) {
|
||||
await editorState.insertTextAtCurrentSelection(
|
||||
word,
|
||||
);
|
||||
await insertText(word, delay);
|
||||
}
|
||||
}
|
||||
await Future.delayed(delay);
|
||||
}
|
||||
|
||||
Future<void> insertSentence(String line, Duration delay) async {
|
||||
await editorState.insertTextAtCurrentSelection(line);
|
||||
await insertText(line, delay);
|
||||
}
|
||||
|
||||
Future<void> insertNewParagraph(Duration delay) async {
|
||||
final selection = editorState.selection;
|
||||
if (selection == null || !selection.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
final next = selection.end.path.next;
|
||||
final transaction = editorState.transaction;
|
||||
transaction.insertNode(
|
||||
next,
|
||||
paragraphNode(),
|
||||
);
|
||||
transaction.afterSelection = Selection.collapsed(
|
||||
Position(path: next),
|
||||
);
|
||||
await editorState.apply(transaction);
|
||||
debugPrint(
|
||||
'AI insertNewParagraph: path: ${editorState.selection!.end.path}, index: ${editorState.selection!.endIndex}',
|
||||
);
|
||||
await Future.delayed(const Duration(milliseconds: 10));
|
||||
}
|
||||
|
||||
Future<void> insertText(String text, Duration delay) async {
|
||||
final selection = editorState.selection;
|
||||
debugPrint(
|
||||
'AI insertText: get selection, path: ${selection!.end.path}, index: ${selection.endIndex}',
|
||||
);
|
||||
if (!selection.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
final node = editorState.getNodeAtPath(selection.end.path);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
final transaction = editorState.transaction;
|
||||
transaction.insertText(node, selection.endIndex, text);
|
||||
await editorState.apply(transaction);
|
||||
await Future.delayed(delay);
|
||||
|
||||
debugPrint(
|
||||
'AI insertText: path: ${selection.end.path}, index: ${selection.endIndex}, text: "$text"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ class _AutoCompletionBlockComponentState
|
|||
}
|
||||
},
|
||||
onProcess: (text) async {
|
||||
await textRobot.autoInsertText(
|
||||
await textRobot.autoInsertTextSync(
|
||||
text,
|
||||
separator: r'\n\n',
|
||||
inputType: TextRobotInputType.sentence,
|
||||
|
@ -269,10 +269,7 @@ class _AutoCompletionBlockComponentState
|
|||
start,
|
||||
end.last - start.last + 1,
|
||||
);
|
||||
await editorState.apply(
|
||||
transaction,
|
||||
options: const ApplyOptions(inMemoryUpdate: true),
|
||||
);
|
||||
await editorState.apply(transaction);
|
||||
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +318,7 @@ class _AutoCompletionBlockComponentState
|
|||
await _makeSurePreviousNodeIsEmptyParagraphNode();
|
||||
},
|
||||
onProcess: (text) async {
|
||||
await textRobot.autoInsertText(
|
||||
await textRobot.autoInsertTextSync(
|
||||
text,
|
||||
inputType: TextRobotInputType.sentence,
|
||||
separator: r'\n\n',
|
||||
|
|
|
@ -20,7 +20,7 @@ void main() {
|
|||
editorState: editorState,
|
||||
);
|
||||
for (final text in _sample1) {
|
||||
await textRobot.autoInsertText(
|
||||
await textRobot.autoInsertTextSync(
|
||||
text,
|
||||
separator: r'\n\n',
|
||||
inputType: TextRobotInputType.sentence,
|
||||
|
@ -58,7 +58,7 @@ void main() {
|
|||
if (text.contains('\n\n')) {
|
||||
breakCount++;
|
||||
}
|
||||
await textRobot.autoInsertText(
|
||||
await textRobot.autoInsertTextSync(
|
||||
text,
|
||||
separator: r'\n\n',
|
||||
inputType: TextRobotInputType.sentence,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue