mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: format the selected text to url if available (#3245)
This commit is contained in:
parent
77637ff461
commit
724fc895e1
@ -195,11 +195,43 @@ void main() {
|
|||||||
// expect(node.attributes[ImageBlockKeys.url], isNotNull);
|
// expect(node.attributes[ImageBlockKeys.url], isNotNull);
|
||||||
// });
|
// });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'format the selected text to href when pasting url if available',
|
||||||
|
(tester) async {
|
||||||
|
const text = 'appflowy';
|
||||||
|
const url = 'https://appflowy.io';
|
||||||
|
await tester.pasteContent(
|
||||||
|
plainText: url,
|
||||||
|
beforeTest: (editorState) async {
|
||||||
|
await tester.ime.insertText(text);
|
||||||
|
await tester.editor.updateSelection(
|
||||||
|
Selection.single(
|
||||||
|
path: [0],
|
||||||
|
startOffset: 0,
|
||||||
|
endOffset: text.length,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(editorState) {
|
||||||
|
final node = editorState.getNodeAtPath([0])!;
|
||||||
|
expect(node.type, ParagraphBlockKeys.type);
|
||||||
|
expect(node.delta!.toJson(), [
|
||||||
|
{
|
||||||
|
'insert': text,
|
||||||
|
'attributes': {'href': url}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on WidgetTester {
|
extension on WidgetTester {
|
||||||
Future<void> pasteContent(
|
Future<void> pasteContent(
|
||||||
void Function(EditorState editorState) test, {
|
void Function(EditorState editorState) test, {
|
||||||
|
Future<void> Function(EditorState editorState)? beforeTest,
|
||||||
String? plainText,
|
String? plainText,
|
||||||
String? html,
|
String? html,
|
||||||
(String, Uint8List?)? image,
|
(String, Uint8List?)? image,
|
||||||
@ -210,6 +242,8 @@ extension on WidgetTester {
|
|||||||
// create a new document
|
// create a new document
|
||||||
await createNewPageWithName();
|
await createNewPageWithName();
|
||||||
|
|
||||||
|
await beforeTest?.call(editor.getCurrentEditorState());
|
||||||
|
|
||||||
// mock the clipboard
|
// mock the clipboard
|
||||||
getIt<ClipboardService>().setData(
|
getIt<ClipboardService>().setData(
|
||||||
ClipboardServiceData(
|
ClipboardServiceData(
|
||||||
@ -227,7 +261,6 @@ extension on WidgetTester {
|
|||||||
);
|
);
|
||||||
await pumpAndSettle();
|
await pumpAndSettle();
|
||||||
|
|
||||||
final editorState = editor.getCurrentEditorState();
|
test(editor.getCurrentEditorState());
|
||||||
test(editorState);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ CommandShortcutEventHandler _pasteCommandHandler = (editorState) {
|
|||||||
await editorState.deleteSelectionIfNeeded();
|
await editorState.deleteSelectionIfNeeded();
|
||||||
await editorState.pasteImage(image.$1, image.$2!);
|
await editorState.pasteImage(image.$1, image.$2!);
|
||||||
} else if (plainText != null && plainText.isNotEmpty) {
|
} else if (plainText != null && plainText.isNotEmpty) {
|
||||||
await editorState.deleteSelectionIfNeeded();
|
|
||||||
await editorState.pastePlainText(plainText);
|
await editorState.pastePlainText(plainText);
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
@ -7,6 +7,12 @@ RegExp _hrefRegex = RegExp(
|
|||||||
|
|
||||||
extension PasteFromPlainText on EditorState {
|
extension PasteFromPlainText on EditorState {
|
||||||
Future<void> pastePlainText(String plainText) async {
|
Future<void> pastePlainText(String plainText) async {
|
||||||
|
if (await pasteHtmlIfAvailable(plainText)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteSelectionIfNeeded();
|
||||||
|
|
||||||
final nodes = plainText
|
final nodes = plainText
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(
|
.map(
|
||||||
@ -33,4 +39,26 @@ extension PasteFromPlainText on EditorState {
|
|||||||
await pasteMultiLineNodes(nodes.toList());
|
await pasteMultiLineNodes(nodes.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> pasteHtmlIfAvailable(String plainText) async {
|
||||||
|
final selection = this.selection;
|
||||||
|
if (selection == null ||
|
||||||
|
!selection.isSingle ||
|
||||||
|
selection.isCollapsed ||
|
||||||
|
!_hrefRegex.hasMatch(plainText)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final node = getNodeAtPath(selection.start.path);
|
||||||
|
if (node == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final transaction = this.transaction;
|
||||||
|
transaction.formatText(node, selection.startIndex, selection.length, {
|
||||||
|
AppFlowyRichTextKeys.href: plainText,
|
||||||
|
});
|
||||||
|
await apply(transaction);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user