mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
relicense appflowy editor (#1938)
* revert:"fix: remove keyword when click selection menu item" This reverts commit5782dec45c
. * revert(appflowy_editor):revert "feat: double asterisks/underscores to bold text" This reverts commitc0964fad5d
. * revert(appflowy_editor):revert "fix: workaround infinity formatting" This reverts commit6a902a2b21
. The Appflowy folder under the frontend had been removed before reverting. * chore(appflow_editor):update test variable after reverting * chore(appflowy_editor): comment out the test for reverting * chore(appflowy_editor): update variable type after reverting * chore(appflowy_editor): remove unused import after reverting * feat(appflowy_editor): double asterisk to bold text * test(appflowy_editor): test double asterisk to bold text * fix(appflowy_editor): delete slash after a selection menu item is selected * test(appflowy_editor): test selection menu widget after clicking * feat(appflowy_editor): double asterisk to bold text and remove slash after clicking selection menu item (#1935) * feat(appflowy_editor): double asterisk to bold text * test(appflowy_editor): test double asterisk to bold text * fix(appflowy_editor): delete slash after a selection menu item is selected * test(appflowy_editor): test selection menu widget after clicking * feat(appflowy_editor): double underscore to bold text * test(appflowy_editor): test double underscore to bold text * chore(appflowy_editor): put checkbox testing back * chore: format code --------- Co-authored-by: Yijing Huang <hyj891204@gmail.com>
This commit is contained in:
parent
1d28bed281
commit
5e8f6a53a0
@ -7,7 +7,7 @@ import 'package:flowy_infra/image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
SelectionMenuItem boardMenuItem = SelectionMenuItem(
|
||||
name: () => LocaleKeys.document_plugins_referencedBoard.tr(),
|
||||
name: LocaleKeys.document_plugins_referencedBoard.tr(),
|
||||
icon: (editorState, onSelected) {
|
||||
return svgWidget(
|
||||
'editor/board',
|
||||
|
@ -7,7 +7,7 @@ import 'package:flowy_infra/image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
SelectionMenuItem gridMenuItem = SelectionMenuItem(
|
||||
name: () => LocaleKeys.document_plugins_referencedGrid.tr(),
|
||||
name: LocaleKeys.document_plugins_referencedGrid.tr(),
|
||||
icon: (editorState, onSelected) {
|
||||
return svgWidget(
|
||||
'editor/grid',
|
||||
|
@ -37,7 +37,7 @@ ShortcutEventHandler _insertHorzaontalRule = (editorState, event) {
|
||||
};
|
||||
|
||||
SelectionMenuItem horizontalRuleMenuItem = SelectionMenuItem(
|
||||
name: () => 'Horizontal rule',
|
||||
name: 'Horizontal rule',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.horizontal_rule,
|
||||
color: onSelected
|
||||
|
@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
SelectionMenuItem autoCompletionMenuItem = SelectionMenuItem(
|
||||
name: () => 'Auto generate content',
|
||||
name: 'Auto generate content',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.rocket,
|
||||
size: 18.0,
|
||||
|
@ -4,7 +4,7 @@ import 'package:example/plugin/AI/text_robot.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
SelectionMenuItem continueToWriteMenuItem = SelectionMenuItem(
|
||||
name: () => 'Continue To Write',
|
||||
name: 'Continue To Write',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.print,
|
||||
size: 18.0,
|
||||
|
@ -37,7 +37,6 @@ class BuiltInAttributeKey {
|
||||
static String checkbox = 'checkbox';
|
||||
static String code = 'code';
|
||||
static String number = 'number';
|
||||
static String defaultFormating = 'defaultFormating';
|
||||
|
||||
static List<String> partialStyleKeys = [
|
||||
BuiltInAttributeKey.bold,
|
||||
|
@ -47,7 +47,7 @@ class _SelectionMenuItemWidgetState extends State<SelectionMenuItemWidget> {
|
||||
: MaterialStateProperty.all(Colors.transparent),
|
||||
),
|
||||
label: Text(
|
||||
widget.item.name(),
|
||||
widget.item.name,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: (widget.isSelected || _onHover)
|
||||
|
@ -156,7 +156,7 @@ List<SelectionMenuItem> get defaultSelectionMenuItems =>
|
||||
_defaultSelectionMenuItems;
|
||||
final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.text,
|
||||
name: AppFlowyEditorLocalizations.current.text,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('text', editorState, onSelected),
|
||||
keywords: ['text'],
|
||||
@ -165,7 +165,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.heading1,
|
||||
name: AppFlowyEditorLocalizations.current.heading1,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('h1', editorState, onSelected),
|
||||
keywords: ['heading 1, h1'],
|
||||
@ -174,7 +174,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.heading2,
|
||||
name: AppFlowyEditorLocalizations.current.heading2,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('h2', editorState, onSelected),
|
||||
keywords: ['heading 2, h2'],
|
||||
@ -183,7 +183,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.heading3,
|
||||
name: AppFlowyEditorLocalizations.current.heading3,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('h3', editorState, onSelected),
|
||||
keywords: ['heading 3, h3'],
|
||||
@ -192,14 +192,14 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.image,
|
||||
name: AppFlowyEditorLocalizations.current.image,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('image', editorState, onSelected),
|
||||
keywords: ['image'],
|
||||
handler: showImageUploadMenu,
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.bulletedList,
|
||||
name: AppFlowyEditorLocalizations.current.bulletedList,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('bulleted_list', editorState, onSelected),
|
||||
keywords: ['bulleted list', 'list', 'unordered list'],
|
||||
@ -208,7 +208,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.numberedList,
|
||||
name: AppFlowyEditorLocalizations.current.numberedList,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('number', editorState, onSelected),
|
||||
keywords: ['numbered list', 'list', 'ordered list'],
|
||||
@ -217,7 +217,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.checkbox,
|
||||
name: AppFlowyEditorLocalizations.current.checkbox,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('checkbox', editorState, onSelected),
|
||||
keywords: ['todo list', 'list', 'checkbox list'],
|
||||
@ -226,7 +226,7 @@ final List<SelectionMenuItem> _defaultSelectionMenuItems = [
|
||||
},
|
||||
),
|
||||
SelectionMenuItem(
|
||||
name: () => AppFlowyEditorLocalizations.current.quote,
|
||||
name: AppFlowyEditorLocalizations.current.quote,
|
||||
icon: (editorState, onSelected) =>
|
||||
_selectionMenuIcon('quote', editorState, onSelected),
|
||||
keywords: ['quote', 'refer'],
|
||||
|
@ -20,14 +20,14 @@ class SelectionMenuItem {
|
||||
required SelectionMenuItemHandler handler,
|
||||
}) {
|
||||
this.handler = (editorState, menuService, context) {
|
||||
_deleteToSlash(editorState);
|
||||
_deleteSlash(editorState);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
handler(editorState, menuService, context);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
final String Function() name;
|
||||
final String name;
|
||||
final Widget Function(EditorState editorState, bool onSelected) icon;
|
||||
|
||||
/// Customizes keywords for item.
|
||||
@ -36,20 +36,23 @@ class SelectionMenuItem {
|
||||
final List<String> keywords;
|
||||
late final SelectionMenuItemHandler handler;
|
||||
|
||||
void _deleteToSlash(EditorState editorState) {
|
||||
void _deleteSlash(EditorState editorState) {
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final selection = selectionService.currentSelection.value;
|
||||
final nodes = selectionService.currentSelectedNodes;
|
||||
if (selection != null && nodes.length == 1) {
|
||||
final node = nodes.first as TextNode;
|
||||
final end = selection.start.offset;
|
||||
final start = node.toPlainText().substring(0, end).lastIndexOf('/');
|
||||
final lastSlashIndex =
|
||||
node.toPlainText().substring(0, end).lastIndexOf('/');
|
||||
// delete all the texts after '/' along with '/'
|
||||
final transaction = editorState.transaction
|
||||
..deleteText(
|
||||
node,
|
||||
start,
|
||||
selection.start.offset - start,
|
||||
lastSlashIndex,
|
||||
end - lastSlashIndex,
|
||||
);
|
||||
|
||||
editorState.apply(transaction);
|
||||
}
|
||||
}
|
||||
@ -81,7 +84,7 @@ class SelectionMenuItem {
|
||||
updateSelection,
|
||||
}) {
|
||||
return SelectionMenuItem(
|
||||
name: () => name,
|
||||
name: name,
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
iconData,
|
||||
color: onSelected
|
||||
|
@ -265,135 +265,6 @@ ShortcutEventHandler markdownLinkOrImageHandler = (editorState, event) {
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
||||
// convert **abc** to bold abc.
|
||||
ShortcutEventHandler doubleAsterisksToBold = (editorState, event) {
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final selection = selectionService.currentSelection.value;
|
||||
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
|
||||
if (selection == null || !selection.isSingle || textNodes.length != 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final textNode = textNodes.first;
|
||||
final text = textNode.toPlainText().substring(0, selection.end.offset);
|
||||
|
||||
// make sure the last two characters are **.
|
||||
if (text.length < 2 || text[selection.end.offset - 1] != '*') {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// find all the index of `*`.
|
||||
final asteriskIndexes = <int>[];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (text[i] == '*') {
|
||||
asteriskIndexes.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (asteriskIndexes.length < 3) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// make sure the second to last and third to last asterisks are connected.
|
||||
final thirdToLastAsteriskIndex = asteriskIndexes[asteriskIndexes.length - 3];
|
||||
final secondToLastAsteriskIndex = asteriskIndexes[asteriskIndexes.length - 2];
|
||||
final lastAsterisIndex = asteriskIndexes[asteriskIndexes.length - 1];
|
||||
if (secondToLastAsteriskIndex != thirdToLastAsteriskIndex + 1 ||
|
||||
lastAsterisIndex == secondToLastAsteriskIndex + 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// delete the last three asterisks.
|
||||
// update the style of the text surround by `** **` to bold.
|
||||
// and update the cursor position.
|
||||
final transaction = editorState.transaction
|
||||
..deleteText(textNode, lastAsterisIndex, 1)
|
||||
..deleteText(textNode, thirdToLastAsteriskIndex, 2)
|
||||
..formatText(
|
||||
textNode,
|
||||
thirdToLastAsteriskIndex,
|
||||
selection.end.offset - thirdToLastAsteriskIndex - 3,
|
||||
{
|
||||
BuiltInAttributeKey.bold: true,
|
||||
BuiltInAttributeKey.defaultFormating: true,
|
||||
},
|
||||
)
|
||||
..afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: textNode.path,
|
||||
offset: selection.end.offset - 3,
|
||||
),
|
||||
);
|
||||
editorState.apply(transaction);
|
||||
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
||||
// convert __abc__ to bold abc.
|
||||
ShortcutEventHandler doubleUnderscoresToBold = (editorState, event) {
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final selection = selectionService.currentSelection.value;
|
||||
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
|
||||
if (selection == null || !selection.isSingle || textNodes.length != 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final textNode = textNodes.first;
|
||||
final text = textNode.toPlainText().substring(0, selection.end.offset);
|
||||
|
||||
// make sure the last two characters are __.
|
||||
if (text.length < 2 || text[selection.end.offset - 1] != '_') {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// find all the index of `_`.
|
||||
final underscoreIndexes = <int>[];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (text[i] == '_') {
|
||||
underscoreIndexes.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (underscoreIndexes.length < 3) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// make sure the second to last and third to last underscores are connected.
|
||||
final thirdToLastUnderscoreIndex =
|
||||
underscoreIndexes[underscoreIndexes.length - 3];
|
||||
final secondToLastUnderscoreIndex =
|
||||
underscoreIndexes[underscoreIndexes.length - 2];
|
||||
final lastAsterisIndex = underscoreIndexes[underscoreIndexes.length - 1];
|
||||
if (secondToLastUnderscoreIndex != thirdToLastUnderscoreIndex + 1 ||
|
||||
lastAsterisIndex == secondToLastUnderscoreIndex + 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// delete the last three underscores.
|
||||
// update the style of the text surround by `__ __` to bold.
|
||||
// and update the cursor position.
|
||||
final transaction = editorState.transaction
|
||||
..deleteText(textNode, lastAsterisIndex, 1)
|
||||
..deleteText(textNode, thirdToLastUnderscoreIndex, 2)
|
||||
..formatText(
|
||||
textNode,
|
||||
thirdToLastUnderscoreIndex,
|
||||
selection.end.offset - thirdToLastUnderscoreIndex - 3,
|
||||
{
|
||||
BuiltInAttributeKey.bold: true,
|
||||
BuiltInAttributeKey.defaultFormating: true,
|
||||
},
|
||||
)
|
||||
..afterSelection = Selection.collapsed(
|
||||
Position(
|
||||
path: textNode.path,
|
||||
offset: selection.end.offset - 3,
|
||||
),
|
||||
);
|
||||
editorState.apply(transaction);
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
||||
ShortcutEventHandler underscoreToItalicHandler = (editorState, event) {
|
||||
// Obtain the selection and selected nodes of the current document through the 'selectionService'
|
||||
// to determine whether the selection is collapsed and whether the selected node is a text node.
|
||||
@ -438,3 +309,117 @@ ShortcutEventHandler underscoreToItalicHandler = (editorState, event) {
|
||||
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
||||
ShortcutEventHandler doubleAsteriskToBoldHanlder = (editorState, event) {
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final selection = selectionService.currentSelection.value;
|
||||
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
|
||||
|
||||
if (selection == null || !selection.isSingle || textNodes.length != 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final textNode = textNodes.first;
|
||||
final text = textNode.toPlainText();
|
||||
|
||||
// make sure the last two characters are '**'
|
||||
if (text.length < 2 || text[selection.end.offset - 1] != '*') {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// find all the index of '*'
|
||||
final asteriskIndexList = <int>[];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (text[i] == '*') {
|
||||
asteriskIndexList.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (asteriskIndexList.length < 3) return KeyEventResult.ignored;
|
||||
|
||||
// make sure the second to last and third to last asterisk are connected
|
||||
final thirdToLastAsteriskIndex =
|
||||
asteriskIndexList[asteriskIndexList.length - 3];
|
||||
final secondToLastAsteriskIndex =
|
||||
asteriskIndexList[asteriskIndexList.length - 2];
|
||||
final lastAsteriskIndex = asteriskIndexList[asteriskIndexList.length - 1];
|
||||
if (secondToLastAsteriskIndex != thirdToLastAsteriskIndex + 1 ||
|
||||
lastAsteriskIndex == secondToLastAsteriskIndex + 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
//delete the last three asterisks
|
||||
//update the style of the text surround by '** **' to bold
|
||||
//update the cursor position
|
||||
final transaction = editorState.transaction
|
||||
..deleteText(textNode, lastAsteriskIndex, 1)
|
||||
..deleteText(textNode, thirdToLastAsteriskIndex, 2)
|
||||
..formatText(textNode, thirdToLastAsteriskIndex,
|
||||
selection.end.offset - thirdToLastAsteriskIndex - 2, {
|
||||
BuiltInAttributeKey.bold: true,
|
||||
})
|
||||
..afterSelection = Selection.collapsed(
|
||||
Position(path: textNode.path, offset: selection.end.offset - 3));
|
||||
|
||||
editorState.apply(transaction);
|
||||
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
||||
//Implement in the same way as doubleAsteriskToBoldHanlder
|
||||
ShortcutEventHandler doubleUnderscoreToBoldHanlder = (editorState, event) {
|
||||
final selectionService = editorState.service.selectionService;
|
||||
final selection = selectionService.currentSelection.value;
|
||||
final textNodes = selectionService.currentSelectedNodes.whereType<TextNode>();
|
||||
|
||||
if (selection == null || !selection.isSingle || textNodes.length != 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
final textNode = textNodes.first;
|
||||
final text = textNode.toPlainText();
|
||||
|
||||
// make sure the last two characters are '__'
|
||||
if (text.length < 2 || text[selection.end.offset - 1] != '_') {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// find all the index of '_'
|
||||
final underscoreIndexList = <int>[];
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (text[i] == '_') {
|
||||
underscoreIndexList.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (underscoreIndexList.length < 3) return KeyEventResult.ignored;
|
||||
|
||||
// make sure the second to last and third to last underscore are connected
|
||||
final thirdToLastUnderscoreIndex =
|
||||
underscoreIndexList[underscoreIndexList.length - 3];
|
||||
final secondToLastUnderscoreIndex =
|
||||
underscoreIndexList[underscoreIndexList.length - 2];
|
||||
final lastUnderscoreIndex =
|
||||
underscoreIndexList[underscoreIndexList.length - 1];
|
||||
if (secondToLastUnderscoreIndex != thirdToLastUnderscoreIndex + 1 ||
|
||||
lastUnderscoreIndex == secondToLastUnderscoreIndex + 1) {
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
//delete the last three underscores
|
||||
//update the style of the text surround by '__ __' to bold
|
||||
//update the cursor position
|
||||
final transaction = editorState.transaction
|
||||
..deleteText(textNode, lastUnderscoreIndex, 1)
|
||||
..deleteText(textNode, thirdToLastUnderscoreIndex, 2)
|
||||
..formatText(textNode, thirdToLastUnderscoreIndex,
|
||||
selection.end.offset - thirdToLastUnderscoreIndex - 2, {
|
||||
BuiltInAttributeKey.bold: true,
|
||||
})
|
||||
..afterSelection = Selection.collapsed(
|
||||
Position(path: textNode.path, offset: selection.end.offset - 3));
|
||||
|
||||
editorState.apply(transaction);
|
||||
|
||||
return KeyEventResult.handled;
|
||||
};
|
||||
|
@ -1,5 +1,3 @@
|
||||
// List<>
|
||||
|
||||
import 'package:appflowy_editor/src/service/internal_key_event_handlers/arrow_keys_handler.dart';
|
||||
import 'package:appflowy_editor/src/service/internal_key_event_handlers/backspace_handler.dart';
|
||||
import 'package:appflowy_editor/src/service/internal_key_event_handlers/copy_paste_handler.dart';
|
||||
@ -284,16 +282,6 @@ List<ShortcutEvent> builtInShortcutEvents = [
|
||||
command: 'tab',
|
||||
handler: tabHandler,
|
||||
),
|
||||
ShortcutEvent(
|
||||
key: 'Double stars to bold',
|
||||
command: 'shift+asterisk',
|
||||
handler: doubleAsterisksToBold,
|
||||
),
|
||||
ShortcutEvent(
|
||||
key: 'Double underscores to bold',
|
||||
command: 'shift+underscore',
|
||||
handler: doubleUnderscoresToBold,
|
||||
),
|
||||
ShortcutEvent(
|
||||
key: 'Backquote to code',
|
||||
command: 'backquote',
|
||||
@ -319,6 +307,16 @@ List<ShortcutEvent> builtInShortcutEvents = [
|
||||
command: 'shift+underscore',
|
||||
handler: underscoreToItalicHandler,
|
||||
),
|
||||
ShortcutEvent(
|
||||
key: 'Double asterisk to bold',
|
||||
command: 'shift+digit 8',
|
||||
handler: doubleAsteriskToBoldHanlder,
|
||||
),
|
||||
ShortcutEvent(
|
||||
key: 'Double underscore to bold',
|
||||
command: 'shift+underscore',
|
||||
handler: doubleUnderscoreToBoldHanlder,
|
||||
),
|
||||
// https://github.com/flutter/flutter/issues/104944
|
||||
// Workaround: Using space editing on the web platform often results in errors,
|
||||
// so adding a shortcut event to handle the space input instead of using the
|
||||
|
@ -142,15 +142,15 @@ extension on LogicalKeyboardKey {
|
||||
if (this == LogicalKeyboardKey.keyZ) {
|
||||
return PhysicalKeyboardKey.keyZ;
|
||||
}
|
||||
if (this == LogicalKeyboardKey.asterisk) {
|
||||
if (this == LogicalKeyboardKey.tilde) {
|
||||
return PhysicalKeyboardKey.backquote;
|
||||
}
|
||||
if (this == LogicalKeyboardKey.digit8) {
|
||||
return PhysicalKeyboardKey.digit8;
|
||||
}
|
||||
if (this == LogicalKeyboardKey.underscore) {
|
||||
return PhysicalKeyboardKey.minus;
|
||||
}
|
||||
if (this == LogicalKeyboardKey.tilde) {
|
||||
return PhysicalKeyboardKey.backquote;
|
||||
}
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ void main() async {
|
||||
});
|
||||
|
||||
// https://github.com/AppFlowy-IO/AppFlowy/issues/1763
|
||||
// [Bug] Mouse unable to click a certain area #1763
|
||||
// // [Bug] Mouse unable to click a certain area #1763
|
||||
testWidgets('insert a new checkbox after an exsiting checkbox',
|
||||
(tester) async {
|
||||
// Before
|
||||
|
@ -10,40 +10,44 @@ void main() async {
|
||||
});
|
||||
|
||||
group('selection_menu_widget.dart', () {
|
||||
for (var i = 0; i < defaultSelectionMenuItems.length; i += 1) {
|
||||
testWidgets('Selects number.$i item in selection menu with enter',
|
||||
(tester) async {
|
||||
final editor = await _prepare(tester);
|
||||
for (var j = 0; j < i; j++) {
|
||||
await editor.pressLogicKey(LogicalKeyboardKey.arrowDown);
|
||||
}
|
||||
// const i = defaultSelectionMenuItems.length;
|
||||
//
|
||||
// Because the `defaultSelectionMenuItems` uses localization,
|
||||
// and the MaterialApp has not been initialized at the time of getting the value,
|
||||
// it will crash.
|
||||
//
|
||||
// Use const value temporarily instead.
|
||||
const i = 7;
|
||||
testWidgets('Selects number.$i item in selection menu with keyboard',
|
||||
(tester) async {
|
||||
final editor = await _prepare(tester);
|
||||
for (var j = 0; j < i; j++) {
|
||||
await editor.pressLogicKey(LogicalKeyboardKey.arrowDown);
|
||||
}
|
||||
|
||||
await editor.pressLogicKey(LogicalKeyboardKey.enter);
|
||||
expect(
|
||||
find.byType(SelectionMenuWidget, skipOffstage: false),
|
||||
findsNothing,
|
||||
);
|
||||
if (defaultSelectionMenuItems[i].name() != 'Image') {
|
||||
await _testDefaultSelectionMenuItems(i, editor);
|
||||
}
|
||||
});
|
||||
await editor.pressLogicKey(LogicalKeyboardKey.enter);
|
||||
expect(
|
||||
find.byType(SelectionMenuWidget, skipOffstage: false),
|
||||
findsNothing,
|
||||
);
|
||||
if (defaultSelectionMenuItems[i].name != 'Image') {
|
||||
await _testDefaultSelectionMenuItems(i, editor);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('Selects number.$i item in selection menu with click',
|
||||
(tester) async {
|
||||
final editor = await _prepare(tester);
|
||||
|
||||
await tester.tap(find.byType(SelectionMenuItemWidget).at(i));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.byType(SelectionMenuWidget, skipOffstage: false),
|
||||
findsNothing,
|
||||
);
|
||||
if (defaultSelectionMenuItems[i].name() != 'Image') {
|
||||
await _testDefaultSelectionMenuItems(i, editor);
|
||||
}
|
||||
});
|
||||
}
|
||||
testWidgets('Selects number.$i item in selection menu with clicking',
|
||||
(tester) async {
|
||||
final editor = await _prepare(tester);
|
||||
await tester.tap(find.byType(SelectionMenuItemWidget).at(i));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.byType(SelectionMenuWidget, skipOffstage: false),
|
||||
findsNothing,
|
||||
);
|
||||
if (defaultSelectionMenuItems[i].name != 'Image') {
|
||||
await _testDefaultSelectionMenuItems(i, editor);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('Search item in selection menu util no results',
|
||||
(tester) async {
|
||||
@ -136,7 +140,7 @@ Future<EditorWidgetTester> _prepare(WidgetTester tester) async {
|
||||
);
|
||||
|
||||
for (final item in defaultSelectionMenuItems) {
|
||||
expect(find.text(item.name()), findsOneWidget);
|
||||
expect(find.text(item.name), findsOneWidget);
|
||||
}
|
||||
|
||||
return Future.value(editor);
|
||||
@ -146,28 +150,31 @@ Future<void> _testDefaultSelectionMenuItems(
|
||||
int index, EditorWidgetTester editor) async {
|
||||
expect(editor.documentLength, 4);
|
||||
expect(editor.documentSelection, Selection.single(path: [2], startOffset: 0));
|
||||
expect((editor.nodeAtPath([0]) as TextNode).toPlainText(),
|
||||
'Welcome to Appflowy 😁');
|
||||
expect((editor.nodeAtPath([1]) as TextNode).toPlainText(),
|
||||
'Welcome to Appflowy 😁');
|
||||
final node = editor.nodeAtPath([2]);
|
||||
final item = defaultSelectionMenuItems[index];
|
||||
final itemName = item.name();
|
||||
if (itemName == 'Text') {
|
||||
if (item.name == 'Text') {
|
||||
expect(node?.subtype == null, true);
|
||||
} else if (itemName == 'Heading 1') {
|
||||
expect(node?.toString(), null);
|
||||
} else if (item.name == 'Heading 1') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.heading);
|
||||
expect(node?.attributes.heading, BuiltInAttributeKey.h1);
|
||||
} else if (itemName == 'Heading 2') {
|
||||
expect(node?.toString(), null);
|
||||
} else if (item.name == 'Heading 2') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.heading);
|
||||
expect(node?.attributes.heading, BuiltInAttributeKey.h2);
|
||||
} else if (itemName == 'Heading 3') {
|
||||
expect(node?.toString(), null);
|
||||
} else if (item.name == 'Heading 3') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.heading);
|
||||
expect(node?.attributes.heading, BuiltInAttributeKey.h3);
|
||||
} else if (itemName == 'Bulleted list') {
|
||||
expect(node?.toString(), null);
|
||||
} else if (item.name == 'Bulleted list') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.bulletedList);
|
||||
} else if (itemName == 'Checkbox') {
|
||||
} else if (item.name == 'Checkbox') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.checkbox);
|
||||
expect(node?.attributes.check, false);
|
||||
} else if (itemName == 'Quote') {
|
||||
expect(node?.subtype, BuiltInAttributeKey.quote);
|
||||
}
|
||||
}
|
||||
|
@ -1,277 +0,0 @@
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/extensions/text_node_extensions.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import '../../infra/test_editor.dart';
|
||||
|
||||
void main() async {
|
||||
setUpAll(() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
|
||||
group('markdown_syntax_to_styled_text_handler.dart', () {
|
||||
group('convert double asterisks to bold', () {
|
||||
Future<void> insertAsterisk(
|
||||
EditorWidgetTester editor, {
|
||||
int repeat = 1,
|
||||
}) async {
|
||||
for (var i = 0; i < repeat; i++) {
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.asterisk,
|
||||
isShiftPressed: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets('**AppFlowy** to bold AppFlowy', (tester) async {
|
||||
const text = '**AppFlowy*';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertAsterisk(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('App**Flowy** to bold AppFlowy', (tester) async {
|
||||
const text = 'App**Flowy*';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertAsterisk(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 3,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('***AppFlowy** to bold *AppFlowy', (tester) async {
|
||||
const text = '***AppFlowy*';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertAsterisk(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 1,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), '*AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('**AppFlowy** application to bold AppFlowy only',
|
||||
(tester) async {
|
||||
const boldText = '**AppFlowy*';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
|
||||
for (var i = 0; i < boldText.length; i++) {
|
||||
await editor.insertText(textNode, boldText[i], i);
|
||||
}
|
||||
await insertAsterisk(editor);
|
||||
final boldTextLength = boldText.replaceAll('*', '').length;
|
||||
final appFlowyBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: boldTextLength,
|
||||
),
|
||||
);
|
||||
expect(appFlowyBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('**** nothing changes', (tester) async {
|
||||
const text = '***';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertAsterisk(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, false);
|
||||
expect(textNode.toPlainText(), text);
|
||||
});
|
||||
});
|
||||
|
||||
group('convert double underscores to bold', () {
|
||||
Future<void> insertUnderscore(
|
||||
EditorWidgetTester editor, {
|
||||
int repeat = 1,
|
||||
}) async {
|
||||
for (var i = 0; i < repeat; i++) {
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.underscore,
|
||||
isShiftPressed: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets('__AppFlowy__ to bold AppFlowy', (tester) async {
|
||||
const text = '__AppFlowy_';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertUnderscore(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('App__Flowy__ to bold AppFlowy', (tester) async {
|
||||
const text = 'App__Flowy_';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertUnderscore(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 3,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('___AppFlowy__ to bold _AppFlowy', (tester) async {
|
||||
const text = '___AppFlowy_';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertUnderscore(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 1,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), '_AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('__AppFlowy__ application to bold AppFlowy only',
|
||||
(tester) async {
|
||||
const boldText = '__AppFlowy_';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
|
||||
for (var i = 0; i < boldText.length; i++) {
|
||||
await editor.insertText(textNode, boldText[i], i);
|
||||
}
|
||||
await insertUnderscore(editor);
|
||||
final boldTextLength = boldText.replaceAll('_', '').length;
|
||||
final appFlowyBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: boldTextLength,
|
||||
),
|
||||
);
|
||||
expect(appFlowyBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
});
|
||||
|
||||
testWidgets('____ nothing changes', (tester) async {
|
||||
const text = '___';
|
||||
final editor = tester.editor..insertTextNode('');
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(
|
||||
Selection.single(path: [0], startOffset: 0),
|
||||
);
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
await insertUnderscore(editor);
|
||||
final allBold = textNode.allSatisfyBoldInSelection(
|
||||
Selection.single(
|
||||
path: [0],
|
||||
startOffset: 0,
|
||||
endOffset: textNode.toPlainText().length,
|
||||
),
|
||||
);
|
||||
expect(allBold, false);
|
||||
expect(textNode.toPlainText(), text);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -257,4 +257,192 @@ void main() async {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('convert double asterisk to bold', () {
|
||||
Future<void> insertAsterisk(
|
||||
EditorWidgetTester editor, {
|
||||
int repeat = 1,
|
||||
}) async {
|
||||
for (var i = 0; i < repeat; i++) {
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.digit8,
|
||||
isShiftPressed: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets('**AppFlowy** to bold AppFlowy', ((widgetTester) async {
|
||||
const text = '**AppFlowy*';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertAsterisk(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 0, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('App**Flowy** to bold AppFlowy', ((widgetTester) async {
|
||||
const text = 'App**Flowy*';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertAsterisk(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 3, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('***AppFlowy** to bold *AppFlowy', ((widgetTester) async {
|
||||
const text = '***AppFlowy*';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertAsterisk(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 1, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), '*AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('**** nothing changes', ((widgetTester) async {
|
||||
const text = '***';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertAsterisk(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 0, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, false);
|
||||
expect(textNode.toPlainText(), text);
|
||||
}));
|
||||
});
|
||||
|
||||
group('convert double underscore to bold', () {
|
||||
Future<void> insertUnderscore(
|
||||
EditorWidgetTester editor, {
|
||||
int repeat = 1,
|
||||
}) async {
|
||||
for (var i = 0; i < repeat; i++) {
|
||||
await editor.pressLogicKey(
|
||||
LogicalKeyboardKey.underscore,
|
||||
isShiftPressed: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets('__AppFlowy__ to bold AppFlowy', ((widgetTester) async {
|
||||
const text = '__AppFlowy_';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertUnderscore(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 0, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('App__Flowy__ to bold AppFlowy', ((widgetTester) async {
|
||||
const text = 'App__Flowy_';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertUnderscore(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 3, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), 'AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('__*AppFlowy__ to bold *AppFlowy', ((widgetTester) async {
|
||||
const text = '__*AppFlowy_';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertUnderscore(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 1, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, true);
|
||||
expect(textNode.toPlainText(), '*AppFlowy');
|
||||
}));
|
||||
|
||||
testWidgets('____ nothing changes', ((widgetTester) async {
|
||||
const text = '___';
|
||||
final editor = widgetTester.editor..insertTextNode('');
|
||||
|
||||
await editor.startTesting();
|
||||
await editor.updateSelection(Selection.single(path: [0], startOffset: 0));
|
||||
final textNode = editor.nodeAtPath([0]) as TextNode;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
await editor.insertText(textNode, text[i], i);
|
||||
}
|
||||
|
||||
await insertUnderscore(editor);
|
||||
|
||||
final allBold = textNode.allSatisfyBoldInSelection(Selection.single(
|
||||
path: [0], startOffset: 0, endOffset: textNode.toPlainText().length));
|
||||
|
||||
expect(allBold, false);
|
||||
expect(textNode.toPlainText(), text);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ void main() async {
|
||||
);
|
||||
|
||||
for (final item in defaultSelectionMenuItems) {
|
||||
expect(find.text(item.name()), findsOneWidget);
|
||||
expect(find.text(item.name), findsOneWidget);
|
||||
}
|
||||
|
||||
await editor.updateSelection(Selection.single(path: [1], startOffset: 0));
|
||||
|
@ -79,7 +79,7 @@ ShortcutEventHandler _pasteHandler = (editorState, event) {
|
||||
};
|
||||
|
||||
SelectionMenuItem codeBlockMenuItem = SelectionMenuItem(
|
||||
name: () => 'Code Block',
|
||||
name: 'Code Block',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.abc,
|
||||
color: onSelected
|
||||
|
@ -34,7 +34,7 @@ ShortcutEventHandler _insertDividerHandler = (editorState, event) {
|
||||
};
|
||||
|
||||
SelectionMenuItem dividerMenuItem = SelectionMenuItem(
|
||||
name: () => 'Divider',
|
||||
name: 'Divider',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.horizontal_rule,
|
||||
color: onSelected
|
||||
|
@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
|
||||
import 'emoji_picker.dart';
|
||||
|
||||
SelectionMenuItem emojiMenuItem = SelectionMenuItem(
|
||||
name: () => 'Emoji',
|
||||
name: 'Emoji',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.emoji_emotions_outlined,
|
||||
color: onSelected
|
||||
|
@ -7,7 +7,7 @@ const String kMathEquationType = 'math_equation';
|
||||
const String kMathEquationAttr = 'math_equation';
|
||||
|
||||
SelectionMenuItem mathEquationMenuItem = SelectionMenuItem(
|
||||
name: () => 'Math Equation',
|
||||
name: 'Math Equation',
|
||||
icon: (editorState, onSelected) => Icon(
|
||||
Icons.text_fields_rounded,
|
||||
color: onSelected
|
||||
|
Loading…
Reference in New Issue
Block a user