mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: implement heading, quote, bulleted_list in toolbar service
This commit is contained in:
parent
b11a127432
commit
9b6afcc5c9
@ -21,7 +21,7 @@ class CheckboxNodeWidgetBuilder extends NodeWidgetBuilder<TextNode> {
|
||||
|
||||
@override
|
||||
NodeValidator<Node> get nodeValidator => ((node) {
|
||||
return node.attributes.containsKey(StyleKey.check);
|
||||
return node.attributes.containsKey(StyleKey.checkbox);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -25,26 +25,48 @@ class StyleKey {
|
||||
static String font = 'font';
|
||||
static String href = 'href';
|
||||
|
||||
static String quote = 'quote';
|
||||
static String list = 'list';
|
||||
static String number = 'number';
|
||||
static String todo = 'todo';
|
||||
static String code = 'code';
|
||||
|
||||
static String subtype = 'subtype';
|
||||
static String check = 'checkbox';
|
||||
static String heading = 'heading';
|
||||
static String h1 = 'h1';
|
||||
static String h2 = 'h2';
|
||||
static String h3 = 'h3';
|
||||
static String h4 = 'h4';
|
||||
static String h5 = 'h5';
|
||||
static String h6 = 'h6';
|
||||
|
||||
static String bulletedList = 'bulleted-list';
|
||||
static String numberList = 'number-list';
|
||||
|
||||
static String quote = 'quote';
|
||||
static String checkbox = 'checkbox';
|
||||
static String code = 'code';
|
||||
static String number = 'number';
|
||||
|
||||
static List<String> partialStyleKeys = [
|
||||
StyleKey.bold,
|
||||
StyleKey.italic,
|
||||
StyleKey.underline,
|
||||
StyleKey.strikethrough,
|
||||
];
|
||||
|
||||
static List<String> globalStyleKeys = [
|
||||
StyleKey.heading,
|
||||
StyleKey.bulletedList,
|
||||
StyleKey.numberList,
|
||||
StyleKey.quote,
|
||||
StyleKey.code,
|
||||
];
|
||||
}
|
||||
|
||||
double baseFontSize = 16.0;
|
||||
// TODO: customize.
|
||||
Map<String, double> headingToFontSize = {
|
||||
'h1': baseFontSize + 15,
|
||||
'h2': baseFontSize + 12,
|
||||
'h3': baseFontSize + 9,
|
||||
'h4': baseFontSize + 6,
|
||||
'h5': baseFontSize + 3,
|
||||
'h6': baseFontSize,
|
||||
StyleKey.h1: baseFontSize + 15,
|
||||
StyleKey.h2: baseFontSize + 12,
|
||||
StyleKey.h3: baseFontSize + 9,
|
||||
StyleKey.h4: baseFontSize + 6,
|
||||
StyleKey.h5: baseFontSize + 3,
|
||||
StyleKey.h6: baseFontSize,
|
||||
};
|
||||
|
||||
extension NodeAttributesExtensions on Attributes {
|
||||
@ -73,13 +95,6 @@ extension NodeAttributesExtensions on Attributes {
|
||||
return null;
|
||||
}
|
||||
|
||||
String? get list {
|
||||
if (containsKey(StyleKey.list) && this[StyleKey.list] is String) {
|
||||
return this[StyleKey.list];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int? get number {
|
||||
if (containsKey(StyleKey.number) && this[StyleKey.number] is int) {
|
||||
return this[StyleKey.number];
|
||||
@ -87,13 +102,6 @@ extension NodeAttributesExtensions on Attributes {
|
||||
return null;
|
||||
}
|
||||
|
||||
bool get todo {
|
||||
if (containsKey(StyleKey.todo) && this[StyleKey.todo] is bool) {
|
||||
return this[StyleKey.todo];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get code {
|
||||
if (containsKey(StyleKey.code) && this[StyleKey.code] == true) {
|
||||
return this[StyleKey.code];
|
||||
@ -102,8 +110,8 @@ extension NodeAttributesExtensions on Attributes {
|
||||
}
|
||||
|
||||
bool get check {
|
||||
if (containsKey(StyleKey.check) && this[StyleKey.check] is bool) {
|
||||
return this[StyleKey.check];
|
||||
if (containsKey(StyleKey.checkbox) && this[StyleKey.checkbox] is bool) {
|
||||
return this[StyleKey.checkbox];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flowy_editor/editor_state.dart';
|
||||
import 'package:flowy_editor/infra/flowy_svg.dart';
|
||||
import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
|
||||
import 'package:flowy_editor/service/default_text_operations/format_rich_text_style.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
typedef ToolbarEventHandler = void Function(EditorState editorState);
|
||||
|
||||
@ -13,17 +14,20 @@ ToolbarEventHandlers defaultToolbarEventHandlers = {
|
||||
'italic': (editorState) => formatItalic(editorState),
|
||||
'strikethrough': (editorState) => formatStrikethrough(editorState),
|
||||
'underline': (editorState) => formatUnderline(editorState),
|
||||
'quote': ((editorState) {}),
|
||||
'number_list': ((editorState) {}),
|
||||
'bulleted_list': ((editorState) {}),
|
||||
'quote': (editorState) => formatQuote(editorState),
|
||||
'number_list': (editorState) {},
|
||||
'bulleted_list': (editorState) => formatBulletedList(editorState),
|
||||
'H1': (editorState) => formatHeading(editorState, StyleKey.h1),
|
||||
'H2': (editorState) => formatHeading(editorState, StyleKey.h2),
|
||||
'H3': (editorState) => formatHeading(editorState, StyleKey.h3),
|
||||
};
|
||||
|
||||
List<String> defaultListToolbarEventNames = [
|
||||
'H1',
|
||||
'H2',
|
||||
'H3',
|
||||
'B-List',
|
||||
'N-List',
|
||||
// 'B-List',
|
||||
// 'N-List',
|
||||
];
|
||||
|
||||
class ToolbarWidget extends StatefulWidget {
|
||||
|
@ -1,27 +1,77 @@
|
||||
import 'package:flowy_editor/document/attributes.dart';
|
||||
import 'package:flowy_editor/document/node.dart';
|
||||
import 'package:flowy_editor/editor_state.dart';
|
||||
import 'package:flowy_editor/extensions/text_node_extensions.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';
|
||||
|
||||
void formatHeading(EditorState editorState, String heading) {
|
||||
formatTextNodes(editorState, {
|
||||
StyleKey.subtype: StyleKey.heading,
|
||||
StyleKey.heading: heading,
|
||||
});
|
||||
}
|
||||
|
||||
void formatQuote(EditorState editorState) {
|
||||
formatTextNodes(editorState, {
|
||||
StyleKey.subtype: StyleKey.quote,
|
||||
});
|
||||
}
|
||||
|
||||
void formatCheckbox(EditorState editorState) {
|
||||
formatTextNodes(editorState, {
|
||||
StyleKey.subtype: StyleKey.checkbox,
|
||||
StyleKey.checkbox: false,
|
||||
});
|
||||
}
|
||||
|
||||
void formatBulletedList(EditorState editorState) {
|
||||
formatTextNodes(editorState, {
|
||||
StyleKey.subtype: StyleKey.bulletedList,
|
||||
});
|
||||
}
|
||||
|
||||
bool formatTextNodes(EditorState editorState, Attributes attributes) {
|
||||
final nodes = editorState.service.selectionService.currentSelectedNodes.value;
|
||||
final textNodes = nodes.whereType<TextNode>().toList();
|
||||
|
||||
if (textNodes.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final builder = TransactionBuilder(editorState);
|
||||
|
||||
for (final textNode in textNodes) {
|
||||
builder.updateNode(
|
||||
textNode,
|
||||
Attributes.fromIterable(
|
||||
StyleKey.globalStyleKeys,
|
||||
value: (_) => null,
|
||||
)..addAll(attributes),
|
||||
);
|
||||
}
|
||||
|
||||
builder.commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool formatBold(EditorState editorState) {
|
||||
return formatRichText(editorState, StyleKey.bold);
|
||||
return formatRichTextPartialStyle(editorState, StyleKey.bold);
|
||||
}
|
||||
|
||||
bool formatItalic(EditorState editorState) {
|
||||
return formatRichText(editorState, StyleKey.italic);
|
||||
return formatRichTextPartialStyle(editorState, StyleKey.italic);
|
||||
}
|
||||
|
||||
bool formatUnderline(EditorState editorState) {
|
||||
return formatRichText(editorState, StyleKey.underline);
|
||||
return formatRichTextPartialStyle(editorState, StyleKey.underline);
|
||||
}
|
||||
|
||||
bool formatStrikethrough(EditorState editorState) {
|
||||
return formatRichText(editorState, StyleKey.strikethrough);
|
||||
return formatRichTextPartialStyle(editorState, StyleKey.strikethrough);
|
||||
}
|
||||
|
||||
bool formatRichText(EditorState editorState, String styleKey) {
|
||||
bool formatRichTextPartialStyle(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);
|
||||
|
Loading…
Reference in New Issue
Block a user