feat: implement italic, strikethrough and underline in toolbar service

This commit is contained in:
Lucas.Xu 2022-08-02 11:01:58 +08:00
parent ba78f0073d
commit b11a127432
5 changed files with 53 additions and 13 deletions

View File

@ -26,7 +26,7 @@ Attributes? composeAttributes(Attributes? a, Attributes? b) {
a ??= {}; a ??= {};
b ??= {}; b ??= {};
final Attributes attributes = {}; final Attributes attributes = {};
attributes.addAll(b); attributes.addAll(Map.from(b)..removeWhere((_, value) => value == null));
for (final entry in a.entries) { for (final entry in a.entries) {
if (!b.containsKey(entry.key)) { if (!b.containsKey(entry.key)) {

View File

@ -89,8 +89,12 @@ class Node extends ChangeNotifier with LinkedListEntry<Node> {
this.attributes['subtype'] != attributes['subtype']; this.attributes['subtype'] != attributes['subtype'];
for (final attribute in attributes.entries) { for (final attribute in attributes.entries) {
if (attribute.value == null) {
this.attributes.remove(attribute.key);
} else {
this.attributes[attribute.key] = attribute.value; this.attributes[attribute.key] = attribute.value;
} }
}
// Notify the new attributes // Notify the new attributes
// if attributes contains 'subtype', should notify parent to rebuild node // if attributes contains 'subtype', should notify parent to rebuild node
// else, just notify current node. // else, just notify current node.

View File

@ -9,12 +9,10 @@ typedef ToolbarEventHandler = void Function(EditorState editorState);
typedef ToolbarEventHandlers = Map<String, ToolbarEventHandler>; typedef ToolbarEventHandlers = Map<String, ToolbarEventHandler>;
ToolbarEventHandlers defaultToolbarEventHandlers = { ToolbarEventHandlers defaultToolbarEventHandlers = {
'bold': ((editorState) { 'bold': (editorState) => formatBold(editorState),
formatRichTextStyle(editorState, {StyleKey.bold: true}); 'italic': (editorState) => formatItalic(editorState),
}), 'strikethrough': (editorState) => formatStrikethrough(editorState),
'italic': ((editorState) {}), 'underline': (editorState) => formatUnderline(editorState),
'strikethrough': ((editorState) {}),
'underline': ((editorState) {}),
'quote': ((editorState) {}), 'quote': ((editorState) {}),
'number_list': ((editorState) {}), 'number_list': ((editorState) {}),
'bulleted_list': ((editorState) {}), 'bulleted_list': ((editorState) {}),

View File

@ -1,9 +1,49 @@
import 'package:flowy_editor/document/attributes.dart';
import 'package:flowy_editor/document/node.dart'; import 'package:flowy_editor/document/node.dart';
import 'package:flowy_editor/editor_state.dart'; import 'package:flowy_editor/editor_state.dart';
import 'package:flowy_editor/operation/transaction_builder.dart'; import 'package:flowy_editor/operation/transaction_builder.dart';
import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
import 'package:flowy_editor/extensions/text_node_extensions.dart';
bool formatRichTextStyle( bool formatBold(EditorState editorState) {
EditorState editorState, Map<String, dynamic> attributes) { return formatRichText(editorState, StyleKey.bold);
}
bool formatItalic(EditorState editorState) {
return formatRichText(editorState, StyleKey.italic);
}
bool formatUnderline(EditorState editorState) {
return formatRichText(editorState, StyleKey.underline);
}
bool formatStrikethrough(EditorState editorState) {
return formatRichText(editorState, StyleKey.strikethrough);
}
bool formatRichText(EditorState editorState, String styleKey) {
final selection = editorState.service.selectionService.currentSelection;
final nodes = editorState.service.selectionService.currentSelectedNodes.value;
final textNodes = nodes.whereType<TextNode>().toList(growable: false);
if (selection == null || textNodes.isEmpty) {
return false;
}
bool value = !textNodes.allSatisfyInSelection(styleKey, selection);
Attributes attributes = {
styleKey: value,
};
if (styleKey == StyleKey.underline && value) {
attributes[StyleKey.strikethrough] = null;
} else if (styleKey == StyleKey.strikethrough && value) {
attributes[StyleKey.underline] = null;
}
return formatRichTextStyle(editorState, attributes);
}
bool formatRichTextStyle(EditorState editorState, Attributes attributes) {
final selection = editorState.service.selectionService.currentSelection; final selection = editorState.service.selectionService.currentSelection;
final nodes = editorState.service.selectionService.currentSelectedNodes.value; final nodes = editorState.service.selectionService.currentSelectedNodes.value;
final textNodes = nodes.whereType<TextNode>().toList(); final textNodes = nodes.whereType<TextNode>().toList();

View File

@ -23,9 +23,7 @@ FlowyKeyEventHandler updateTextStyleByCommandXHandler = (editorState, event) {
// bold // bold
case 'B': case 'B':
case 'b': case 'b':
formatRichTextStyle(editorState, { formatBold(editorState);
StyleKey.bold: !textNodes.allSatisfyBoldInSelection(selection),
});
return KeyEventResult.handled; return KeyEventResult.handled;
default: default:
break; break;