mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: decorate TextSpan with global style
This commit is contained in:
parent
985fe14a8b
commit
612e3dd50f
@ -13,10 +13,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "🌶 Read Me",
|
||||
"attributes": {
|
||||
"heading": "h1"
|
||||
}
|
||||
"insert": "🌶 Read Me"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
@ -27,10 +24,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "👋 Welcome to Appflowy",
|
||||
"attributes": {
|
||||
"heading": "h2"
|
||||
}
|
||||
"insert": "👋 Welcome to Appflowy"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
@ -41,10 +35,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "Here are the basics:",
|
||||
"attributes": {
|
||||
"heading": "h3"
|
||||
}
|
||||
"insert": "Here are the basics:"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
@ -102,10 +93,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "Here are the examples:",
|
||||
"attributes": {
|
||||
"heading": "h3"
|
||||
}
|
||||
"insert": "Here are the examples:"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
@ -149,8 +137,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "Hello world",
|
||||
"attributes": { "quote": true }
|
||||
"insert": "Hello world"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
@ -161,8 +148,7 @@
|
||||
"type": "text",
|
||||
"delta": [
|
||||
{
|
||||
"insert": "Hello world",
|
||||
"attributes": { "quote": true }
|
||||
"insert": "Hello world"
|
||||
}
|
||||
],
|
||||
"attributes": {
|
||||
|
@ -169,7 +169,7 @@ class _FlowyRichTextState extends State<FlowyRichText> with Selectable {
|
||||
return SizedBox(
|
||||
width:
|
||||
MediaQuery.of(context).size.width - 20, // FIXME: use the const value
|
||||
child: RichText(key: _textKey, text: _textSpan),
|
||||
child: RichText(key: _textKey, text: _decorateTextSpanWithGlobalStyle),
|
||||
);
|
||||
}
|
||||
|
||||
@ -255,6 +255,22 @@ class _FlowyRichTextState extends State<FlowyRichText> with Selectable {
|
||||
return Rect.zero;
|
||||
}
|
||||
|
||||
TextSpan get _decorateTextSpanWithGlobalStyle => TextSpan(
|
||||
children: _textSpan.children
|
||||
?.whereType<TextSpan>()
|
||||
.map(
|
||||
(span) => TextSpan(
|
||||
text: span.text,
|
||||
style: span.style?.copyWith(
|
||||
fontSize: _textNode.attributes.fontSize,
|
||||
color: _textNode.attributes.quoteColor,
|
||||
),
|
||||
recognizer: span.recognizer,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
TextSpan get _textSpan => TextSpan(
|
||||
children: _textNode.delta.operations
|
||||
.whereType<TextInsert>()
|
||||
|
@ -2,6 +2,19 @@ import 'package:flowy_editor/document/attributes.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
///
|
||||
/// Supported partial rendering types:
|
||||
/// bold, italic,
|
||||
/// underline, strikethrough,
|
||||
/// color, font,
|
||||
/// href
|
||||
///
|
||||
/// Supported global rendering types:
|
||||
/// heading: h1, h2, h3, h4, h5, h6, ...
|
||||
/// block quote,
|
||||
/// list: ordered list, bulleted list,
|
||||
/// code block
|
||||
///
|
||||
class StyleKey {
|
||||
static String bold = 'bold';
|
||||
static String italic = 'italic';
|
||||
@ -11,6 +24,7 @@ class StyleKey {
|
||||
static String highlightColor = 'highlightColor';
|
||||
static String font = 'font';
|
||||
static String href = 'href';
|
||||
|
||||
static String heading = 'heading';
|
||||
static String quote = 'quote';
|
||||
static String list = 'list';
|
||||
@ -19,7 +33,76 @@ class StyleKey {
|
||||
static String code = 'code';
|
||||
}
|
||||
|
||||
extension AttributesExtensions on Attributes {
|
||||
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,
|
||||
};
|
||||
|
||||
extension NodeAttributesExtensions on Attributes {
|
||||
String? get heading {
|
||||
if (containsKey(StyleKey.heading) && this[StyleKey.heading] is String) {
|
||||
return this[StyleKey.heading];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double get fontSize {
|
||||
if (heading != null) {
|
||||
return headingToFontSize[heading]!;
|
||||
}
|
||||
return baseFontSize;
|
||||
}
|
||||
|
||||
bool get quote {
|
||||
if (containsKey(StyleKey.quote) && this[StyleKey.quote] == true) {
|
||||
return this[StyleKey.quote];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Color? get quoteColor {
|
||||
if (quote) {
|
||||
return Colors.grey;
|
||||
}
|
||||
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];
|
||||
}
|
||||
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];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
extension DeltaAttributesExtensions on Attributes {
|
||||
bool get bold {
|
||||
return (containsKey(StyleKey.bold) && this[StyleKey.bold] == true);
|
||||
}
|
||||
@ -68,63 +151,8 @@ extension AttributesExtensions on Attributes {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? get heading {
|
||||
if (containsKey(StyleKey.heading) && this[StyleKey.heading] is String) {
|
||||
return this[StyleKey.heading];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool get quote {
|
||||
if (containsKey(StyleKey.quote) && this[StyleKey.quote] == true) {
|
||||
return this[StyleKey.quote];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
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];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Supported partial rendering types:
|
||||
/// bold, italic,
|
||||
/// underline, strikethrough,
|
||||
/// color, font,
|
||||
/// href
|
||||
///
|
||||
/// Supported global rendering types:
|
||||
/// heading: h1, h2, h3, h4, h5, h6,
|
||||
/// block quote,
|
||||
/// list: ordered list, bulleted list,
|
||||
/// code block
|
||||
///
|
||||
class RichTextStyle {
|
||||
// TODO: customize
|
||||
RichTextStyle({
|
||||
@ -154,8 +182,6 @@ class RichTextStyle {
|
||||
FontWeight get fontWeight {
|
||||
if (attributes.bold) {
|
||||
return FontWeight.bold;
|
||||
} else if (attributes.heading != null) {
|
||||
return FontWeight.bold;
|
||||
}
|
||||
return FontWeight.normal;
|
||||
}
|
||||
@ -178,8 +204,6 @@ class RichTextStyle {
|
||||
Color get textColor {
|
||||
if (attributes.href != null) {
|
||||
return Colors.lightBlue;
|
||||
} else if (attributes.quote) {
|
||||
return Colors.grey;
|
||||
}
|
||||
return attributes.color ?? Colors.black;
|
||||
}
|
||||
@ -190,14 +214,7 @@ class RichTextStyle {
|
||||
|
||||
// font size
|
||||
double get fontSize {
|
||||
final heading = attributes.heading;
|
||||
if (heading != null) {
|
||||
final headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
||||
final fontSizes = [30.0, 25.0, 20.0, 20.0, 20.0, 20.0];
|
||||
return fontSizes[headings.indexOf(heading)];
|
||||
} else {
|
||||
return 16.0;
|
||||
}
|
||||
return baseFontSize;
|
||||
}
|
||||
|
||||
// recognizer
|
||||
|
Loading…
Reference in New Issue
Block a user