feat: support scaling the svg (#722)

* feat: support scaling the svg

* fix: flutter test
This commit is contained in:
Lucas.Xu 2024-02-21 14:41:55 +07:00 • committed by GitHub
commit 1715ed4549
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 53 additions and 16 deletions

View file

@ -0,0 +1 @@
extensions:

View file

@ -3,20 +3,18 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:flutter/foundation.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:example/pages/customize_theme_for_editor.dart'; import 'package:example/pages/customize_theme_for_editor.dart';
import 'package:example/pages/editor.dart'; import 'package:example/pages/editor.dart';
import 'package:example/pages/editor_list.dart'; import 'package:example/pages/editor_list.dart';
import 'package:example/pages/focus_example_for_editor.dart'; import 'package:example/pages/focus_example_for_editor.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:universal_html/html.dart' as html; import 'package:universal_html/html.dart' as html;
import 'package:appflowy_editor/appflowy_editor.dart';
enum ExportFileType { enum ExportFileType {
documentJson, documentJson,
markdown, markdown,

View file

@ -111,6 +111,7 @@ class _MobileEditorState extends State<MobileEditor> {
// showcase 1: customize the editor style. // showcase 1: customize the editor style.
EditorStyle _buildMobileEditorStyle() { EditorStyle _buildMobileEditorStyle() {
return EditorStyle.mobile( return EditorStyle.mobile(
textScaleFactor: 1.0,
cursorColor: const Color.fromARGB(255, 134, 46, 247), cursorColor: const Color.fromARGB(255, 134, 46, 247),
dragHandleColor: const Color.fromARGB(255, 134, 46, 247), dragHandleColor: const Color.fromARGB(255, 134, 46, 247),
selectionColor: const Color.fromARGB(50, 134, 46, 247), selectionColor: const Color.fromARGB(50, 134, 46, 247),

View file

@ -1,6 +1,7 @@
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart'; import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class BulletedListBlockKeys { class BulletedListBlockKeys {
const BulletedListBlockKeys._(); const BulletedListBlockKeys._();
@ -218,14 +219,17 @@ class _BulletedListIcon extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textScaleFactor =
context.read<EditorState>().editorStyle.textScaleFactor;
return Container( return Container(
constraints: const BoxConstraints(minWidth: 26, minHeight: 22), constraints:
const BoxConstraints(minWidth: 26, minHeight: 22) * textScaleFactor,
padding: const EdgeInsets.only(right: 4.0), padding: const EdgeInsets.only(right: 4.0),
child: Center( child: Center(
child: Text( child: Text(
icon, icon,
style: textStyle, style: textStyle,
textScaler: const TextScaler.linear(0.5), textScaler: TextScaler.linear(0.5 * textScaleFactor),
), ),
), ),
); );

View file

@ -209,11 +209,14 @@ class _NumberedListIcon extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final editorState = context.read<EditorState>(); final editorState = context.read<EditorState>();
final text = editorState.editorStyle.textStyleConfiguration.text; final text = editorState.editorStyle.textStyleConfiguration.text;
final textScaleFactor = editorState.editorStyle.textScaleFactor;
return Container( return Container(
constraints: const BoxConstraints(minWidth: 26, minHeight: 22), constraints:
const BoxConstraints(minWidth: 26, minHeight: 22) * textScaleFactor,
padding: const EdgeInsets.only(right: 4.0), padding: const EdgeInsets.only(right: 4.0),
child: Center( child: Center(
child: Text.rich( child: Text.rich(
textScaler: TextScaler.linear(textScaleFactor),
textHeightBehavior: const TextHeightBehavior( textHeightBehavior: const TextHeightBehavior(
applyHeightToFirstAscent: false, applyHeightToFirstAscent: false,
applyHeightToLastDescent: false, applyHeightToLastDescent: false,

View file

@ -187,12 +187,15 @@ class _QuoteIcon extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textScaleFactor =
context.read<EditorState>().editorStyle.textScaleFactor;
return Container( return Container(
alignment: Alignment.center, alignment: Alignment.center,
constraints: const BoxConstraints(minWidth: 26, minHeight: 22), constraints:
const BoxConstraints(minWidth: 26, minHeight: 22) * textScaleFactor,
padding: const EdgeInsets.only(right: 4.0), padding: const EdgeInsets.only(right: 4.0),
child: Container( child: Container(
width: 4, width: 4 * textScaleFactor,
color: '#00BCF0'.tryToColor(), color: '#00BCF0'.tryToColor(),
), ),
); );

View file

@ -285,6 +285,8 @@ class _AppFlowyRichTextState extends State<AppFlowyRichText>
? widget.placeholderTextSpanDecorator!(textSpan) ? widget.placeholderTextSpanDecorator!(textSpan)
: textSpan, : textSpan,
textDirection: textDirection(), textDirection: textDirection(),
textScaler:
TextScaler.linear(widget.editorState.editorStyle.textScaleFactor),
); );
} }
@ -301,6 +303,8 @@ class _AppFlowyRichTextState extends State<AppFlowyRichText>
? widget.textSpanDecorator!(textSpan) ? widget.textSpanDecorator!(textSpan)
: textSpan, : textSpan,
textDirection: textDirection(), textDirection: textDirection(),
textScaler:
TextScaler.linear(widget.editorState.editorStyle.textScaleFactor),
); );
} }

View file

@ -2,6 +2,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart'; import 'package:appflowy_editor/src/editor/block_component/base_component/block_icon_builder.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
class TodoListBlockKeys { class TodoListBlockKeys {
const TodoListBlockKeys._(); const TodoListBlockKeys._();
@ -269,13 +270,16 @@ class _TodoListIcon extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textScaleFactor =
context.read<EditorState>().editorStyle.textScaleFactor;
return MouseRegion( return MouseRegion(
cursor: SystemMouseCursors.click, cursor: SystemMouseCursors.click,
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: onTap, onTap: onTap,
child: Container( child: Container(
constraints: const BoxConstraints(minWidth: 26, minHeight: 22), constraints: const BoxConstraints(minWidth: 26, minHeight: 22) *
textScaleFactor,
padding: const EdgeInsets.only(right: 4.0), padding: const EdgeInsets.only(right: 4.0),
child: EditorSvg( child: EditorSvg(
width: 22, width: 22,

View file

@ -20,6 +20,7 @@ class EditorStyle {
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.defaultTextDirection, this.defaultTextDirection,
this.enableHapticFeedbackOnAndroid = true, this.enableHapticFeedbackOnAndroid = true,
this.textScaleFactor = 1.0,
}); });
// The padding of the editor. // The padding of the editor.
@ -70,6 +71,8 @@ class EditorStyle {
// enable haptic feedback when updating selection by dragging the drag handler // enable haptic feedback when updating selection by dragging the drag handler
final bool enableHapticFeedbackOnAndroid; final bool enableHapticFeedbackOnAndroid;
final double textScaleFactor;
const EditorStyle.desktop({ const EditorStyle.desktop({
EdgeInsets? padding, EdgeInsets? padding,
Color? cursorColor, Color? cursorColor,
@ -78,6 +81,7 @@ class EditorStyle {
TextSpanDecoratorForAttribute? textSpanDecorator, TextSpanDecoratorForAttribute? textSpanDecorator,
this.defaultTextDirection, this.defaultTextDirection,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.textScaleFactor = 1.0,
}) : padding = padding ?? const EdgeInsets.symmetric(horizontal: 100), }) : padding = padding ?? const EdgeInsets.symmetric(horizontal: 100),
cursorColor = cursorColor ?? const Color(0xFF00BCF0), cursorColor = cursorColor ?? const Color(0xFF00BCF0),
selectionColor = selectionColor =
@ -107,6 +111,7 @@ class EditorStyle {
this.mobileDragHandleWidth = 2.0, this.mobileDragHandleWidth = 2.0,
this.cursorWidth = 2.0, this.cursorWidth = 2.0,
this.enableHapticFeedbackOnAndroid = true, this.enableHapticFeedbackOnAndroid = true,
this.textScaleFactor = 1.0,
}) : padding = padding ?? const EdgeInsets.symmetric(horizontal: 20), }) : padding = padding ?? const EdgeInsets.symmetric(horizontal: 20),
cursorColor = cursorColor ?? const Color(0xFF00BCF0), cursorColor = cursorColor ?? const Color(0xFF00BCF0),
dragHandleColor = dragHandleColor ?? const Color(0xFF00BCF0), dragHandleColor = dragHandleColor ?? const Color(0xFF00BCF0),
@ -132,6 +137,7 @@ class EditorStyle {
double? mobileDragHandleWidth, double? mobileDragHandleWidth,
bool? enableHapticFeedbackOnAndroid, bool? enableHapticFeedbackOnAndroid,
double? cursorWidth, double? cursorWidth,
double? textScaleFactor,
}) { }) {
return EditorStyle( return EditorStyle(
padding: padding ?? this.padding, padding: padding ?? this.padding,
@ -150,6 +156,7 @@ class EditorStyle {
enableHapticFeedbackOnAndroid: enableHapticFeedbackOnAndroid:
enableHapticFeedbackOnAndroid ?? this.enableHapticFeedbackOnAndroid, enableHapticFeedbackOnAndroid ?? this.enableHapticFeedbackOnAndroid,
cursorWidth: cursorWidth ?? this.cursorWidth, cursorWidth: cursorWidth ?? this.cursorWidth,
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
); );
} }
} }

View file

@ -1,5 +1,7 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
class EditorSvg extends StatelessWidget { class EditorSvg extends StatelessWidget {
const EditorSvg({ const EditorSvg({
@ -24,13 +26,23 @@ class EditorSvg extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scaleFactor =
context.read<EditorState?>()?.editorStyle.textScaleFactor ?? 1.0;
final height = (this.height ?? _defaultHeight) * scaleFactor;
final width = (this.width ?? _defaultWidth) * scaleFactor;
return Padding( return Padding(
padding: padding ?? const EdgeInsets.all(0), padding: padding ?? const EdgeInsets.all(0),
child: _buildSvg(), child: _buildSvg(
height,
width,
),
); );
} }
Widget _buildSvg() { Widget _buildSvg(
double height,
double width,
) {
if (name != null) { if (name != null) {
return SvgPicture.asset( return SvgPicture.asset(
'assets/images/$name.svg', 'assets/images/$name.svg',
@ -46,8 +58,8 @@ class EditorSvg extends StatelessWidget {
'<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"><text x="30" y="150" fill="black" font-size="160">$number.</text></svg>'; '<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"><text x="30" y="150" fill="black" font-size="160">$number.</text></svg>';
return SvgPicture.string( return SvgPicture.string(
numberText, numberText,
width: width ?? _defaultWidth, width: width,
height: height ?? _defaultHeight, height: height,
); );
} }
return Container(); return Container();