diff --git a/.github/ISSUE_TEMPLATE/issue-template.md b/.github/ISSUE_TEMPLATE/issue-template.md
index c8a389aa..cd6b26f9 100644
--- a/.github/ISSUE_TEMPLATE/issue-template.md
+++ b/.github/ISSUE_TEMPLATE/issue-template.md
@@ -1,20 +1,16 @@
---
name: Issue template
about: Common things to fill
-title: "[Web] or [Mobile] or [Desktop]"
+title: "Issue in [Mobile, Desktop, Web]"
labels: ''
assignees: ''
---
-My issue is about [Web]
-My issue is about [Mobile]
-My issue is about [Desktop]
-
-I have tried running `example` directory successfully before creating an issue here.
-
Please note that we are using latest flutter version in stable channel on branch master. If you are using beta or master channel, or you are not using latest flutter version in stable channel, you may experience error.
+
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5776f039..f406c647 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [8.1.2]
+- Fix bug that is related to the regexp of the insert link dialog
+- Require dart 3 as minimum
+- Code cleanup
+- Add spacer widget between each button in the `QuillToolbar`
+
## [8.1.1]
- Fix null error in line.dart [#1487](https://github.com/singerdmx/flutter-quill/issues/1487)
diff --git a/lib/src/models/config/others/animations.dart b/lib/src/models/config/others/animations.dart
index 829442c5..ce6bcb0c 100644
--- a/lib/src/models/config/others/animations.dart
+++ b/lib/src/models/config/others/animations.dart
@@ -1,10 +1,8 @@
import 'package:equatable/equatable.dart';
-import 'package:flutter/foundation.dart' show immutable;
-
-import '../../../utils/experimental.dart';
+import 'package:meta/meta.dart' show experimental, immutable;
@immutable
-@Experimental('This class might removed')
+@experimental
class QuillAnimationConfigurations extends Equatable {
const QuillAnimationConfigurations({
required this.checkBoxPointItem,
diff --git a/lib/src/models/config/toolbar/buttons/link_style2.dart b/lib/src/models/config/toolbar/buttons/link_style2.dart
new file mode 100644
index 00000000..d42eec96
--- /dev/null
+++ b/lib/src/models/config/toolbar/buttons/link_style2.dart
@@ -0,0 +1,63 @@
+import 'package:flutter/widgets.dart';
+
+import '../../../themes/quill_dialog_theme.dart';
+import 'base.dart';
+
+class QuillToolbarLinkStyleButton2ExtraOptions
+ extends QuillToolbarBaseButtonExtraOptions {
+ const QuillToolbarLinkStyleButton2ExtraOptions({
+ required super.controller,
+ required super.context,
+ required super.onPressed,
+ });
+}
+
+class QuillToolbarLinkStyleButton2Options extends QuillToolbarBaseButtonOptions<
+ QuillToolbarLinkStyleButton2Options,
+ QuillToolbarLinkStyleButton2ExtraOptions> {
+ const QuillToolbarLinkStyleButton2Options({
+ this.iconSize,
+ this.dialogTheme,
+ this.constraints,
+ this.addLinkLabel,
+ this.editLinkLabel,
+ this.linkColor,
+ this.validationMessage,
+ this.buttonSize,
+ this.dialogBarrierColor,
+ this.childrenSpacing = 16.0,
+ this.autovalidateMode = AutovalidateMode.disabled,
+ super.iconData,
+ super.afterButtonPressed,
+ super.tooltip,
+ super.iconTheme,
+ super.childBuilder,
+ super.controller,
+ });
+
+ final double? iconSize;
+ final QuillDialogTheme? dialogTheme;
+
+ /// The constrains for dialog.
+ final BoxConstraints? constraints;
+
+ /// The text of label in link add mode.
+ final String? addLinkLabel;
+
+ /// The text of label in link edit mode.
+ final String? editLinkLabel;
+
+ /// The color of URL.
+ final Color? linkColor;
+
+ /// The margin between child widgets in the dialog.
+ final double childrenSpacing;
+
+ final AutovalidateMode autovalidateMode;
+ final String? validationMessage;
+
+ /// The size of dialog buttons.
+ final Size? buttonSize;
+
+ final Color? dialogBarrierColor;
+}
diff --git a/lib/src/models/config/toolbar/buttons/select_alignment.dart b/lib/src/models/config/toolbar/buttons/select_alignment.dart
index 3bbef892..19bb21bd 100644
--- a/lib/src/models/config/toolbar/buttons/select_alignment.dart
+++ b/lib/src/models/config/toolbar/buttons/select_alignment.dart
@@ -19,6 +19,8 @@ class QuillToolbarSelectAlignmentButtonOptions
this.tooltips,
this.iconSize,
super.afterButtonPressed,
+
+ /// This will called on every select alignment button
super.childBuilder,
super.controller,
super.iconTheme,
diff --git a/lib/src/models/config/toolbar/buttons/select_header_style.dart b/lib/src/models/config/toolbar/buttons/select_header_style.dart
index 1145afaf..fd4298b7 100644
--- a/lib/src/models/config/toolbar/buttons/select_header_style.dart
+++ b/lib/src/models/config/toolbar/buttons/select_header_style.dart
@@ -20,20 +20,21 @@ class QuillToolbarSelectHeaderStyleButtonsOptions
super.afterButtonPressed,
super.childBuilder,
super.controller,
- super.iconData,
super.iconTheme,
super.tooltip,
this.axis,
- this.attributes = const [
- Attribute.header,
- Attribute.h1,
- Attribute.h2,
- Attribute.h3,
- ],
+ this.attributes,
this.iconSize,
});
- final List attributes;
+ /// Default value:
+ /// const [
+ /// Attribute.header,
+ /// Attribute.h1,
+ /// Attribute.h2,
+ /// Attribute.h3,
+ /// ]
+ final List? attributes;
/// By default we will the toolbar axis from [QuillToolbarConfigurations]
final Axis? axis;
diff --git a/lib/src/models/config/toolbar/configurations.dart b/lib/src/models/config/toolbar/configurations.dart
index 533ac8fb..00412042 100644
--- a/lib/src/models/config/toolbar/configurations.dart
+++ b/lib/src/models/config/toolbar/configurations.dart
@@ -1,7 +1,7 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart' show immutable;
import 'package:flutter/widgets.dart'
- show Axis, Color, Decoration, WrapAlignment, WrapCrossAlignment;
+ show Axis, Color, Decoration, Widget, WrapAlignment, WrapCrossAlignment;
import '../../../widgets/embeds.dart';
import '../../structs/link_dialog_action.dart';
@@ -107,6 +107,7 @@ class QuillToolbarConfigurations extends Equatable {
this.color,
this.sectionDividerColor,
this.sectionDividerSpace,
+ this.spacerWidget,
/// By default it will calculated based on the [globalIconSize] from
/// [base] in [QuillToolbarButtonOptions]
@@ -130,6 +131,15 @@ class QuillToolbarConfigurations extends Equatable {
/// If you want change spesefic buttons or all of them
/// then you came to the right place
final QuillToolbarButtonOptions buttonOptions;
+
+ /// A widget that will placed between each button in the toolbar
+ /// can be used as a spacer
+ /// it will not used before the first button
+ /// it will not used after the last button
+ /// it will also not used in the toolbar dividers
+ /// Default value will be [SizedBox.shrink()]
+ /// some widgets like the header styles will be considered as one widget
+ final Widget? spacerWidget;
final bool multiRowsDisplay;
/// By default it will be
diff --git a/lib/src/models/documents/nodes/block.dart b/lib/src/models/documents/nodes/block.dart
index ed5a4c75..886ad392 100644
--- a/lib/src/models/documents/nodes/block.dart
+++ b/lib/src/models/documents/nodes/block.dart
@@ -13,7 +13,7 @@ import 'node.dart';
/// - Text Alignment
/// - Text Direction
/// - Code Block
-class Block extends Container {
+base class Block extends Container {
/// Creates new unmounted [Block].
@override
Node newInstance() => Block();
diff --git a/lib/src/models/documents/nodes/container.dart b/lib/src/models/documents/nodes/container.dart
index f061a4ca..47bc37e4 100644
--- a/lib/src/models/documents/nodes/container.dart
+++ b/lib/src/models/documents/nodes/container.dart
@@ -14,7 +14,7 @@ import 'node.dart';
///
/// Most of the operation handling logic is implemented by [Line]
/// and [QuillText].
-abstract class Container extends Node {
+abstract base class Container extends Node {
final LinkedList _children = LinkedList();
/// List of children.
diff --git a/lib/src/models/documents/nodes/leaf.dart b/lib/src/models/documents/nodes/leaf.dart
index 8bf78462..8ae3be36 100644
--- a/lib/src/models/documents/nodes/leaf.dart
+++ b/lib/src/models/documents/nodes/leaf.dart
@@ -8,7 +8,7 @@ import 'line.dart';
import 'node.dart';
/// A leaf in Quill document tree.
-abstract class Leaf extends Node {
+abstract base class Leaf extends Node {
/// Creates a new [Leaf] with specified [data].
factory Leaf(Object data) {
if (data is Embeddable) {
@@ -216,7 +216,7 @@ abstract class Leaf extends Node {
/// The reason we are renamed quill Text to [QuillText] so it doesn't
/// conflict with the one from the widgets, material or cupertino library
///
-class QuillText extends Leaf {
+base class QuillText extends Leaf {
QuillText([String text = ''])
: assert(!text.contains('\n')),
super.val(text);
@@ -249,7 +249,7 @@ class QuillText extends Leaf {
/// necessarily mean the embed will look according to that style. For instance,
/// applying "bold" style to an image gives no effect, while adding a "link" to
/// an image actually makes the image react to user's action.
-class Embed extends Leaf {
+base class Embed extends Leaf {
Embed(Embeddable data) : super.val(data);
// Refer to https://www.fileformat.info/info/unicode/char/fffc/index.htm
diff --git a/lib/src/models/documents/nodes/line.dart b/lib/src/models/documents/nodes/line.dart
index 58ba9cc6..4a0c8c71 100644
--- a/lib/src/models/documents/nodes/line.dart
+++ b/lib/src/models/documents/nodes/line.dart
@@ -19,7 +19,7 @@ import 'node.dart';
///
/// When a line contains an embed, it fully occupies the line, no other embeds
/// or text nodes are allowed.
-class Line extends Container {
+base class Line extends Container {
@override
Leaf get defaultChild => QuillText();
diff --git a/lib/src/models/documents/nodes/node.dart b/lib/src/models/documents/nodes/node.dart
index 098f1241..bb6a1c59 100644
--- a/lib/src/models/documents/nodes/node.dart
+++ b/lib/src/models/documents/nodes/node.dart
@@ -17,7 +17,7 @@ import 'line.dart';
///
/// The current parent node is exposed by the [parent] property. A node is
/// considered [mounted] when the [parent] property is not `null`.
-abstract class Node extends LinkedListEntry {
+abstract base class Node extends LinkedListEntry {
/// Current parent of this node. May be null if this node is not mounted.
Container? parent;
@@ -127,7 +127,7 @@ abstract class Node extends LinkedListEntry {
}
/// Root node of document tree.
-class Root extends Container> {
+base class Root extends Container> {
@override
Node newInstance() => Root();
diff --git a/lib/src/models/rules/insert.dart b/lib/src/models/rules/insert.dart
index 92fc461e..8f1c1dea 100644
--- a/lib/src/models/rules/insert.dart
+++ b/lib/src/models/rules/insert.dart
@@ -358,14 +358,14 @@ class AutoFormatMultipleLinksRule extends InsertRule {
// TODO: You might want to rename those but everywhere even in
// flutter_quill_extensions
- static const _oneLinePattern =
+ static const _oneLineLinkPattern =
r'^https?:\/\/[\w\-]+(\.[\w\-]+)*(:\d+)?(\/.*)?$';
static const _detectLinkPattern =
r'https?:\/\/[\w\-]+(\.[\w\-]+)*(:\d+)?(\/[^\s]*)?';
/// It requires a valid link in one link
- static final oneLineRegExp = RegExp(
- _oneLinePattern,
+ static final oneLineLinkRegExp = RegExp(
+ _oneLineLinkPattern,
caseSensitive: false,
);
@@ -375,10 +375,10 @@ class AutoFormatMultipleLinksRule extends InsertRule {
_detectLinkPattern,
caseSensitive: false,
);
- @Deprecated(
- 'Please use [linkRegExp1] or [linkRegExp2]',
- )
- static final linkRegExp = oneLineRegExp;
+ // @Deprecated(
+ // 'Please use [linkRegExp1] or [linkRegExp2]',
+ // )
+ static final linkRegExp = oneLineLinkRegExp;
@override
Delta? applyRule(
diff --git a/lib/src/test/widget_tester_extension.dart b/lib/src/test/widget_tester_extension.dart
index 85cc4500..ab811fdc 100644
--- a/lib/src/test/widget_tester_extension.dart
+++ b/lib/src/test/widget_tester_extension.dart
@@ -11,10 +11,10 @@ extension QuillEnterText on WidgetTester {
return TestAsyncUtils.guard(() async {
final editor = state(
find.descendant(
- of: finder,
- matching:
- find.byType(QuillEditor, skipOffstage: finder.skipOffstage),
- matchRoot: true),
+ of: finder,
+ matching: find.byType(QuillEditor, skipOffstage: finder.skipOffstage),
+ matchRoot: true,
+ ),
);
editor.widget.focusNode.requestFocus();
await pump();
diff --git a/lib/src/utils/delta.dart b/lib/src/utils/delta.dart
index c737e1ac..7ef44a2d 100644
--- a/lib/src/utils/delta.dart
+++ b/lib/src/utils/delta.dart
@@ -1,13 +1,20 @@
import 'dart:math' as math;
import 'dart:ui';
+import 'package:meta/meta.dart' show immutable;
+
import '../models/documents/attribute.dart';
import '../models/documents/nodes/node.dart';
import '../models/quill_delta.dart';
// Diff between two texts - old text and new text
+@immutable
class Diff {
- Diff(this.start, this.deleted, this.inserted);
+ const Diff({
+ required this.start,
+ required this.deleted,
+ required this.inserted,
+ });
// Start index in old text at which changes begin.
final int start;
@@ -37,7 +44,11 @@ Diff getDiff(String oldText, String newText, int cursorPosition) {
start++) {}
final deleted = (start >= end) ? '' : oldText.substring(start, end);
final inserted = newText.substring(start, end + delta);
- return Diff(start, deleted, inserted);
+ return Diff(
+ start: start,
+ deleted: deleted,
+ inserted: inserted,
+ );
}
int getPositionDelta(Delta user, Delta actual) {
diff --git a/lib/src/utils/experimental.dart b/lib/src/utils/experimental.dart
deleted file mode 100644
index 8f24e87e..00000000
--- a/lib/src/utils/experimental.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:flutter/foundation.dart' show immutable;
-
-@immutable
-class Experimental {
- const Experimental([this.reason = 'Experimental feature']);
- final String reason;
-}
diff --git a/lib/src/utils/string.dart b/lib/src/utils/string.dart
index f639c716..3de84e65 100644
--- a/lib/src/utils/string.dart
+++ b/lib/src/utils/string.dart
@@ -19,20 +19,6 @@ Map parseKeyValuePairs(String s, Set targetKeys) {
return result;
}
-@Deprecated('Use replaceStyleStringWithSize instead')
-String replaceStyleString(
- String s,
- double width,
- double height,
-) {
- return replaceStyleStringWithSize(
- s,
- width: width,
- height: height,
- isMobile: true,
- );
-}
-
String replaceStyleStringWithSize(
String s, {
required double width,
diff --git a/lib/src/widgets/controller.dart b/lib/src/widgets/controller.dart
index 242faa55..fbfc77f0 100644
--- a/lib/src/widgets/controller.dart
+++ b/lib/src/widgets/controller.dart
@@ -333,18 +333,23 @@ class QuillController extends ChangeNotifier {
void moveCursorToStart() {
updateSelection(
- const TextSelection.collapsed(offset: 0), ChangeSource.LOCAL);
+ const TextSelection.collapsed(offset: 0),
+ ChangeSource.LOCAL,
+ );
}
void moveCursorToPosition(int position) {
updateSelection(
- TextSelection.collapsed(offset: position), ChangeSource.LOCAL);
+ TextSelection.collapsed(offset: position),
+ ChangeSource.LOCAL,
+ );
}
void moveCursorToEnd() {
updateSelection(
- TextSelection.collapsed(offset: plainTextEditingValue.text.length),
- ChangeSource.LOCAL);
+ TextSelection.collapsed(offset: plainTextEditingValue.text.length),
+ ChangeSource.LOCAL,
+ );
}
void updateSelection(TextSelection textSelection, ChangeSource source) {
@@ -358,9 +363,12 @@ class QuillController extends ChangeNotifier {
}
textSelection = selection.copyWith(
- baseOffset: delta.transformPosition(selection.baseOffset, force: false),
- extentOffset:
- delta.transformPosition(selection.extentOffset, force: false));
+ baseOffset: delta.transformPosition(selection.baseOffset, force: false),
+ extentOffset: delta.transformPosition(
+ selection.extentOffset,
+ force: false,
+ ),
+ );
if (selection != textSelection) {
_updateSelection(textSelection, source);
}
diff --git a/lib/src/widgets/cursor.dart b/lib/src/widgets/cursor.dart
index de2dbb5f..293b2ec6 100644
--- a/lib/src/widgets/cursor.dart
+++ b/lib/src/widgets/cursor.dart
@@ -257,7 +257,11 @@ class CursorPainter {
/// [offset] is global top left (x, y) of text line
/// [position] is relative (x) in text line
void paint(
- Canvas canvas, Offset offset, TextPosition position, bool lineHasEmbed) {
+ Canvas canvas,
+ Offset offset,
+ TextPosition position,
+ bool lineHasEmbed,
+ ) {
// relative (x, y) to global offset
var relativeCaretOffset = editable!.getOffsetForCaret(position, prototype);
if (lineHasEmbed && relativeCaretOffset == Offset.zero) {
diff --git a/lib/src/widgets/default_styles.dart b/lib/src/widgets/default_styles.dart
index d600b71d..dded6d08 100644
--- a/lib/src/widgets/default_styles.dart
+++ b/lib/src/widgets/default_styles.dart
@@ -240,22 +240,30 @@ class DefaultStyles {
const VerticalSpacing(0, 0),
null),
h3: DefaultTextBlockStyle(
- defaultTextStyle.style.copyWith(
- fontSize: 20,
- color: defaultTextStyle.style.color!.withOpacity(0.70),
- height: 1.25,
- fontWeight: FontWeight.w500,
- decoration: TextDecoration.none,
- ),
- const VerticalSpacing(8, 0),
- const VerticalSpacing(0, 0),
- null),
+ defaultTextStyle.style.copyWith(
+ fontSize: 20,
+ color: defaultTextStyle.style.color!.withOpacity(0.70),
+ height: 1.25,
+ fontWeight: FontWeight.w500,
+ decoration: TextDecoration.none,
+ ),
+ const VerticalSpacing(8, 0),
+ const VerticalSpacing(0, 0),
+ null,
+ ),
paragraph: DefaultTextBlockStyle(baseStyle, const VerticalSpacing(0, 0),
const VerticalSpacing(0, 0), null),
bold: const TextStyle(fontWeight: FontWeight.bold),
- subscript: const TextStyle(fontFeatures: [FontFeature.subscripts()]),
- superscript:
- const TextStyle(fontFeatures: [FontFeature.superscripts()]),
+ subscript: const TextStyle(
+ fontFeatures: [
+ FontFeature.subscripts(),
+ ],
+ ),
+ superscript: const TextStyle(
+ fontFeatures: [
+ FontFeature.superscripts(),
+ ],
+ ),
italic: const TextStyle(fontStyle: FontStyle.italic),
small: const TextStyle(fontSize: 12),
underline: const TextStyle(decoration: TextDecoration.underline),
@@ -288,16 +296,22 @@ class DefaultStyles {
const VerticalSpacing(0, 0),
null),
lists: DefaultListBlockStyle(
- baseStyle, baseSpacing, const VerticalSpacing(0, 6), null, null),
+ baseStyle,
+ baseSpacing,
+ const VerticalSpacing(0, 6),
+ null,
+ null,
+ ),
quote: DefaultTextBlockStyle(
- TextStyle(color: baseStyle.color!.withOpacity(0.6)),
- baseSpacing,
- const VerticalSpacing(6, 2),
- BoxDecoration(
- border: Border(
- left: BorderSide(width: 4, color: Colors.grey.shade300),
- ),
- )),
+ TextStyle(color: baseStyle.color!.withOpacity(0.6)),
+ baseSpacing,
+ const VerticalSpacing(6, 2),
+ BoxDecoration(
+ border: Border(
+ left: BorderSide(width: 4, color: Colors.grey.shade300),
+ ),
+ ),
+ ),
code: DefaultTextBlockStyle(
TextStyle(
color: Colors.blue.shade900.withOpacity(0.9),
@@ -312,11 +326,23 @@ class DefaultStyles {
borderRadius: BorderRadius.circular(2),
)),
indent: DefaultTextBlockStyle(
- baseStyle, baseSpacing, const VerticalSpacing(0, 6), null),
- align: DefaultTextBlockStyle(baseStyle, const VerticalSpacing(0, 0),
- const VerticalSpacing(0, 0), null),
- leading: DefaultTextBlockStyle(baseStyle, const VerticalSpacing(0, 0),
- const VerticalSpacing(0, 0), null),
+ baseStyle,
+ baseSpacing,
+ const VerticalSpacing(0, 6),
+ null,
+ ),
+ align: DefaultTextBlockStyle(
+ baseStyle,
+ const VerticalSpacing(0, 0),
+ const VerticalSpacing(0, 0),
+ null,
+ ),
+ leading: DefaultTextBlockStyle(
+ baseStyle,
+ const VerticalSpacing(0, 0),
+ const VerticalSpacing(0, 0),
+ null,
+ ),
sizeSmall: const TextStyle(fontSize: 10),
sizeLarge: const TextStyle(fontSize: 18),
sizeHuge: const TextStyle(fontSize: 22));
@@ -324,29 +350,30 @@ class DefaultStyles {
DefaultStyles merge(DefaultStyles other) {
return DefaultStyles(
- h1: other.h1 ?? h1,
- h2: other.h2 ?? h2,
- h3: other.h3 ?? h3,
- paragraph: other.paragraph ?? paragraph,
- bold: other.bold ?? bold,
- subscript: other.subscript ?? subscript,
- superscript: other.superscript ?? superscript,
- italic: other.italic ?? italic,
- small: other.small ?? small,
- underline: other.underline ?? underline,
- strikeThrough: other.strikeThrough ?? strikeThrough,
- inlineCode: other.inlineCode ?? inlineCode,
- link: other.link ?? link,
- color: other.color ?? color,
- placeHolder: other.placeHolder ?? placeHolder,
- lists: other.lists ?? lists,
- quote: other.quote ?? quote,
- code: other.code ?? code,
- indent: other.indent ?? indent,
- align: other.align ?? align,
- leading: other.leading ?? leading,
- sizeSmall: other.sizeSmall ?? sizeSmall,
- sizeLarge: other.sizeLarge ?? sizeLarge,
- sizeHuge: other.sizeHuge ?? sizeHuge);
+ h1: other.h1 ?? h1,
+ h2: other.h2 ?? h2,
+ h3: other.h3 ?? h3,
+ paragraph: other.paragraph ?? paragraph,
+ bold: other.bold ?? bold,
+ subscript: other.subscript ?? subscript,
+ superscript: other.superscript ?? superscript,
+ italic: other.italic ?? italic,
+ small: other.small ?? small,
+ underline: other.underline ?? underline,
+ strikeThrough: other.strikeThrough ?? strikeThrough,
+ inlineCode: other.inlineCode ?? inlineCode,
+ link: other.link ?? link,
+ color: other.color ?? color,
+ placeHolder: other.placeHolder ?? placeHolder,
+ lists: other.lists ?? lists,
+ quote: other.quote ?? quote,
+ code: other.code ?? code,
+ indent: other.indent ?? indent,
+ align: other.align ?? align,
+ leading: other.leading ?? leading,
+ sizeSmall: other.sizeSmall ?? sizeSmall,
+ sizeLarge: other.sizeLarge ?? sizeLarge,
+ sizeHuge: other.sizeHuge ?? sizeHuge,
+ );
}
}
diff --git a/lib/src/widgets/delegate.dart b/lib/src/widgets/delegate.dart
index c196a5d3..f595beff 100644
--- a/lib/src/widgets/delegate.dart
+++ b/lib/src/widgets/delegate.dart
@@ -314,8 +314,10 @@ class EditorTextSelectionGestureDetectorBuilder {
void onDragSelectionUpdate(
//DragStartDetails startDetails,
DragUpdateDetails updateDetails) {
- renderEditor!.extendSelection(updateDetails.globalPosition,
- cause: SelectionChangedCause.drag);
+ renderEditor!.extendSelection(
+ updateDetails.globalPosition,
+ cause: SelectionChangedCause.drag,
+ );
}
/// Handler for [EditorTextSelectionGestureDetector.onDragSelectionEnd].
@@ -341,29 +343,30 @@ class EditorTextSelectionGestureDetectorBuilder {
/// the handlers provided by this builder.
///
/// The [child] or its subtree should contain [EditableText].
- Widget build(
- {required HitTestBehavior behavior,
- required Widget child,
- Key? key,
- bool detectWordBoundary = true}) {
+ Widget build({
+ required HitTestBehavior behavior,
+ required Widget child,
+ Key? key,
+ bool detectWordBoundary = true,
+ }) {
return EditorTextSelectionGestureDetector(
- key: key,
- onTapDown: onTapDown,
- onForcePressStart:
- delegate.forcePressEnabled ? onForcePressStart : null,
- onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null,
- onSingleTapUp: onSingleTapUp,
- onSingleTapCancel: onSingleTapCancel,
- onSingleLongTapStart: onSingleLongTapStart,
- onSingleLongTapMoveUpdate: onSingleLongTapMoveUpdate,
- onSingleLongTapEnd: onSingleLongTapEnd,
- onDoubleTapDown: onDoubleTapDown,
- onSecondarySingleTapUp: onSecondarySingleTapUp,
- onDragSelectionStart: onDragSelectionStart,
- onDragSelectionUpdate: onDragSelectionUpdate,
- onDragSelectionEnd: onDragSelectionEnd,
- behavior: behavior,
- detectWordBoundary: detectWordBoundary,
- child: child);
+ key: key,
+ onTapDown: onTapDown,
+ onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null,
+ onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null,
+ onSingleTapUp: onSingleTapUp,
+ onSingleTapCancel: onSingleTapCancel,
+ onSingleLongTapStart: onSingleLongTapStart,
+ onSingleLongTapMoveUpdate: onSingleLongTapMoveUpdate,
+ onSingleLongTapEnd: onSingleLongTapEnd,
+ onDoubleTapDown: onDoubleTapDown,
+ onSecondarySingleTapUp: onSecondarySingleTapUp,
+ onDragSelectionStart: onDragSelectionStart,
+ onDragSelectionUpdate: onDragSelectionUpdate,
+ onDragSelectionEnd: onDragSelectionEnd,
+ behavior: behavior,
+ detectWordBoundary: detectWordBoundary,
+ child: child,
+ );
}
}
diff --git a/lib/src/widgets/editor/editor.dart b/lib/src/widgets/editor/editor.dart
index 766ad8aa..3c25cdb4 100644
--- a/lib/src/widgets/editor/editor.dart
+++ b/lib/src/widgets/editor/editor.dart
@@ -1,10 +1,5 @@
import 'dart:math' as math;
-// ignore: unnecessary_import
-// import 'dart:typed_data';
-// The project maanged to compiled successfully without the import
-// do we still need this import (dart:typed_data)??
-
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
@@ -1495,7 +1490,7 @@ class RenderEditor extends RenderEditableContainerBox
}
}
-class QuillVerticalCaretMovementRun extends Iterator {
+class QuillVerticalCaretMovementRun implements Iterator {
QuillVerticalCaretMovementRun._(
this._editor,
this._currentTextPosition,
diff --git a/lib/src/widgets/embeds.dart b/lib/src/widgets/embeds.dart
index 11d34b87..87511204 100644
--- a/lib/src/widgets/embeds.dart
+++ b/lib/src/widgets/embeds.dart
@@ -29,7 +29,8 @@ abstract class EmbedBuilder {
}
typedef EmbedButtonBuilder = Widget Function(
- QuillController controller,
- double toolbarIconSize,
- QuillIconTheme? iconTheme,
- QuillDialogTheme? dialogTheme);
+ QuillController controller,
+ double toolbarIconSize,
+ QuillIconTheme? iconTheme,
+ QuillDialogTheme? dialogTheme,
+);
diff --git a/lib/src/widgets/keyboard_listener.dart b/lib/src/widgets/keyboard_listener.dart
index 47cb9555..ee1e3d11 100644
--- a/lib/src/widgets/keyboard_listener.dart
+++ b/lib/src/widgets/keyboard_listener.dart
@@ -44,8 +44,9 @@ class QuillKeyboardListenerState extends State {
final QuillPressedKeys _pressedKeys = QuillPressedKeys();
bool _keyEvent(KeyEvent event) {
- _pressedKeys
- ._updatePressedKeys(HardwareKeyboard.instance.logicalKeysPressed);
+ _pressedKeys._updatePressedKeys(
+ HardwareKeyboard.instance.logicalKeysPressed,
+ );
return false;
}
diff --git a/lib/src/widgets/proxy.dart b/lib/src/widgets/proxy.dart
index 155e620a..2379c883 100644
--- a/lib/src/widgets/proxy.dart
+++ b/lib/src/widgets/proxy.dart
@@ -6,8 +6,12 @@ import 'package:flutter/widgets.dart';
import 'box.dart';
class BaselineProxy extends SingleChildRenderObjectWidget {
- const BaselineProxy({Key? key, Widget? child, this.textStyle, this.padding})
- : super(key: key, child: child);
+ const BaselineProxy({
+ Key? key,
+ Widget? child,
+ this.textStyle,
+ this.padding,
+ }) : super(key: key, child: child);
final TextStyle? textStyle;
final EdgeInsets? padding;
diff --git a/lib/src/widgets/quill_single_child_scroll_view.dart b/lib/src/widgets/quill_single_child_scroll_view.dart
index 40971b06..ba6c0371 100644
--- a/lib/src/widgets/quill_single_child_scroll_view.dart
+++ b/lib/src/widgets/quill_single_child_scroll_view.dart
@@ -14,10 +14,10 @@ class QuillSingleChildScrollView extends StatelessWidget {
const QuillSingleChildScrollView({
required this.controller,
required this.viewportBuilder,
- Key? key,
+ super.key,
this.physics,
this.restorationId,
- }) : super(key: key);
+ });
/// An object that can be used to control the position to which this scroll
/// view is scrolled.
@@ -48,7 +48,10 @@ class QuillSingleChildScrollView extends StatelessWidget {
AxisDirection _getDirection(BuildContext context) {
return getAxisDirectionFromAxisReverseAndDirectionality(
- context, Axis.vertical, false);
+ context,
+ Axis.vertical,
+ false,
+ );
}
@override
diff --git a/lib/src/widgets/raw_editor/raw_editor.dart b/lib/src/widgets/raw_editor/raw_editor.dart
index 8e5090f0..28d6c342 100644
--- a/lib/src/widgets/raw_editor/raw_editor.dart
+++ b/lib/src/widgets/raw_editor/raw_editor.dart
@@ -437,9 +437,6 @@ class RawEditorState extends EditorState
// in the web browser, but we do unfocus for all other kinds of events.
switch (event.kind) {
case ui.PointerDeviceKind.touch:
- // if (isWeb()) {
- // widget.focusNode.unfocus();
- // }
break;
case ui.PointerDeviceKind.mouse:
case ui.PointerDeviceKind.stylus:
@@ -449,7 +446,7 @@ class RawEditorState extends EditorState
break;
case ui.PointerDeviceKind.trackpad:
throw UnimplementedError(
- 'Unexpected pointer down event for trackpad',
+ 'Unexpected pointer down event for trackpad.',
);
}
break;
@@ -461,7 +458,7 @@ class RawEditorState extends EditorState
default:
throw UnsupportedError(
'The platform ${defaultTargetPlatform.name} is not supported in the'
- ' _defaultOnTapOutside',
+ ' _defaultOnTapOutside()',
);
}
}
@@ -474,8 +471,11 @@ class RawEditorState extends EditorState
var _doc = controller.document;
if (_doc.isEmpty() && widget.placeholder != null) {
final raw = widget.placeholder?.replaceAll(r'"', '\\"');
- _doc = Document.fromJson(jsonDecode(
- '[{"attributes":{"placeholder":true},"insert":"$raw\\n"}]'));
+ _doc = Document.fromJson(
+ jsonDecode(
+ '[{"attributes":{"placeholder":true},"insert":"$raw\\n"}]',
+ ),
+ );
}
Widget child = CompositedTransformTarget(
@@ -1435,7 +1435,6 @@ class RawEditorState extends EditorState
@override
void requestKeyboard() {
if (controller.skipRequestKeyboard) {
- // TODO: There is a bug, requestKeyboard is being called 2-4 times!
// and that just by one simple change
controller.skipRequestKeyboard = false;
return;
diff --git a/lib/src/widgets/style_widgets/bullet_point.dart b/lib/src/widgets/style_widgets/bullet_point.dart
index 8b5fce70..f760c992 100644
--- a/lib/src/widgets/style_widgets/bullet_point.dart
+++ b/lib/src/widgets/style_widgets/bullet_point.dart
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
-class QuillBulletPoint extends StatelessWidget {
- const QuillBulletPoint({
+class QuillEditorBulletPoint extends StatelessWidget {
+ const QuillEditorBulletPoint({
required this.style,
required this.width,
this.padding = 0,
diff --git a/lib/src/widgets/style_widgets/checkbox_point.dart b/lib/src/widgets/style_widgets/checkbox_point.dart
index 1276a152..4d87df16 100644
--- a/lib/src/widgets/style_widgets/checkbox_point.dart
+++ b/lib/src/widgets/style_widgets/checkbox_point.dart
@@ -3,8 +3,8 @@ import 'package:flutter_animate/flutter_animate.dart';
import '../../utils/extensions/build_context.dart';
-class CheckboxPoint extends StatefulWidget {
- const CheckboxPoint({
+class QuillEditorCheckboxPoint extends StatefulWidget {
+ const QuillEditorCheckboxPoint({
required this.size,
required this.value,
required this.enabled,
@@ -20,10 +20,11 @@ class CheckboxPoint extends StatefulWidget {
final QuillCheckboxBuilder? uiBuilder;
@override
- _CheckboxPointState createState() => _CheckboxPointState();
+ _QuillEditorCheckboxPointState createState() =>
+ _QuillEditorCheckboxPointState();
}
-class _CheckboxPointState extends State {
+class _QuillEditorCheckboxPointState extends State {
@override
Widget build(BuildContext context) {
final uiBuilder = widget.uiBuilder;
diff --git a/lib/src/widgets/style_widgets/number_point.dart b/lib/src/widgets/style_widgets/number_point.dart
index 54d5ebc9..30b5590e 100644
--- a/lib/src/widgets/style_widgets/number_point.dart
+++ b/lib/src/widgets/style_widgets/number_point.dart
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
import '../../models/documents/attribute.dart';
import '../text_block.dart';
-class QuillNumberPoint extends StatelessWidget {
- const QuillNumberPoint({
+class QuillEditorNumberPoint extends StatelessWidget {
+ const QuillEditorNumberPoint({
required this.index,
required this.indentLevelCounts,
required this.count,
@@ -13,8 +13,8 @@ class QuillNumberPoint extends StatelessWidget {
required this.attrs,
this.withDot = true,
this.padding = 0.0,
- Key? key,
- }) : super(key: key);
+ super.key,
+ });
final int index;
final Map indentLevelCounts;
diff --git a/lib/src/widgets/text_block.dart b/lib/src/widgets/text_block.dart
index d10596fe..f99ccbb0 100644
--- a/lib/src/widgets/text_block.dart
+++ b/lib/src/widgets/text_block.dart
@@ -146,7 +146,13 @@ class EditableTextBlock extends StatelessWidget {
index++;
final editableTextLine = EditableTextLine(
line,
- _buildLeading(context, line, index, indentLevelCounts, count),
+ _buildLeading(
+ context: context,
+ line: line,
+ index: index,
+ indentLevelCounts: indentLevelCounts,
+ count: count,
+ ),
TextLine(
line: line,
textDirection: textDirection,
@@ -194,14 +200,19 @@ class EditableTextBlock extends StatelessWidget {
}
}
- Widget? _buildLeading(BuildContext context, Line line, int index,
- Map indentLevelCounts, int count) {
+ Widget? _buildLeading({
+ required BuildContext context,
+ required Line line,
+ required int index,
+ required Map indentLevelCounts,
+ required int count,
+ }) {
final defaultStyles = QuillStyles.getStyles(context, false)!;
final fontSize = defaultStyles.paragraph?.style.fontSize ?? 16;
final attrs = line.style.attributes;
if (attrs[Attribute.list.key] == Attribute.ol) {
- return QuillNumberPoint(
+ return QuillEditorNumberPoint(
index: index,
indentLevelCounts: indentLevelCounts,
count: count,
@@ -213,7 +224,7 @@ class EditableTextBlock extends StatelessWidget {
}
if (attrs[Attribute.list.key] == Attribute.ul) {
- return QuillBulletPoint(
+ return QuillEditorBulletPoint(
style:
defaultStyles.leading!.style.copyWith(fontWeight: FontWeight.bold),
width: fontSize * 2,
@@ -223,7 +234,7 @@ class EditableTextBlock extends StatelessWidget {
if (attrs[Attribute.list.key] == Attribute.checked ||
attrs[Attribute.list.key] == Attribute.unchecked) {
- return CheckboxPoint(
+ return QuillEditorCheckboxPoint(
size: fontSize,
value: attrs[Attribute.list.key] == Attribute.checked,
enabled: !readOnly,
@@ -233,7 +244,7 @@ class EditableTextBlock extends StatelessWidget {
}
if (attrs.containsKey(Attribute.codeBlock.key) &&
context.requireQuillEditorElementOptions.codeBlock.enableLineNumbers) {
- return QuillNumberPoint(
+ return QuillEditorNumberPoint(
index: index,
indentLevelCounts: indentLevelCounts,
count: count,
@@ -278,7 +289,11 @@ class EditableTextBlock extends StatelessWidget {
}
VerticalSpacing _getSpacingForLine(
- Line node, int index, int count, DefaultStyles? defaultStyles) {
+ Line node,
+ int index,
+ int count,
+ DefaultStyles? defaultStyles,
+ ) {
var top = 0.0, bottom = 0.0;
final attrs = block.style.attributes;
@@ -301,7 +316,7 @@ class EditableTextBlock extends StatelessWidget {
throw 'Invalid level $level';
}
} else {
- late VerticalSpacing lineSpacing;
+ final VerticalSpacing lineSpacing;
if (attrs.containsKey(Attribute.blockQuote.key)) {
lineSpacing = defaultStyles!.quote!.lineSpacing;
} else if (attrs.containsKey(Attribute.indent.key)) {
@@ -500,12 +515,18 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
TextSelectionPoint getBaseEndpointForSelection(TextSelection selection) {
if (selection.isCollapsed) {
return TextSelectionPoint(
- Offset(0, preferredLineHeight(selection.extent)) +
- getOffsetForCaret(selection.extent),
- null);
+ Offset(0, preferredLineHeight(selection.extent)) +
+ getOffsetForCaret(selection.extent),
+ null,
+ );
}
- final baseNode = container.queryChild(selection.start, false).node;
+ final baseNode = container
+ .queryChild(
+ selection.start,
+ false,
+ )
+ .node;
var baseChild = firstChild;
while (baseChild != null) {
if (baseChild.container == baseNode) {
@@ -516,19 +537,26 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
assert(baseChild != null);
final basePoint = baseChild!.getBaseEndpointForSelection(
- localSelection(baseChild.container, selection, true));
+ localSelection(
+ baseChild.container,
+ selection,
+ true,
+ ),
+ );
return TextSelectionPoint(
- basePoint.point + (baseChild.parentData as BoxParentData).offset,
- basePoint.direction);
+ basePoint.point + (baseChild.parentData as BoxParentData).offset,
+ basePoint.direction,
+ );
}
@override
TextSelectionPoint getExtentEndpointForSelection(TextSelection selection) {
if (selection.isCollapsed) {
return TextSelectionPoint(
- Offset(0, preferredLineHeight(selection.extent)) +
- getOffsetForCaret(selection.extent),
- null);
+ Offset(0, preferredLineHeight(selection.extent)) +
+ getOffsetForCaret(selection.extent),
+ null,
+ );
}
final extentNode = container.queryChild(selection.end, false).node;
@@ -543,10 +571,16 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
assert(extentChild != null);
final extentPoint = extentChild!.getExtentEndpointForSelection(
- localSelection(extentChild.container, selection, true));
+ localSelection(
+ extentChild.container,
+ selection,
+ true,
+ ),
+ );
return TextSelectionPoint(
- extentPoint.point + (extentChild.parentData as BoxParentData).offset,
- extentPoint.direction);
+ extentPoint.point + (extentChild.parentData as BoxParentData).offset,
+ extentPoint.direction,
+ );
}
@override
@@ -576,8 +610,10 @@ class RenderEditableTextBlock extends RenderEditableContainerBox
offset.translate(decorationPadding.left, decorationPadding.top);
_painter!.paint(context.canvas, decorationOffset, filledConfiguration);
if (debugSaveCount != context.canvas.getSaveCount()) {
- throw '${_decoration.runtimeType} painter had mismatching save and '
- 'restore calls.';
+ throw StateError(
+ '${_decoration.runtimeType} painter had mismatching save and '
+ 'restore calls.',
+ );
}
if (decoration.isComplex) {
context.setIsComplexHint();
diff --git a/lib/src/widgets/text_line.dart b/lib/src/widgets/text_line.dart
index 6dd4f793..8aa88ccb 100644
--- a/lib/src/widgets/text_line.dart
+++ b/lib/src/widgets/text_line.dart
@@ -43,8 +43,8 @@ class TextLine extends StatefulWidget {
this.customStyleBuilder,
this.customRecognizerBuilder,
this.customLinkPrefixes = const [],
- Key? key,
- }) : super(key: key);
+ super.key,
+ });
final Line line;
final TextDirection? textDirection;
@@ -88,8 +88,8 @@ class _TextLineState extends State {
// In editing mode it depends on the platform:
- // Desktop platforms (macos, linux, windows):
- // only allow Meta(Control)+Click combinations
+ // Desktop platforms (macOS, Linux, Windows):
+ // only allow Meta (Control) + Click combinations
if (isDesktop()) {
return _metaOrControlPressed;
}
@@ -581,21 +581,22 @@ class EditableTextLine extends RenderObjectWidget {
}
}
-enum TextLineSlot { LEADING, BODY }
+enum TextLineSlot { leading, body }
class RenderEditableTextLine extends RenderEditableBox {
/// Creates new editable paragraph render box.
RenderEditableTextLine(
- this.line,
- this.textDirection,
- this.textSelection,
- this.enableInteractiveSelection,
- this.hasFocus,
- this.devicePixelRatio,
- this.padding,
- this.color,
- this.cursorCont,
- this.inlineCodeStyle);
+ this.line,
+ this.textDirection,
+ this.textSelection,
+ this.enableInteractiveSelection,
+ this.hasFocus,
+ this.devicePixelRatio,
+ this.padding,
+ this.color,
+ this.cursorCont,
+ this.inlineCodeStyle,
+ );
RenderBox? _leading;
RenderContentProxyBox? _body;
@@ -715,11 +716,11 @@ class RenderEditableTextLine extends RenderEditableBox {
}
void setLeading(RenderBox? l) {
- _leading = _updateChild(_leading, l, TextLineSlot.LEADING);
+ _leading = _updateChild(_leading, l, TextLineSlot.leading);
}
void setBody(RenderContentProxyBox? b) {
- _body = _updateChild(_body, b, TextLineSlot.BODY) as RenderContentProxyBox?;
+ _body = _updateChild(_body, b, TextLineSlot.body) as RenderContentProxyBox?;
}
void setInlineCodeStyle(InlineCodeStyle newStyle) {
@@ -744,7 +745,10 @@ class RenderEditableTextLine extends RenderEditableBox {
}
RenderBox? _updateChild(
- RenderBox? old, RenderBox? newChild, TextLineSlot slot) {
+ RenderBox? old,
+ RenderBox? newChild,
+ TextLineSlot slot,
+ ) {
if (old != null) {
dropChild(old);
children.remove(slot);
@@ -800,8 +804,9 @@ class RenderEditableTextLine extends RenderEditableBox {
assert(boxes.isNotEmpty);
final targetBox = first ? boxes.first : boxes.last;
return TextSelectionPoint(
- Offset(first ? targetBox.start : targetBox.end, targetBox.bottom),
- targetBox.direction);
+ Offset(first ? targetBox.start : targetBox.end, targetBox.bottom),
+ targetBox.direction,
+ );
}
@override
@@ -814,9 +819,12 @@ class RenderEditableTextLine extends RenderEditableBox {
.where((element) => element.top < lineDy && element.bottom > lineDy)
.toList(growable: false);
return TextRange(
- start:
- getPositionForOffset(Offset(lineBoxes.first.left, lineDy)).offset,
- end: getPositionForOffset(Offset(lineBoxes.last.right, lineDy)).offset);
+ start: getPositionForOffset(
+ Offset(lineBoxes.first.left, lineDy),
+ ).offset,
+ end: getPositionForOffset(
+ Offset(lineBoxes.last.right, lineDy),
+ ).offset);
}
@override
@@ -886,7 +894,9 @@ class RenderEditableTextLine extends RenderEditableBox {
/// of the cursor for iOS is approximate and obtained through an eyeball
/// comparison.
void _computeCaretPrototype() {
- if (isAppleOS()) {
+ // If the cursor is taller only on iOS and not AppleOS then we should check
+ // only for iOS instead of AppleOS (macOS for example)
+ if (isIOS()) {
_caretPrototype = Rect.fromLTWH(0, 0, cursorWidth, cursorHeight + 2);
} else {
_caretPrototype = Rect.fromLTWH(0, 2, cursorWidth, cursorHeight - 4.0);
@@ -1090,8 +1100,13 @@ class RenderEditableTextLine extends RenderEditableBox {
} else {
final parentData = _leading!.parentData as BoxParentData;
final effectiveOffset = offset + parentData.offset;
- context.paintChild(_leading!,
- Offset(size.width - _leading!.size.width, effectiveOffset.dy));
+ context.paintChild(
+ _leading!,
+ Offset(
+ size.width - _leading!.size.width,
+ effectiveOffset.dy,
+ ),
+ );
}
}
@@ -1106,18 +1121,29 @@ class RenderEditableTextLine extends RenderEditableBox {
continue;
}
final textRange = TextSelection(
- baseOffset: item.offset, extentOffset: item.offset + item.length);
+ baseOffset: item.offset,
+ extentOffset: item.offset + item.length,
+ );
final rects = _body!.getBoxesForSelection(textRange);
final paint = Paint()..color = inlineCodeStyle.backgroundColor!;
for (final box in rects) {
final rect = box.toRect().translate(0, 1).shift(effectiveOffset);
if (inlineCodeStyle.radius == null) {
final paintRect = Rect.fromLTRB(
- rect.left - 2, rect.top, rect.right + 2, rect.bottom);
+ rect.left - 2,
+ rect.top,
+ rect.right + 2,
+ rect.bottom,
+ );
context.canvas.drawRect(paintRect, paint);
} else {
- final paintRect = RRect.fromLTRBR(rect.left - 2, rect.top,
- rect.right + 2, rect.bottom, inlineCodeStyle.radius!);
+ final paintRect = RRect.fromLTRBR(
+ rect.left - 2,
+ rect.top,
+ rect.right + 2,
+ rect.bottom,
+ inlineCodeStyle.radius!,
+ );
context.canvas.drawRRect(paintRect, paint);
}
}
@@ -1154,10 +1180,20 @@ class RenderEditableTextLine extends RenderEditableBox {
if (line.isEmpty &&
textSelection.baseOffset <= line.offset &&
textSelection.extentOffset > line.offset) {
- final lineHeight =
- preferredLineHeight(TextPosition(offset: line.offset));
- _selectedRects
- ?.add(TextBox.fromLTRBD(0, 0, 3, lineHeight, textDirection));
+ final lineHeight = preferredLineHeight(
+ TextPosition(
+ offset: line.offset,
+ ),
+ );
+ _selectedRects?.add(
+ TextBox.fromLTRBD(
+ 0,
+ 0,
+ 3,
+ lineHeight,
+ textDirection,
+ ),
+ );
}
_paintSelection(context, effectiveOffset);
@@ -1179,12 +1215,18 @@ class RenderEditableTextLine extends RenderEditableBox {
? TextPosition(
offset: cursorCont.floatingCursorTextPosition.value!.offset -
line.documentOffset,
- affinity: cursorCont.floatingCursorTextPosition.value!.affinity)
+ affinity: cursorCont.floatingCursorTextPosition.value!.affinity,
+ )
: TextPosition(
offset: textSelection.extentOffset - line.documentOffset,
- affinity: textSelection.base.affinity);
+ affinity: textSelection.base.affinity,
+ );
_cursorPainter.paint(
- context.canvas, effectiveOffset, position, lineHasEmbed);
+ context.canvas,
+ effectiveOffset,
+ position,
+ lineHasEmbed,
+ );
}
@override
@@ -1192,29 +1234,35 @@ class RenderEditableTextLine extends RenderEditableBox {
if (_leading != null) {
final childParentData = _leading!.parentData as BoxParentData;
final isHit = result.addWithPaintOffset(
- offset: childParentData.offset,
- position: position,
- hitTest: (result, transformed) {
- assert(transformed == position - childParentData.offset);
- return _leading!.hitTest(result, position: transformed);
- });
+ offset: childParentData.offset,
+ position: position,
+ hitTest: (result, transformed) {
+ assert(transformed == position - childParentData.offset);
+ return _leading!.hitTest(result, position: transformed);
+ },
+ );
if (isHit) return true;
}
if (_body == null) return false;
final parentData = _body!.parentData as BoxParentData;
return result.addWithPaintOffset(
- offset: parentData.offset,
- position: position,
- hitTest: (result, position) {
- return _body!.hitTest(result, position: position);
- });
+ offset: parentData.offset,
+ position: position,
+ hitTest: (result, position) {
+ return _body!.hitTest(result, position: position);
+ },
+ );
}
@override
Rect getLocalRectForCaret(TextPosition position) {
final caretOffset = getOffsetForCaret(position);
- var rect =
- Rect.fromLTWH(0, 0, cursorWidth, cursorHeight).shift(caretOffset);
+ var rect = Rect.fromLTWH(
+ 0,
+ 0,
+ cursorWidth,
+ cursorHeight,
+ ).shift(caretOffset);
final cursorOffset = cursorCont.style.offset;
// Add additional cursor offset (generally only if on iOS).
if (cursorOffset != null) rect = rect.shift(cursorOffset);
@@ -1272,16 +1320,16 @@ class _TextLineElement extends RenderObjectElement {
@override
void mount(Element? parent, dynamic newSlot) {
super.mount(parent, newSlot);
- _mountChild(widget.leading, TextLineSlot.LEADING);
- _mountChild(widget.body, TextLineSlot.BODY);
+ _mountChild(widget.leading, TextLineSlot.leading);
+ _mountChild(widget.body, TextLineSlot.body);
}
@override
void update(EditableTextLine newWidget) {
super.update(newWidget);
assert(widget == newWidget);
- _updateChild(widget.leading, TextLineSlot.LEADING);
- _updateChild(widget.body, TextLineSlot.BODY);
+ _updateChild(widget.leading, TextLineSlot.leading);
+ _updateChild(widget.body, TextLineSlot.body);
}
@override
@@ -1318,10 +1366,10 @@ class _TextLineElement extends RenderObjectElement {
void _updateRenderObject(RenderBox? child, TextLineSlot? slot) {
switch (slot) {
- case TextLineSlot.LEADING:
+ case TextLineSlot.leading:
renderObject.setLeading(child);
break;
- case TextLineSlot.BODY:
+ case TextLineSlot.body:
renderObject.setBody(child as RenderContentProxyBox?);
break;
default:
diff --git a/lib/src/widgets/text_selection.dart b/lib/src/widgets/text_selection.dart
index c13f9952..07cbdeb8 100644
--- a/lib/src/widgets/text_selection.dart
+++ b/lib/src/widgets/text_selection.dart
@@ -842,8 +842,10 @@ class _EditorTextSelectionGestureDetectorState
void _handleDragUpdate(DragUpdateDetails details) {
_lastDragUpdateDetails = details;
- _dragUpdateThrottleTimer ??=
- Timer(const Duration(milliseconds: 50), _handleDragUpdateThrottled);
+ _dragUpdateThrottleTimer ??= Timer(
+ const Duration(milliseconds: 50),
+ _handleDragUpdateThrottled,
+ );
}
/// Drag updates are being throttled to avoid excessive text layouts in text
diff --git a/lib/src/widgets/toolbar/buttons/arrow_indicated_list.dart b/lib/src/widgets/toolbar/buttons/arrow_indicated_list.dart
index 146fcc95..f90b9b4d 100644
--- a/lib/src/widgets/toolbar/buttons/arrow_indicated_list.dart
+++ b/lib/src/widgets/toolbar/buttons/arrow_indicated_list.dart
@@ -10,8 +10,8 @@ class QuillToolbarArrowIndicatedButtonList extends StatefulWidget {
const QuillToolbarArrowIndicatedButtonList({
required this.axis,
required this.buttons,
- Key? key,
- }) : super(key: key);
+ super.key,
+ });
final Axis axis;
final List buttons;
diff --git a/lib/src/widgets/toolbar/buttons/link_style.dart b/lib/src/widgets/toolbar/buttons/link_style.dart
index 15cd5af1..b7bf91c0 100644
--- a/lib/src/widgets/toolbar/buttons/link_style.dart
+++ b/lib/src/widgets/toolbar/buttons/link_style.dart
@@ -95,14 +95,13 @@ class _QuillToolbarLinkStyleButtonState
context.requireQuillSharedConfigurations.dialogBarrierColor;
}
- RegExp get linkRegExp {
- return options.linkRegExp ?? RegExp(r'https?://\S+');
+ RegExp? get linkRegExp {
+ return options.linkRegExp;
}
@override
Widget build(BuildContext context) {
final isToggled = _getLinkAttributeValue() != null;
- final pressedHandler = () => _openLinkDialog(context);
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
@@ -124,7 +123,7 @@ class _QuillToolbarLinkStyleButtonState
context: context,
controller: controller,
onPressed: () {
- pressedHandler();
+ _openLinkDialog(context);
afterButtonPressed?.call();
},
),
@@ -144,10 +143,10 @@ class _QuillToolbarLinkStyleButtonState
: (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
),
fillColor: isToggled
- ? (iconTheme?.iconSelectedFillColor ?? Theme.of(context).primaryColor)
+ ? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
borderRadius: iconTheme?.borderRadius ?? 2,
- onPressed: pressedHandler,
+ onPressed: () => _openLinkDialog(context),
afterPressed: afterButtonPressed,
);
}
@@ -236,7 +235,11 @@ class _LinkDialog extends StatefulWidget {
class _LinkDialogState extends State<_LinkDialog> {
late String _link;
late String _text;
- late RegExp linkRegExp;
+
+ RegExp get linkRegExp {
+ return widget.linkRegExp ?? AutoFormatMultipleLinksRule.oneLineLinkRegExp;
+ }
+
late TextEditingController _linkController;
late TextEditingController _textController;
@@ -245,7 +248,6 @@ class _LinkDialogState extends State<_LinkDialog> {
super.initState();
_link = widget.link ?? '';
_text = widget.text ?? '';
- linkRegExp = widget.linkRegExp ?? AutoFormatMultipleLinksRule.oneLineRegExp;
_linkController = TextEditingController(text: _link);
_textController = TextEditingController(text: _text);
}
diff --git a/lib/src/widgets/toolbar/buttons/link_style2.dart b/lib/src/widgets/toolbar/buttons/link_style2.dart
index d2ecbddd..57e0bcf1 100644
--- a/lib/src/widgets/toolbar/buttons/link_style2.dart
+++ b/lib/src/widgets/toolbar/buttons/link_style2.dart
@@ -5,9 +5,11 @@ import 'package:url_launcher/link.dart';
import '../../../../extensions.dart'
show UtilityWidgets, AutoFormatMultipleLinksRule;
import '../../../../translations.dart';
+import '../../../models/config/toolbar/buttons/link_style2.dart';
import '../../../models/documents/attribute.dart';
import '../../../models/themes/quill_dialog_theme.dart';
import '../../../models/themes/quill_icon_theme.dart';
+import '../../../utils/extensions/build_context.dart';
import '../../controller.dart';
import '../../link.dart';
import '../base_toolbar.dart';
@@ -16,60 +18,20 @@ import '../base_toolbar.dart';
/// customization
/// and uses dialog similar to one which is used on [http://quilljs.com].
class QuillToolbarLinkStyleButton2 extends StatefulWidget {
- const QuillToolbarLinkStyleButton2({
+ QuillToolbarLinkStyleButton2({
required this.controller,
- this.icon,
- this.iconSize = kDefaultIconSize,
- this.iconTheme,
- this.dialogTheme,
- this.afterButtonPressed,
- this.tooltip,
- this.constraints,
- this.addLinkLabel,
- this.editLinkLabel,
- this.linkColor,
- this.childrenSpacing = 16.0,
- this.autovalidateMode = AutovalidateMode.disabled,
- this.validationMessage,
- this.buttonSize,
- this.dialogBarrierColor = Colors.black54,
- Key? key,
- }) : assert(addLinkLabel == null || addLinkLabel.length > 0),
- assert(editLinkLabel == null || editLinkLabel.length > 0),
- assert(childrenSpacing > 0),
- assert(validationMessage == null || validationMessage.length > 0),
- super(key: key);
+ required this.options,
+ super.key,
+ }) : assert(options.addLinkLabel == null ||
+ (options.addLinkLabel?.isNotEmpty ?? true)),
+ assert(options.editLinkLabel == null ||
+ (options.editLinkLabel?.isNotEmpty ?? true)),
+ assert(options.childrenSpacing > 0),
+ assert(options.validationMessage == null ||
+ (options.validationMessage?.isNotEmpty ?? true));
final QuillController controller;
- final IconData? icon;
- final double iconSize;
- final QuillIconTheme? iconTheme;
- final QuillDialogTheme? dialogTheme;
- final VoidCallback? afterButtonPressed;
- final String? tooltip;
-
- /// The constrains for dialog.
- final BoxConstraints? constraints;
-
- /// The text of label in link add mode.
- final String? addLinkLabel;
-
- /// The text of label in link edit mode.
- final String? editLinkLabel;
-
- /// The color of URL.
- final Color? linkColor;
-
- /// The margin between child widgets in the dialog.
- final double childrenSpacing;
-
- final AutovalidateMode autovalidateMode;
- final String? validationMessage;
-
- /// The size of dialog buttons.
- final Size? buttonSize;
-
- final Color dialogBarrierColor;
+ final QuillToolbarLinkStyleButton2Options options;
@override
State createState() =>
@@ -99,30 +61,101 @@ class _QuillToolbarLinkStyleButton2State
}
}
+ QuillController get controller {
+ return widget.controller;
+ }
+
+ QuillToolbarLinkStyleButton2Options get options {
+ return widget.options;
+ }
+
+ double get iconSize {
+ final baseFontSize = baseButtonExtraOptions.globalIconSize;
+ final iconSize = options.iconSize;
+ return iconSize ?? baseFontSize;
+ }
+
+ VoidCallback? get afterButtonPressed {
+ return options.afterButtonPressed ??
+ baseButtonExtraOptions.afterButtonPressed;
+ }
+
+ QuillIconTheme? get iconTheme {
+ return options.iconTheme ?? baseButtonExtraOptions.iconTheme;
+ }
+
+ QuillToolbarBaseButtonOptions get baseButtonExtraOptions {
+ return context.requireQuillToolbarBaseButtonOptions;
+ }
+
+ String get tooltip {
+ return options.tooltip ??
+ baseButtonExtraOptions.tooltip ??
+ 'Insert URL'.i18n;
+ }
+
+ IconData get iconData {
+ return options.iconData ?? baseButtonExtraOptions.iconData ?? Icons.link;
+ }
+
+ Color get dialogBarrierColor {
+ return options.dialogBarrierColor ??
+ context.requireQuillSharedConfigurations.dialogBarrierColor;
+ }
+
@override
Widget build(BuildContext context) {
+ final childBuilder =
+ options.childBuilder ?? baseButtonExtraOptions.childBuilder;
+ if (childBuilder != null) {
+ return childBuilder(
+ QuillToolbarLinkStyleButton2Options(
+ iconData: iconData,
+ addLinkLabel: options.addLinkLabel,
+ afterButtonPressed: options.afterButtonPressed,
+ autovalidateMode: options.autovalidateMode,
+ buttonSize: options.buttonSize,
+ childrenSpacing: options.childrenSpacing,
+ dialogBarrierColor: dialogBarrierColor,
+ dialogTheme: options.dialogTheme,
+ iconSize: iconSize,
+ constraints: options.constraints,
+ tooltip: tooltip,
+ iconTheme: iconTheme,
+ editLinkLabel: options.editLinkLabel,
+ validationMessage: options.validationMessage,
+ linkColor: options.linkColor,
+ ),
+ QuillToolbarLinkStyleButton2ExtraOptions(
+ controller: controller,
+ context: context,
+ onPressed: () {
+ _openLinkDialog();
+ afterButtonPressed?.call();
+ },
+ ),
+ );
+ }
final theme = Theme.of(context);
final isToggled = _getLinkAttributeValue() != null;
return QuillToolbarIconButton(
- tooltip: widget.tooltip,
+ tooltip: tooltip,
highlightElevation: 0,
hoverElevation: 0,
- size: widget.iconSize * kIconButtonFactor,
+ size: iconSize * kIconButtonFactor,
icon: Icon(
- widget.icon ?? Icons.link,
- size: widget.iconSize,
+ iconData,
+ size: iconSize,
color: isToggled
- ? (widget.iconTheme?.iconSelectedColor ??
- theme.primaryIconTheme.color)
- : (widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
+ ? (iconTheme?.iconSelectedColor ?? theme.primaryIconTheme.color)
+ : (iconTheme?.iconUnselectedColor ?? theme.iconTheme.color),
),
fillColor: isToggled
- ? (widget.iconTheme?.iconSelectedFillColor ??
- Theme.of(context).primaryColor)
- : (widget.iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
- borderRadius: widget.iconTheme?.borderRadius ?? 2,
+ ? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
+ : (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
+ borderRadius: iconTheme?.borderRadius ?? 2,
onPressed: _openLinkDialog,
- afterPressed: widget.afterButtonPressed,
+ afterPressed: afterButtonPressed,
);
}
@@ -131,19 +164,19 @@ class _QuillToolbarLinkStyleButton2State
final textLink = await showDialog(
context: context,
- barrierColor: widget.dialogBarrierColor,
+ barrierColor: dialogBarrierColor,
builder: (_) => LinkStyleDialog(
- dialogTheme: widget.dialogTheme,
+ dialogTheme: options.dialogTheme,
text: initialTextLink.text,
link: initialTextLink.link,
- constraints: widget.constraints,
- addLinkLabel: widget.addLinkLabel,
- editLinkLabel: widget.editLinkLabel,
- linkColor: widget.linkColor,
- childrenSpacing: widget.childrenSpacing,
- autovalidateMode: widget.autovalidateMode,
- validationMessage: widget.validationMessage,
- buttonSize: widget.buttonSize,
+ constraints: options.constraints,
+ addLinkLabel: options.addLinkLabel,
+ editLinkLabel: options.editLinkLabel,
+ linkColor: options.linkColor,
+ childrenSpacing: options.childrenSpacing,
+ autovalidateMode: options.autovalidateMode,
+ validationMessage: options.validationMessage,
+ buttonSize: options.buttonSize,
),
);
@@ -166,7 +199,7 @@ class _QuillToolbarLinkStyleButton2State
class LinkStyleDialog extends StatefulWidget {
const LinkStyleDialog({
- Key? key,
+ super.key,
this.text,
this.link,
this.dialogTheme,
@@ -183,8 +216,7 @@ class LinkStyleDialog extends StatefulWidget {
}) : assert(addLinkLabel == null || addLinkLabel.length > 0),
assert(editLinkLabel == null || editLinkLabel.length > 0),
assert(childrenSpacing > 0),
- assert(validationMessage == null || validationMessage.length > 0),
- super(key: key);
+ assert(validationMessage == null || validationMessage.length > 0);
final String? text;
final String? link;
@@ -387,7 +419,7 @@ class _LinkStyleDialogState extends State {
String? _validateLink(String? value) {
if ((value?.isEmpty ?? false) ||
- !AutoFormatMultipleLinksRule.oneLineRegExp.hasMatch(value!)) {
+ !AutoFormatMultipleLinksRule.oneLineLinkRegExp.hasMatch(value!)) {
return widget.validationMessage ?? 'That is not a valid URL';
}
diff --git a/lib/src/widgets/toolbar/buttons/select_alignment.dart b/lib/src/widgets/toolbar/buttons/select_alignment.dart
index 2d4018dd..9ee36622 100644
--- a/lib/src/widgets/toolbar/buttons/select_alignment.dart
+++ b/lib/src/widgets/toolbar/buttons/select_alignment.dart
@@ -60,18 +60,18 @@ class _QuillToolbarSelectAlignmentButtonState
return widget.controller;
}
- double get iconSize {
+ double get _iconSize {
final baseFontSize = baseButtonExtraOptions.globalIconSize;
final iconSize = options.iconSize;
return iconSize ?? baseFontSize;
}
- VoidCallback? get afterButtonPressed {
+ VoidCallback? get _afterButtonPressed {
return options.afterButtonPressed ??
baseButtonExtraOptions.afterButtonPressed;
}
- QuillIconTheme? get iconTheme {
+ QuillIconTheme? get _iconTheme {
return options.iconTheme ?? baseButtonExtraOptions.iconTheme;
}
@@ -191,25 +191,42 @@ class _QuillToolbarSelectAlignmentButtonState
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
- if (childBuilder != null) {
- throw UnsupportedError(
- 'Sorry but the `childBuilder` for the Select alignment buttons'
- ' is not supported. Yet but we will work on that soon.',
- );
+ void _sharedOnPressed(int index) {
+ _valueAttribute[index] == Attribute.leftAlignment
+ ? controller.formatSelection(
+ Attribute.clone(Attribute.align, null),
+ )
+ : controller.formatSelection(_valueAttribute[index]);
+ _afterButtonPressed?.call();
}
- final theme = Theme.of(context);
-
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(buttonCount, (index) {
+ if (childBuilder != null) {
+ return childBuilder(
+ QuillToolbarSelectAlignmentButtonOptions(
+ afterButtonPressed: _afterButtonPressed,
+ iconSize: _iconSize,
+ iconTheme: _iconTheme,
+ tooltips: _tooltips,
+ iconsData: _iconsData,
+ ),
+ QuillToolbarSelectAlignmentButtonExtraOptions(
+ context: context,
+ controller: controller,
+ onPressed: () => _sharedOnPressed(index),
+ ),
+ );
+ }
+ final theme = Theme.of(context);
return Padding(
padding: widget.padding ??
const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
- width: iconSize * kIconButtonFactor,
- height: iconSize * kIconButtonFactor,
+ width: _iconSize * kIconButtonFactor,
+ height: _iconSize * kIconButtonFactor,
),
child: UtilityWidgets.maybeTooltip(
message: _valueString[index] == Attribute.leftAlignment.value
@@ -226,19 +243,12 @@ class _QuillToolbarSelectAlignmentButtonState
visualDensity: VisualDensity.compact,
shape: RoundedRectangleBorder(
borderRadius:
- BorderRadius.circular(iconTheme?.borderRadius ?? 2)),
+ BorderRadius.circular(_iconTheme?.borderRadius ?? 2)),
fillColor: _valueToText[_value] == _valueString[index]
- ? (iconTheme?.iconSelectedFillColor ??
- Theme.of(context).primaryColor)
- : (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
- onPressed: () {
- _valueAttribute[index] == Attribute.leftAlignment
- ? controller.formatSelection(
- Attribute.clone(Attribute.align, null),
- )
- : controller.formatSelection(_valueAttribute[index]);
- afterButtonPressed?.call();
- },
+ ? (_iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
+ : (_iconTheme?.iconUnselectedFillColor ??
+ theme.canvasColor),
+ onPressed: () => _sharedOnPressed(index),
child: Icon(
_valueString[index] == Attribute.leftAlignment.value
? _iconsData.leftAlignment
@@ -248,11 +258,11 @@ class _QuillToolbarSelectAlignmentButtonState
Attribute.rightAlignment.value
? _iconsData.rightAlignment
: _iconsData.justifyAlignment,
- size: iconSize,
+ size: _iconSize,
color: _valueToText[_value] == _valueString[index]
- ? (iconTheme?.iconSelectedColor ??
+ ? (_iconTheme?.iconSelectedColor ??
theme.primaryIconTheme.color)
- : (iconTheme?.iconUnselectedColor ??
+ : (_iconTheme?.iconUnselectedColor ??
theme.iconTheme.color),
),
),
diff --git a/lib/src/widgets/toolbar/buttons/select_header_style.dart b/lib/src/widgets/toolbar/buttons/select_header_style.dart
index 57ba28d2..987f9f3e 100644
--- a/lib/src/widgets/toolbar/buttons/select_header_style.dart
+++ b/lib/src/widgets/toolbar/buttons/select_header_style.dart
@@ -1,3 +1,4 @@
+import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import '../../../../extensions.dart';
@@ -90,10 +91,20 @@ class _QuillToolbarSelectHeaderStyleButtonsState
afterButtonPressed?.call();
}
+ List get _attrbuites {
+ return options.attributes ??
+ const [
+ Attribute.header,
+ Attribute.h1,
+ Attribute.h2,
+ Attribute.h3,
+ ];
+ }
+
@override
Widget build(BuildContext context) {
assert(
- options.attributes.every(
+ _attrbuites.every(
(element) => _valueToText.keys.contains(element),
),
'All attributes must be one of them: header, h1, h2 or h3',
@@ -107,19 +118,28 @@ class _QuillToolbarSelectHeaderStyleButtonsState
final childBuilder =
options.childBuilder ?? baseButtonExtraOptions.childBuilder;
- if (childBuilder != null) {
- throw UnsupportedError(
- 'Sorry but the `childBuilder` for the Select header button'
- ' is not supported. Yet but we will work on that soon.',
- );
- }
- final theme = Theme.of(context);
-
- final children = options.attributes.map((attribute) {
+ final children = _attrbuites.map((attribute) {
+ if (childBuilder != null) {
+ return childBuilder(
+ QuillToolbarSelectHeaderStyleButtonsOptions(
+ afterButtonPressed: afterButtonPressed,
+ attributes: _attrbuites,
+ axis: axis,
+ iconSize: iconSize,
+ iconTheme: iconTheme,
+ tooltip: tooltip,
+ ),
+ QuillToolbarSelectHeaderStyleButtonExtraOptions(
+ controller: controller,
+ context: context,
+ onPressed: () => _sharedOnPressed(attribute),
+ ),
+ );
+ }
+ final theme = Theme.of(context);
final isSelected = _selectedAttribute == attribute;
return Padding(
- // Do we really need to ignore (prefer_const_constructors)??
- padding: EdgeInsets.symmetric(horizontal: !isWeb() ? 1.0 : 5.0),
+ padding: const EdgeInsets.symmetric(horizontal: !kIsWeb ? 1.0 : 5.0),
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
width: iconSize * kIconButtonFactor,
@@ -136,12 +156,14 @@ class _QuillToolbarSelectHeaderStyleButtonsState
borderRadius:
BorderRadius.circular(iconTheme?.borderRadius ?? 2)),
fillColor: isSelected
- ? (iconTheme?.iconSelectedFillColor ??
- Theme.of(context).primaryColor)
+ ? (iconTheme?.iconSelectedFillColor ?? theme.primaryColor)
: (iconTheme?.iconUnselectedFillColor ?? theme.canvasColor),
onPressed: () => _sharedOnPressed(attribute),
child: Text(
- _valueToText[attribute] ?? '',
+ _valueToText[attribute] ??
+ (throw ArgumentError.notNull(
+ 'attrbuite',
+ )),
style: style.copyWith(
color: isSelected
? (iconTheme?.iconSelectedColor ??
diff --git a/lib/src/widgets/toolbar/toolbar.dart b/lib/src/widgets/toolbar/toolbar.dart
index 092f5012..6749f0b5 100644
--- a/lib/src/widgets/toolbar/toolbar.dart
+++ b/lib/src/widgets/toolbar/toolbar.dart
@@ -70,36 +70,47 @@ class QuillToolbar extends StatelessWidget {
final axis = toolbarConfigurations.axis;
final globalController = context.requireQuillController;
+ final spacerWidget =
+ configurations.spacerWidget ?? const SizedBox.shrink();
+
return [
- if (configurations.showUndo)
+ if (configurations.showUndo) ...[
QuillToolbarHistoryButton(
options: toolbarConfigurations.buttonOptions.undoHistory,
controller: toolbarConfigurations
.buttonOptions.undoHistory.controller ??
globalController,
),
- if (configurations.showRedo)
+ spacerWidget,
+ ],
+ if (configurations.showRedo) ...[
QuillToolbarHistoryButton(
options: toolbarConfigurations.buttonOptions.redoHistory,
controller: toolbarConfigurations
.buttonOptions.redoHistory.controller ??
globalController,
),
- if (configurations.showFontFamily)
+ spacerWidget,
+ ],
+ if (configurations.showFontFamily) ...[
QuillToolbarFontFamilyButton(
options: toolbarConfigurations.buttonOptions.fontFamily,
controller: toolbarConfigurations
.buttonOptions.fontFamily.controller ??
globalController,
),
- if (configurations.showFontSize)
+ spacerWidget,
+ ],
+ if (configurations.showFontSize) ...[
QuillToolbarFontSizeButton(
options: toolbarConfigurations.buttonOptions.fontSize,
controller: toolbarConfigurations
.buttonOptions.fontFamily.controller ??
globalController,
),
- if (configurations.showBoldButton)
+ spacerWidget,
+ ],
+ if (configurations.showBoldButton) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.bold,
options: toolbarConfigurations.buttonOptions.bold,
@@ -107,7 +118,9 @@ class QuillToolbar extends StatelessWidget {
toolbarConfigurations.buttonOptions.bold.controller ??
globalController,
),
- if (configurations.showSubscript)
+ spacerWidget,
+ ],
+ if (configurations.showSubscript) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.subscript,
options: toolbarConfigurations.buttonOptions.subscript,
@@ -115,7 +128,9 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.subscript.controller ??
globalController,
),
- if (configurations.showSuperscript)
+ spacerWidget,
+ ],
+ if (configurations.showSuperscript) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.superscript,
options: toolbarConfigurations.buttonOptions.superscript,
@@ -123,7 +138,9 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.superscript.controller ??
globalController,
),
- if (configurations.showItalicButton)
+ spacerWidget,
+ ],
+ if (configurations.showItalicButton) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.italic,
options: toolbarConfigurations.buttonOptions.italic,
@@ -131,7 +148,9 @@ class QuillToolbar extends StatelessWidget {
toolbarConfigurations.buttonOptions.italic.controller ??
globalController,
),
- if (configurations.showSmallButton)
+ spacerWidget,
+ ],
+ if (configurations.showSmallButton) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.small,
options: toolbarConfigurations.buttonOptions.small,
@@ -139,7 +158,9 @@ class QuillToolbar extends StatelessWidget {
toolbarConfigurations.buttonOptions.small.controller ??
globalController,
),
- if (configurations.showUnderLineButton)
+ spacerWidget,
+ ],
+ if (configurations.showUnderLineButton) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.underline,
options: toolbarConfigurations.buttonOptions.underLine,
@@ -147,7 +168,9 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.underLine.controller ??
globalController,
),
- if (configurations.showStrikeThrough)
+ spacerWidget,
+ ],
+ if (configurations.showStrikeThrough) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.strikeThrough,
options: toolbarConfigurations.buttonOptions.strikeThrough,
@@ -155,7 +178,9 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.strikeThrough.controller ??
globalController,
),
- if (configurations.showInlineCode)
+ spacerWidget,
+ ],
+ if (configurations.showInlineCode) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.inlineCode,
options: toolbarConfigurations.buttonOptions.inlineCode,
@@ -163,23 +188,31 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.inlineCode.controller ??
globalController,
),
- if (configurations.showColorButton)
+ spacerWidget,
+ ],
+ if (configurations.showColorButton) ...[
QuillToolbarColorButton(
controller: controller,
isBackground: false,
options: toolbarConfigurations.buttonOptions.color,
),
- if (configurations.showBackgroundColorButton)
+ spacerWidget,
+ ],
+ if (configurations.showBackgroundColorButton) ...[
QuillToolbarColorButton(
options: toolbarConfigurations.buttonOptions.backgroundColor,
controller: controller,
isBackground: true,
),
- if (configurations.showClearFormat)
+ spacerWidget,
+ ],
+ if (configurations.showClearFormat) ...[
QuillToolbarClearFormatButton(
controller: controller,
options: toolbarConfigurations.buttonOptions.clearFormat,
),
+ spacerWidget,
+ ],
if (theEmbedButtons != null)
for (final builder in theEmbedButtons)
builder(
@@ -199,7 +232,7 @@ class QuillToolbar extends StatelessWidget {
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- if (configurations.showAlignmentButtons)
+ if (configurations.showAlignmentButtons) ...[
QuillToolbarSelectAlignmentButton(
controller: controller,
options: toolbarConfigurations
@@ -216,7 +249,9 @@ class QuillToolbar extends StatelessWidget {
showRightAlignment: configurations.showRightAlignment,
showJustifyAlignment: configurations.showJustifyAlignment,
),
- if (configurations.showDirection)
+ spacerWidget,
+ ],
+ if (configurations.showDirection) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.rtl,
options: toolbarConfigurations.buttonOptions.direction,
@@ -224,6 +259,8 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.direction.controller ??
context.requireQuillController,
),
+ spacerWidget,
+ ],
if (configurations.showDividers &&
isButtonGroupShown[1] &&
(isButtonGroupShown[2] ||
@@ -235,12 +272,14 @@ class QuillToolbar extends StatelessWidget {
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- if (configurations.showHeaderStyle)
+ if (configurations.showHeaderStyle) ...[
QuillToolbarSelectHeaderStyleButtons(
controller: controller,
options: toolbarConfigurations
.buttonOptions.selectHeaderStyleButtons,
),
+ spacerWidget,
+ ],
if (configurations.showDividers &&
configurations.showHeaderStyle &&
isButtonGroupShown[2] &&
@@ -252,7 +291,7 @@ class QuillToolbar extends StatelessWidget {
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- if (configurations.showListNumbers)
+ if (configurations.showListNumbers) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.ol,
options: toolbarConfigurations.buttonOptions.listNumbers,
@@ -260,7 +299,9 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.listNumbers.controller ??
globalController,
),
- if (configurations.showListBullets)
+ spacerWidget,
+ ],
+ if (configurations.showListBullets) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.ul,
options: toolbarConfigurations.buttonOptions.listBullets,
@@ -268,14 +309,18 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.listBullets.controller ??
globalController,
),
- if (configurations.showListCheck)
+ spacerWidget,
+ ],
+ if (configurations.showListCheck) ...[
QuillToolbarToggleCheckListButton(
options: toolbarConfigurations.buttonOptions.toggleCheckList,
controller: toolbarConfigurations
.buttonOptions.toggleCheckList.controller ??
globalController,
),
- if (configurations.showCodeBlock)
+ spacerWidget,
+ ],
+ if (configurations.showCodeBlock) ...[
QuillToolbarToggleStyleButton(
attribute: Attribute.codeBlock,
options: toolbarConfigurations.buttonOptions.codeBlock,
@@ -283,15 +328,18 @@ class QuillToolbar extends StatelessWidget {
.buttonOptions.codeBlock.controller ??
globalController,
),
+ spacerWidget,
+ ],
if (configurations.showDividers &&
isButtonGroupShown[3] &&
- (isButtonGroupShown[4] || isButtonGroupShown[5]))
+ (isButtonGroupShown[4] || isButtonGroupShown[5])) ...[
QuillToolbarDivider(
axis,
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- if (configurations.showQuote)
+ ],
+ if (configurations.showQuote) ...[
QuillToolbarToggleStyleButton(
options: toolbarConfigurations.buttonOptions.quote,
controller:
@@ -299,7 +347,9 @@ class QuillToolbar extends StatelessWidget {
globalController,
attribute: Attribute.blockQuote,
),
- if (configurations.showIndent)
+ spacerWidget,
+ ],
+ if (configurations.showIndent) ...[
QuillToolbarIndentButton(
controller: toolbarConfigurations
.buttonOptions.indentIncrease.controller ??
@@ -307,7 +357,9 @@ class QuillToolbar extends StatelessWidget {
isIncrease: true,
options: toolbarConfigurations.buttonOptions.indentIncrease,
),
- if (configurations.showIndent)
+ spacerWidget,
+ ],
+ if (configurations.showIndent) ...[
QuillToolbarIndentButton(
controller: toolbarConfigurations
.buttonOptions.indentDecrease.controller ??
@@ -315,6 +367,8 @@ class QuillToolbar extends StatelessWidget {
isIncrease: false,
options: toolbarConfigurations.buttonOptions.indentDecrease,
),
+ spacerWidget,
+ ],
if (configurations.showDividers &&
isButtonGroupShown[4] &&
isButtonGroupShown[5])
@@ -323,45 +377,51 @@ class QuillToolbar extends StatelessWidget {
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- if (configurations.showLink)
+ if (configurations.showLink) ...[
QuillToolbarLinkStyleButton(
controller: controller,
options: toolbarConfigurations.buttonOptions.linkStyle,
),
- if (configurations.showSearchButton)
+ spacerWidget,
+ ],
+ if (configurations.showSearchButton) ...[
QuillToolbarSearchButton(
controller: controller,
options: toolbarConfigurations.buttonOptions.search,
),
- if (configurations.customButtons.isNotEmpty)
+ spacerWidget,
+ ],
+ if (configurations.customButtons.isNotEmpty) ...[
if (configurations.showDividers)
QuillToolbarDivider(
axis,
color: configurations.sectionDividerColor,
space: configurations.sectionDividerSpace,
),
- for (final customButton in configurations.customButtons)
- if (customButton.child != null) ...[
- InkWell(
- onTap: customButton.onTap,
- child: customButton.child,
- ),
- ] else ...[
- CustomButton(
- onPressed: customButton.onTap,
- icon: customButton.iconData ??
- context.quillToolbarBaseButtonOptions?.iconData,
- iconColor: customButton.iconColor,
- iconSize: customButton.iconSize ?? globalIconSize,
- iconTheme:
- context.requireQuillToolbarBaseButtonOptions.iconTheme,
- afterButtonPressed: customButton.afterButtonPressed ??
- context
- .quillToolbarBaseButtonOptions?.afterButtonPressed,
- tooltip: customButton.tooltip ??
- context.quillToolbarBaseButtonOptions?.tooltip,
- ),
- ],
+ for (final customButton in configurations.customButtons)
+ if (customButton.child != null) ...[
+ InkWell(
+ onTap: customButton.onTap,
+ child: customButton.child,
+ ),
+ ] else ...[
+ CustomButton(
+ onPressed: customButton.onTap,
+ icon: customButton.iconData ??
+ context.quillToolbarBaseButtonOptions?.iconData,
+ iconColor: customButton.iconColor,
+ iconSize: customButton.iconSize ?? globalIconSize,
+ iconTheme: context
+ .requireQuillToolbarBaseButtonOptions.iconTheme,
+ afterButtonPressed: customButton.afterButtonPressed ??
+ context.quillToolbarBaseButtonOptions
+ ?.afterButtonPressed,
+ tooltip: customButton.tooltip ??
+ context.quillToolbarBaseButtonOptions?.tooltip,
+ ),
+ ],
+ spacerWidget,
+ ],
];
},
),
diff --git a/pubspec.yaml b/pubspec.yaml
index 8fd42e6e..1be2a3a6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_quill
description: A rich text editor built for the modern Android, iOS, web and desktop platforms. It is the WYSIWYG editor and a Quill component for Flutter.
-version: 8.1.1
+version: 8.1.2
homepage: https://1o24bbs.com/c/bulletjournal/108
repository: https://github.com/singerdmx/flutter-quill
topics:
@@ -17,7 +17,8 @@ platforms:
windows:
environment:
- sdk: ">=2.17.0 <4.0.0"
+ sdk: '>=3.1.3 <4.0.0'
+ # sdk: ">=2.17.0 <4.0.0"
flutter: ">=3.10.0"
dependencies:
@@ -40,5 +41,6 @@ dependencies:
flutter_test:
sdk: flutter
+ meta: ^1.9.1
flutter: null
\ No newline at end of file
diff --git a/test/bug_fix_test.dart b/test/bug_fix_test.dart
index 6ade28f5..9869d517 100644
--- a/test/bug_fix_test.dart
+++ b/test/bug_fix_test.dart
@@ -130,7 +130,7 @@ void main() {
controller.formatSelection(Attribute.unchecked);
editor.focusNode.unfocus();
await tester.pump();
- await tester.tap(find.byType(CheckboxPoint));
+ await tester.tap(find.byType(QuillEditorCheckboxPoint));
expect(tester.takeException(), isNull);
});
});