feat: enable toggling and canceling of the formatting with shortcuts (#528)
This commit is contained in:
parent
8a04d99529
commit
b17bddceb8
6 changed files with 153 additions and 16 deletions
|
|
@ -195,6 +195,7 @@ extension TextTransaction on Transaction {
|
|||
int index,
|
||||
String text, {
|
||||
Attributes? attributes,
|
||||
Attributes? toggledAttributes,
|
||||
}) {
|
||||
final delta = node.delta;
|
||||
if (delta == null) {
|
||||
|
|
@ -207,7 +208,11 @@ extension TextTransaction on Transaction {
|
|||
'The index($index) is out of range or negative.',
|
||||
);
|
||||
|
||||
final newAttributes = attributes ?? delta.sliceAttributes(index);
|
||||
final newAttributes = attributes ?? delta.sliceAttributes(index) ?? {};
|
||||
|
||||
if (toggledAttributes != null) {
|
||||
newAttributes.addAll(toggledAttributes);
|
||||
}
|
||||
|
||||
final insert = Delta()
|
||||
..retain(index)
|
||||
|
|
@ -316,6 +321,7 @@ extension TextTransaction on Transaction {
|
|||
return;
|
||||
}
|
||||
afterSelection = beforeSelection;
|
||||
|
||||
final format = Delta()
|
||||
..retain(index)
|
||||
..retain(length, attributes: attributes);
|
||||
|
|
|
|||
|
|
@ -19,4 +19,13 @@ class AppFlowyRichTextKeys {
|
|||
textColor,
|
||||
highlightColor,
|
||||
];
|
||||
|
||||
// The values supported toggled even if the selection is collapsed.
|
||||
static List<String> supportToggled = [
|
||||
bold,
|
||||
italic,
|
||||
underline,
|
||||
strikethrough,
|
||||
code,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
|
||||
extension TextTransforms on EditorState {
|
||||
|
|
@ -185,18 +187,37 @@ extension TextTransforms on EditorState {
|
|||
if (selection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final nodes = getNodesInSelection(selection);
|
||||
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.everyAttributes(
|
||||
(attributes) => attributes[key] == true,
|
||||
if (selection.isCollapsed) {
|
||||
// get the attributes from the previous one character.
|
||||
selection = selection.copyWith(
|
||||
start: selection.start.copyWith(
|
||||
offset: max(
|
||||
selection.startIndex - 1,
|
||||
0,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
await formatDelta(
|
||||
selection,
|
||||
{
|
||||
key: !isHighlight,
|
||||
},
|
||||
);
|
||||
final toggled = nodes.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.everyAttributes(
|
||||
(attributes) => attributes[key] == true,
|
||||
);
|
||||
});
|
||||
toggledStyle[key] = !toggled;
|
||||
} else {
|
||||
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
||||
return delta.everyAttributes(
|
||||
(attributes) => attributes[key] == true,
|
||||
);
|
||||
});
|
||||
await formatDelta(
|
||||
selection,
|
||||
{
|
||||
key: !isHighlight,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// format the node at the given selection.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:appflowy_editor/src/editor/editor_component/service/ime/character_shortcut_event_helper.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
Future<void> onInsert(
|
||||
|
|
@ -42,11 +43,21 @@ Future<void> onInsert(
|
|||
}
|
||||
assert(node.delta != null);
|
||||
|
||||
if (kDebugMode) {
|
||||
// verify the toggled keys are supported.
|
||||
assert(
|
||||
editorState.toggledStyle.keys.every(
|
||||
(element) => AppFlowyRichTextKeys.supportToggled.contains(element),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final transaction = editorState.transaction
|
||||
..insertText(
|
||||
node,
|
||||
selection.startIndex,
|
||||
insertion.textInserted,
|
||||
toggledAttributes: editorState.toggledStyle,
|
||||
);
|
||||
return editorState.apply(transaction);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,35 +24,50 @@ final CommandShortcutEvent toggleBoldCommand = CommandShortcutEvent(
|
|||
key: 'toggle bold',
|
||||
command: 'ctrl+b',
|
||||
macOSCommand: 'cmd+b',
|
||||
handler: (editorState) => _toggleAttribute(editorState, 'bold'),
|
||||
handler: (editorState) => _toggleAttribute(
|
||||
editorState,
|
||||
AppFlowyRichTextKeys.bold,
|
||||
),
|
||||
);
|
||||
|
||||
final CommandShortcutEvent toggleItalicCommand = CommandShortcutEvent(
|
||||
key: 'toggle italic',
|
||||
command: 'ctrl+i',
|
||||
macOSCommand: 'cmd+i',
|
||||
handler: (editorState) => _toggleAttribute(editorState, 'italic'),
|
||||
handler: (editorState) => _toggleAttribute(
|
||||
editorState,
|
||||
AppFlowyRichTextKeys.italic,
|
||||
),
|
||||
);
|
||||
|
||||
final CommandShortcutEvent toggleUnderlineCommand = CommandShortcutEvent(
|
||||
key: 'toggle underline',
|
||||
command: 'ctrl+u',
|
||||
macOSCommand: 'cmd+u',
|
||||
handler: (editorState) => _toggleAttribute(editorState, 'underline'),
|
||||
handler: (editorState) => _toggleAttribute(
|
||||
editorState,
|
||||
AppFlowyRichTextKeys.underline,
|
||||
),
|
||||
);
|
||||
|
||||
final CommandShortcutEvent toggleStrikethroughCommand = CommandShortcutEvent(
|
||||
key: 'toggle strikethrough',
|
||||
command: 'ctrl+shift+s',
|
||||
macOSCommand: 'cmd+shift+s',
|
||||
handler: (editorState) => _toggleAttribute(editorState, 'strikethrough'),
|
||||
handler: (editorState) => _toggleAttribute(
|
||||
editorState,
|
||||
AppFlowyRichTextKeys.strikethrough,
|
||||
),
|
||||
);
|
||||
|
||||
final CommandShortcutEvent toggleCodeCommand = CommandShortcutEvent(
|
||||
key: 'toggle code',
|
||||
command: 'ctrl+e',
|
||||
macOSCommand: 'cmd+e',
|
||||
handler: (editorState) => _toggleAttribute(editorState, 'code'),
|
||||
handler: (editorState) => _toggleAttribute(
|
||||
editorState,
|
||||
AppFlowyRichTextKeys.code,
|
||||
),
|
||||
);
|
||||
|
||||
KeyEventResult _toggleAttribute(
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ class EditorState {
|
|||
|
||||
/// Sets the selection of the editor.
|
||||
set selection(Selection? value) {
|
||||
// clear the toggled style when the selection is changed.
|
||||
toggledStyle.clear();
|
||||
|
||||
selectionNotifier.value = value;
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +148,13 @@ class EditorState {
|
|||
sync: true,
|
||||
);
|
||||
|
||||
/// Store the toggled format style, like bold, italic, etc.
|
||||
/// All the values must be the key from [AppFlowyRichTextKeys.supportToggled].
|
||||
///
|
||||
/// NOTES: It only works once;
|
||||
/// after the selection is changed, the toggled style will be cleared.
|
||||
final toggledStyle = <String, bool>{};
|
||||
|
||||
final UndoManager undoManager = UndoManager();
|
||||
|
||||
Transaction get transaction {
|
||||
|
|
|
|||
Loading…
Reference in a new issue