diff --git a/analysis_options.yaml b/analysis_options.yaml index e62a6e5c..2fc4fec6 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -29,5 +29,7 @@ linter: - prefer_interpolation_to_compose_strings - prefer_relative_imports - prefer_single_quotes + - sort_constructors_first + - sort_unnamed_constructors_first - unnecessary_parenthesis - unnecessary_string_interpolations diff --git a/example/lib/widgets/demo_scaffold.dart b/example/lib/widgets/demo_scaffold.dart index 52d44e4f..4098a5f6 100644 --- a/example/lib/widgets/demo_scaffold.dart +++ b/example/lib/widgets/demo_scaffold.dart @@ -11,13 +11,6 @@ typedef DemoContentBuilder = Widget Function( // Common scaffold for all examples. class DemoScaffold extends StatefulWidget { - /// Filename of the document to load into the editor. - final String documentFilename; - final DemoContentBuilder builder; - final List? actions; - final Widget? floatingActionButton; - final bool showToolbar; - const DemoScaffold({ required this.documentFilename, required this.builder, @@ -27,6 +20,13 @@ class DemoScaffold extends StatefulWidget { Key? key, }) : super(key: key); + /// Filename of the document to load into the editor. + final String documentFilename; + final DemoContentBuilder builder; + final List? actions; + final Widget? floatingActionButton; + final bool showToolbar; + @override _DemoScaffoldState createState() => _DemoScaffoldState(); } diff --git a/lib/models/documents/attribute.dart b/lib/models/documents/attribute.dart index 7683b9ed..18822e01 100644 --- a/lib/models/documents/attribute.dart +++ b/lib/models/documents/attribute.dart @@ -8,12 +8,12 @@ enum AttributeScope { } class Attribute { + Attribute(this.key, this.scope, this.value); + final String key; final AttributeScope scope; final T value; - Attribute(this.key, this.scope, this.value); - static final Map _registry = { Attribute.bold.key: Attribute.bold, Attribute.italic.key: Attribute.italic, diff --git a/lib/models/documents/document.dart b/lib/models/documents/document.dart index 232642fb..0362665e 100644 --- a/lib/models/documents/document.dart +++ b/lib/models/documents/document.dart @@ -15,6 +15,18 @@ import 'style.dart'; /// The rich text document class Document { + Document() : _delta = Delta()..insert('\n') { + _loadDocument(_delta); + } + + Document.fromJson(List data) : _delta = _transform(Delta.fromJson(data)) { + _loadDocument(_delta); + } + + Document.fromDelta(Delta delta) : _delta = delta { + _loadDocument(delta); + } + /// The root node of the document tree final Root _root = Root(); @@ -35,18 +47,6 @@ class Document { Stream> get changes => _observer.stream; - Document() : _delta = Delta()..insert('\n') { - _loadDocument(_delta); - } - - Document.fromJson(List data) : _delta = _transform(Delta.fromJson(data)) { - _loadDocument(_delta); - } - - Document.fromDelta(Delta delta) : _delta = delta { - _loadDocument(delta); - } - Delta insert(int index, Object? data) { assert(index >= 0); assert(data is String || data is Embeddable); diff --git a/lib/models/documents/history.dart b/lib/models/documents/history.dart index 9398ad1c..d406505e 100644 --- a/lib/models/documents/history.dart +++ b/lib/models/documents/history.dart @@ -4,6 +4,14 @@ import '../quill_delta.dart'; import 'document.dart'; class History { + History({ + this.ignoreChange = false, + this.interval = 400, + this.maxStack = 100, + this.userOnly = false, + this.lastRecorded = 0, + }); + final HistoryStack stack = HistoryStack.empty(); bool get hasUndo => stack.undo.isNotEmpty; @@ -24,13 +32,6 @@ class History { ///record delay final int interval; - History( - {this.ignoreChange = false, - this.interval = 400, - this.maxStack = 100, - this.userOnly = false, - this.lastRecorded = 0}); - void handleDocChange(Tuple3 change) { if (ignoreChange) return; if (!userOnly || change.item3 == ChangeSource.LOCAL) { @@ -119,13 +120,13 @@ class History { } class HistoryStack { - final List undo; - final List redo; - HistoryStack.empty() : undo = [], redo = []; + final List undo; + final List redo; + void clear() { undo.clear(); redo.clear(); diff --git a/lib/models/documents/nodes/container.dart b/lib/models/documents/nodes/container.dart index 8b3fd0c3..28fc2475 100644 --- a/lib/models/documents/nodes/container.dart +++ b/lib/models/documents/nodes/container.dart @@ -116,9 +116,9 @@ abstract class Container extends Node { /// Query of a child in a Container class ChildQuery { + ChildQuery(this.node, this.offset); + final Node? node; // null if not found final int offset; - - ChildQuery(this.node, this.offset); } diff --git a/lib/models/documents/nodes/embed.dart b/lib/models/documents/nodes/embed.dart index cc0ecaea..81ca6005 100644 --- a/lib/models/documents/nodes/embed.dart +++ b/lib/models/documents/nodes/embed.dart @@ -1,9 +1,9 @@ class Embeddable { + Embeddable(this.type, this.data); + final String type; final dynamic data; - Embeddable(this.type, this.data); - Map toJson() { final m = {type: data}; return m; diff --git a/lib/models/documents/nodes/leaf.dart b/lib/models/documents/nodes/leaf.dart index 3d98060e..24431fc9 100644 --- a/lib/models/documents/nodes/leaf.dart +++ b/lib/models/documents/nodes/leaf.dart @@ -8,12 +8,6 @@ import 'node.dart'; /* A leaf node in document tree */ abstract class Leaf extends Node { - Object _value; - - Object get value => _value; - - Leaf.val(Object val) : _value = val; - factory Leaf(Object data) { if (data is Embeddable) { return Embed(data); @@ -23,6 +17,12 @@ abstract class Leaf extends Node { return Text(text); } + Leaf.val(Object val) : _value = val; + + Object _value; + + Object get value => _value; + @override void applyStyle(Style value) { assert(value.isInline || value.isIgnored || value.isEmpty, diff --git a/lib/models/documents/style.dart b/lib/models/documents/style.dart index f8a8ee74..c805280d 100644 --- a/lib/models/documents/style.dart +++ b/lib/models/documents/style.dart @@ -5,11 +5,11 @@ import 'attribute.dart'; /* Collection of style attributes */ class Style { - final Map _attributes; + Style() : _attributes = {}; Style.attr(this._attributes); - Style() : _attributes = {}; + final Map _attributes; static Style fromJson(Map? attributes) { if (attributes == null) { diff --git a/lib/models/quill_delta.dart b/lib/models/quill_delta.dart index 0135bd6a..895b27fe 100644 --- a/lib/models/quill_delta.dart +++ b/lib/models/quill_delta.dart @@ -22,6 +22,29 @@ Object? _passThroughDataDecoder(Object? data) => data; /// Operation performed on a rich-text document. class Operation { + Operation._(this.key, this.length, this.data, Map? attributes) + : assert(_validKeys.contains(key), 'Invalid operation key "$key".'), + assert(() { + if (key != Operation.insertKey) return true; + return data is String ? data.length == length : length == 1; + }(), 'Length of insert operation must be equal to the data length.'), + _attributes = + attributes != null ? Map.from(attributes) : null; + + /// Creates operation which deletes [length] of characters. + factory Operation.delete(int length) => + Operation._(Operation.deleteKey, length, '', null); + + /// Creates operation which inserts [text] with optional [attributes]. + factory Operation.insert(dynamic data, [Map? attributes]) => + Operation._(Operation.insertKey, data is String ? data.length : 1, data, + attributes); + + /// Creates operation which retains [length] of characters and optionally + /// applies attributes. + factory Operation.retain(int? length, [Map? attributes]) => + Operation._(Operation.retainKey, length, '', attributes); + /// Key of insert operations. static const String insertKey = 'insert'; @@ -50,15 +73,6 @@ class Operation { _attributes == null ? null : Map.from(_attributes!); final Map? _attributes; - Operation._(this.key, this.length, this.data, Map? attributes) - : assert(_validKeys.contains(key), 'Invalid operation key "$key".'), - assert(() { - if (key != Operation.insertKey) return true; - return data is String ? data.length == length : length == 1; - }(), 'Length of insert operation must be equal to the data length.'), - _attributes = - attributes != null ? Map.from(attributes) : null; - /// Creates new [Operation] from JSON payload. /// /// If `dataDecoder` parameter is not null then it is used to additionally @@ -89,20 +103,6 @@ class Operation { return json; } - /// Creates operation which deletes [length] of characters. - factory Operation.delete(int length) => - Operation._(Operation.deleteKey, length, '', null); - - /// Creates operation which inserts [text] with optional [attributes]. - factory Operation.insert(dynamic data, [Map? attributes]) => - Operation._(Operation.insertKey, data is String ? data.length : 1, data, - attributes); - - /// Creates operation which retains [length] of characters and optionally - /// applies attributes. - factory Operation.retain(int? length, [Map? attributes]) => - Operation._(Operation.retainKey, length, '', attributes); - /// Returns value of this operation. /// /// For insert operations this returns text, for delete and retain - length. @@ -180,6 +180,15 @@ class Operation { /// "document delta". When delta includes also "retain" or "delete" operations /// it is a "change delta". class Delta { + /// Creates new empty [Delta]. + factory Delta() => Delta._([]); + + Delta._(List operations) : _operations = operations; + + /// Creates new [Delta] from [other]. + factory Delta.from(Delta other) => + Delta._(List.from(other._operations)); + /// Transforms two attribute sets. static Map? transformAttributes( Map? a, Map? b, bool priority) { @@ -242,15 +251,6 @@ class Delta { int _modificationCount = 0; - Delta._(List operations) : _operations = operations; - - /// Creates new empty [Delta]. - factory Delta() => Delta._([]); - - /// Creates new [Delta] from [other]. - factory Delta.from(Delta other) => - Delta._(List.from(other._operations)); - /// Creates [Delta] from de-serialized JSON representation. /// /// If `dataDecoder` parameter is not null then it is used to additionally @@ -599,13 +599,13 @@ class Delta { /// Specialized iterator for [Delta]s. class DeltaIterator { + DeltaIterator(this.delta) : _modificationCount = delta._modificationCount; + final Delta delta; final int _modificationCount; int _index = 0; num _offset = 0; - DeltaIterator(this.delta) : _modificationCount = delta._modificationCount; - bool get isNextInsert => nextOperationKey == Operation.insertKey; bool get isNextDelete => nextOperationKey == Operation.deleteKey; diff --git a/lib/models/rules/rule.dart b/lib/models/rules/rule.dart index 19bc9177..4ee6c278 100644 --- a/lib/models/rules/rule.dart +++ b/lib/models/rules/rule.dart @@ -26,6 +26,8 @@ abstract class Rule { } class Rules { + Rules(this._rules); + final List _rules; static final Rules _instance = Rules([ const FormatLinkAtCaretPositionRule(), @@ -45,8 +47,6 @@ class Rules { const CatchAllDeleteRule(), ]); - Rules(this._rules); - static Rules getInstance() => _instance; Delta apply(RuleType ruleType, Document document, int index, diff --git a/lib/utils/diff_delta.dart b/lib/utils/diff_delta.dart index 1e6d913e..003bae47 100644 --- a/lib/utils/diff_delta.dart +++ b/lib/utils/diff_delta.dart @@ -33,6 +33,8 @@ const Set WHITE_SPACE = { // Diff between two texts - old text and new text class Diff { + Diff(this.start, this.deleted, this.inserted); + // Start index in old text at which changes begin. final int start; @@ -42,8 +44,6 @@ class Diff { // The inserted text final String inserted; - Diff(this.start, this.deleted, this.inserted); - @override String toString() { return 'Diff[$start, "$deleted", "$inserted"]'; diff --git a/lib/widgets/controller.dart b/lib/widgets/controller.dart index faabf4c2..3bd66b6f 100644 --- a/lib/widgets/controller.dart +++ b/lib/widgets/controller.dart @@ -11,10 +11,6 @@ import '../models/quill_delta.dart'; import '../utils/diff_delta.dart'; class QuillController extends ChangeNotifier { - final Document document; - TextSelection selection; - Style toggledStyle = Style(); - QuillController({required this.document, required this.selection}); factory QuillController.basic() { @@ -24,6 +20,10 @@ class QuillController extends ChangeNotifier { ); } + final Document document; + TextSelection selection; + Style toggledStyle = Style(); + // item1: Document state before [change]. // // item2: Change delta applied to the document. diff --git a/lib/widgets/cursor.dart b/lib/widgets/cursor.dart index 307e70a5..383906d0 100644 --- a/lib/widgets/cursor.dart +++ b/lib/widgets/cursor.dart @@ -8,15 +8,6 @@ import 'box.dart'; const Duration _FADE_DURATION = Duration(milliseconds: 250); class CursorStyle { - final Color color; - final Color backgroundColor; - final double width; - final double? height; - final Radius? radius; - final Offset? offset; - final bool opacityAnimates; - final bool paintAboveText; - const CursorStyle({ required this.color, required this.backgroundColor, @@ -28,6 +19,15 @@ class CursorStyle { this.paintAboveText = false, }); + final Color color; + final Color backgroundColor; + final double width; + final double? height; + final Radius? radius; + final Offset? offset; + final bool opacityAnimates; + final bool paintAboveText; + @override bool operator ==(Object other) => identical(this, other) || @@ -55,14 +55,6 @@ class CursorStyle { } class CursorCont extends ChangeNotifier { - final ValueNotifier show; - final ValueNotifier _blink; - final ValueNotifier color; - late AnimationController _blinkOpacityCont; - Timer? _cursorTimer; - bool _targetCursorVisibility = false; - CursorStyle _style; - CursorCont({ required this.show, required CursorStyle style, @@ -75,6 +67,14 @@ class CursorCont extends ChangeNotifier { _blinkOpacityCont.addListener(_onColorTick); } + final ValueNotifier show; + final ValueNotifier _blink; + final ValueNotifier color; + late AnimationController _blinkOpacityCont; + Timer? _cursorTimer; + bool _targetCursorVisibility = false; + CursorStyle _style; + ValueNotifier get cursorBlink => _blink; ValueNotifier get cursorColor => color; @@ -156,15 +156,15 @@ class CursorCont extends ChangeNotifier { } class CursorPainter { + CursorPainter(this.editable, this.style, this.prototype, this.color, + this.devicePixelRatio); + final RenderContentProxyBox? editable; final CursorStyle style; final Rect? prototype; final Color color; final double devicePixelRatio; - CursorPainter(this.editable, this.style, this.prototype, this.color, - this.devicePixelRatio); - void paint(Canvas canvas, Offset offset, TextPosition position) { assert(prototype != null); diff --git a/lib/widgets/default_styles.dart b/lib/widgets/default_styles.dart index 8612d92b..1cebe135 100644 --- a/lib/widgets/default_styles.dart +++ b/lib/widgets/default_styles.dart @@ -3,14 +3,14 @@ import 'package:flutter/widgets.dart'; import 'package:tuple/tuple.dart'; class QuillStyles extends InheritedWidget { - final DefaultStyles data; - const QuillStyles({ required this.data, required Widget child, Key? key, }) : super(key: key, child: child); + final DefaultStyles data; + @override bool updateShouldNotify(QuillStyles oldWidget) { return data != oldWidget.data; @@ -27,6 +27,13 @@ class QuillStyles extends InheritedWidget { } class DefaultTextBlockStyle { + DefaultTextBlockStyle( + this.style, + this.verticalSpacing, + this.lineSpacing, + this.decoration, + ); + final TextStyle style; final Tuple2 verticalSpacing; @@ -34,12 +41,32 @@ class DefaultTextBlockStyle { final Tuple2 lineSpacing; final BoxDecoration? decoration; - - DefaultTextBlockStyle( - this.style, this.verticalSpacing, this.lineSpacing, this.decoration); } class DefaultStyles { + DefaultStyles({ + this.h1, + this.h2, + this.h3, + this.paragraph, + this.bold, + this.italic, + this.underline, + this.strikeThrough, + this.link, + this.color, + this.placeHolder, + this.lists, + this.quote, + this.code, + this.indent, + this.align, + this.leading, + this.sizeSmall, + this.sizeLarge, + this.sizeHuge, + }); + final DefaultTextBlockStyle? h1; final DefaultTextBlockStyle? h2; final DefaultTextBlockStyle? h3; @@ -61,28 +88,6 @@ class DefaultStyles { final DefaultTextBlockStyle? align; final DefaultTextBlockStyle? leading; - DefaultStyles( - {this.h1, - this.h2, - this.h3, - this.paragraph, - this.bold, - this.italic, - this.underline, - this.strikeThrough, - this.link, - this.color, - this.placeHolder, - this.lists, - this.quote, - this.code, - this.indent, - this.align, - this.leading, - this.sizeSmall, - this.sizeLarge, - this.sizeHuge}); - static DefaultStyles getInstance(BuildContext context) { final themeData = Theme.of(context); final defaultTextStyle = DefaultTextStyle.of(context); diff --git a/lib/widgets/delegate.dart b/lib/widgets/delegate.dart index 8adf8ce7..4b4bdea7 100644 --- a/lib/widgets/delegate.dart +++ b/lib/widgets/delegate.dart @@ -18,11 +18,11 @@ abstract class EditorTextSelectionGestureDetectorBuilderDelegate { } class EditorTextSelectionGestureDetectorBuilder { + EditorTextSelectionGestureDetectorBuilder(this.delegate); + final EditorTextSelectionGestureDetectorBuilderDelegate delegate; bool shouldShowSelectionToolbar = true; - EditorTextSelectionGestureDetectorBuilder(this.delegate); - EditorState? getEditor() { return delegate.getEditableTextKey().currentState; } diff --git a/lib/widgets/editor.dart b/lib/widgets/editor.dart index c3d5d2cb..3b33211c 100644 --- a/lib/widgets/editor.dart +++ b/lib/widgets/editor.dart @@ -114,6 +114,43 @@ Widget _defaultEmbedBuilder(BuildContext context, leaf.Embed node) { } class QuillEditor extends StatefulWidget { + const QuillEditor({ + required this.controller, + required this.focusNode, + required this.scrollController, + required this.scrollable, + required this.padding, + required this.autoFocus, + required this.readOnly, + required this.expands, + this.showCursor, + this.placeholder, + this.enableInteractiveSelection = true, + this.minHeight, + this.maxHeight, + this.customStyles, + this.textCapitalization = TextCapitalization.sentences, + this.keyboardAppearance = Brightness.light, + this.scrollPhysics, + this.onLaunchUrl, + this.embedBuilder = _defaultEmbedBuilder, + }); + + factory QuillEditor.basic({ + required QuillController controller, + required bool readOnly, + }) { + return QuillEditor( + controller: controller, + scrollController: ScrollController(), + scrollable: true, + focusNode: FocusNode(), + autoFocus: true, + readOnly: readOnly, + expands: false, + padding: EdgeInsets.zero); + } + final QuillController controller; final FocusNode focusNode; final ScrollController scrollController; @@ -134,40 +171,6 @@ class QuillEditor extends StatefulWidget { final ValueChanged? onLaunchUrl; final EmbedBuilder embedBuilder; - const QuillEditor( - {required this.controller, - required this.focusNode, - required this.scrollController, - required this.scrollable, - required this.padding, - required this.autoFocus, - required this.readOnly, - required this.expands, - this.showCursor, - this.placeholder, - this.enableInteractiveSelection = true, - this.minHeight, - this.maxHeight, - this.customStyles, - this.textCapitalization = TextCapitalization.sentences, - this.keyboardAppearance = Brightness.light, - this.scrollPhysics, - this.onLaunchUrl, - this.embedBuilder = _defaultEmbedBuilder}); - - factory QuillEditor.basic( - {required QuillController controller, required bool readOnly}) { - return QuillEditor( - controller: controller, - scrollController: ScrollController(), - scrollable: true, - focusNode: FocusNode(), - autoFocus: true, - readOnly: readOnly, - expands: false, - padding: EdgeInsets.zero); - } - @override _QuillEditorState createState() => _QuillEditorState(); } @@ -295,10 +298,10 @@ class _QuillEditorState extends State class _QuillEditorSelectionGestureDetectorBuilder extends EditorTextSelectionGestureDetectorBuilder { - final _QuillEditorState _state; - _QuillEditorSelectionGestureDetectorBuilder(this._state) : super(_state); + final _QuillEditorState _state; + @override void onForcePressStart(ForcePressDetails details) { super.onForcePressStart(details); @@ -495,6 +498,24 @@ typedef TextSelectionChangedHandler = void Function( class RenderEditor extends RenderEditableContainerBox implements RenderAbstractEditor { + RenderEditor( + List? children, + TextDirection textDirection, + EdgeInsetsGeometry padding, + this.document, + this.selection, + this._hasFocus, + this.onSelectionChanged, + this._startHandleLayerLink, + this._endHandleLayerLink, + EdgeInsets floatingCursorAddedMargin, + ) : super( + children, + document.root, + textDirection, + padding, + ); + Document document; TextSelection selection; bool _hasFocus = false; @@ -510,24 +531,6 @@ class RenderEditor extends RenderEditableContainerBox ValueListenable get selectionEndInViewport => _selectionEndInViewport; final ValueNotifier _selectionEndInViewport = ValueNotifier(true); - RenderEditor( - List? children, - TextDirection textDirection, - EdgeInsetsGeometry padding, - this.document, - this.selection, - this._hasFocus, - this.onSelectionChanged, - this._startHandleLayerLink, - this._endHandleLayerLink, - EdgeInsets floatingCursorAddedMargin) - : super( - children, - document.root, - textDirection, - padding, - ); - void setDocument(Document doc) { if (document == doc) { return; @@ -866,17 +869,20 @@ class RenderEditableContainerBox extends RenderBox EditableContainerParentData>, RenderBoxContainerDefaultsMixin { + RenderEditableContainerBox( + List? children, + this._container, + this.textDirection, + this._padding, + ) : assert(_padding.isNonNegative) { + addAll(children); + } + container_node.Container _container; TextDirection textDirection; EdgeInsetsGeometry _padding; EdgeInsets? _resolvedPadding; - RenderEditableContainerBox(List? children, this._container, - this.textDirection, this._padding) - : assert(_padding.isNonNegative) { - addAll(children); - } - container_node.Container getContainer() { return _container; } diff --git a/lib/widgets/keyboard_listener.dart b/lib/widgets/keyboard_listener.dart index f952c3dd..17c47aad 100644 --- a/lib/widgets/keyboard_listener.dart +++ b/lib/widgets/keyboard_listener.dart @@ -9,9 +9,12 @@ typedef InputShortcutCallback = void Function(InputShortcut? shortcut); typedef OnDeleteCallback = void Function(bool forward); class KeyboardListener { + KeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete); + final CursorMoveCallback onCursorMove; final InputShortcutCallback onShortcut; final OnDeleteCallback onDelete; + static final Set _moveKeys = { LogicalKeyboardKey.arrowRight, LogicalKeyboardKey.arrowLeft, @@ -59,8 +62,6 @@ class KeyboardListener { LogicalKeyboardKey.keyA: InputShortcut.SELECT_ALL, }; - KeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete); - bool handleRawKeyEvent(RawKeyEvent event) { if (kIsWeb) { // On web platform, we should ignore the key because it's processed already. diff --git a/lib/widgets/proxy.dart b/lib/widgets/proxy.dart index bae59f1b..8a04c4e1 100644 --- a/lib/widgets/proxy.dart +++ b/lib/widgets/proxy.dart @@ -4,12 +4,12 @@ import 'package:flutter/widgets.dart'; import 'box.dart'; class BaselineProxy extends SingleChildRenderObjectWidget { - final TextStyle? textStyle; - final EdgeInsets? padding; - const BaselineProxy({Key? key, Widget? child, this.textStyle, this.padding}) : super(key: key, child: child); + final TextStyle? textStyle; + final EdgeInsets? padding; + @override RenderBaselineProxy createRenderObject(BuildContext context) { return RenderBaselineProxy( @@ -122,6 +122,18 @@ class RenderEmbedProxy extends RenderProxyBox implements RenderContentProxyBox { } class RichTextProxy extends SingleChildRenderObjectWidget { + const RichTextProxy( + RichText child, + this.textStyle, + this.textAlign, + this.textDirection, + this.textScaleFactor, + this.locale, + this.strutStyle, + this.textWidthBasis, + this.textHeightBehavior, + ) : super(child: child); + final TextStyle textStyle; final TextAlign textAlign; final TextDirection textDirection; @@ -145,18 +157,6 @@ class RichTextProxy extends SingleChildRenderObjectWidget { textHeightBehavior); } - const RichTextProxy( - RichText child, - this.textStyle, - this.textAlign, - this.textDirection, - this.textScaleFactor, - this.locale, - this.strutStyle, - this.textWidthBasis, - this.textHeightBehavior) - : super(child: child); - @override void updateRenderObject( BuildContext context, covariant RenderParagraphProxy renderObject) { diff --git a/lib/widgets/raw_editor.dart b/lib/widgets/raw_editor.dart index cf293aba..72422991 100644 --- a/lib/widgets/raw_editor.dart +++ b/lib/widgets/raw_editor.dart @@ -28,6 +28,39 @@ import 'text_line.dart'; import 'text_selection.dart'; class RawEditor extends StatefulWidget { + const RawEditor( + Key key, + this.controller, + this.focusNode, + this.scrollController, + this.scrollable, + this.padding, + this.readOnly, + this.placeholder, + this.onLaunchUrl, + this.toolbarOptions, + this.showSelectionHandles, + bool? showCursor, + this.cursorStyle, + this.textCapitalization, + this.maxHeight, + this.minHeight, + this.customStyles, + this.expands, + this.autoFocus, + this.selectionColor, + this.selectionCtrls, + this.keyboardAppearance, + this.enableInteractiveSelection, + this.scrollPhysics, + this.embedBuilder, + ) : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'), + assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'), + assert(maxHeight == null || minHeight == null || maxHeight >= minHeight, + 'maxHeight cannot be null'), + showCursor = showCursor ?? true, + super(key: key); + final QuillController controller; final FocusNode focusNode; final ScrollController scrollController; @@ -53,39 +86,6 @@ class RawEditor extends StatefulWidget { final ScrollPhysics? scrollPhysics; final EmbedBuilder embedBuilder; - const RawEditor( - Key key, - this.controller, - this.focusNode, - this.scrollController, - this.scrollable, - this.padding, - this.readOnly, - this.placeholder, - this.onLaunchUrl, - this.toolbarOptions, - this.showSelectionHandles, - bool? showCursor, - this.cursorStyle, - this.textCapitalization, - this.maxHeight, - this.minHeight, - this.customStyles, - this.expands, - this.autoFocus, - this.selectionColor, - this.selectionCtrls, - this.keyboardAppearance, - this.enableInteractiveSelection, - this.scrollPhysics, - this.embedBuilder) - : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'), - assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'), - assert(maxHeight == null || minHeight == null || maxHeight >= minHeight, - 'maxHeight cannot be null'), - showCursor = showCursor ?? true, - super(key: key); - @override State createState() { return RawEditorState(); diff --git a/lib/widgets/responsive_widget.dart b/lib/widgets/responsive_widget.dart index dbfec8d5..3829565c 100644 --- a/lib/widgets/responsive_widget.dart +++ b/lib/widgets/responsive_widget.dart @@ -1,10 +1,6 @@ import 'package:flutter/material.dart'; class ResponsiveWidget extends StatelessWidget { - final Widget largeScreen; - final Widget? mediumScreen; - final Widget? smallScreen; - const ResponsiveWidget({ required this.largeScreen, this.mediumScreen, @@ -12,6 +8,10 @@ class ResponsiveWidget extends StatelessWidget { Key? key, }) : super(key: key); + final Widget largeScreen; + final Widget? mediumScreen; + final Widget? smallScreen; + static bool isSmallScreen(BuildContext context) { return MediaQuery.of(context).size.width < 800; } diff --git a/lib/widgets/text_block.dart b/lib/widgets/text_block.dart index 61448d5a..25ea8d9c 100644 --- a/lib/widgets/text_block.dart +++ b/lib/widgets/text_block.dart @@ -47,6 +47,21 @@ const List romanNumbers = [ ]; class EditableTextBlock extends StatelessWidget { + const EditableTextBlock( + this.block, + this.textDirection, + this.verticalSpacing, + this.textSelection, + this.color, + this.styles, + this.enableInteractiveSelection, + this.hasFocus, + this.contentPadding, + this.embedBuilder, + this.cursorCont, + this.indentLevelCounts, + ); + final Block block; final TextDirection textDirection; final Tuple2 verticalSpacing; @@ -60,20 +75,6 @@ class EditableTextBlock extends StatelessWidget { final CursorCont cursorCont; final Map indentLevelCounts; - const EditableTextBlock( - this.block, - this.textDirection, - this.verticalSpacing, - this.textSelection, - this.color, - this.styles, - this.enableInteractiveSelection, - this.hasFocus, - this.contentPadding, - this.embedBuilder, - this.cursorCont, - this.indentLevelCounts); - @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); @@ -509,16 +510,21 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } class _EditableBlock extends MultiChildRenderObjectWidget { + _EditableBlock( + this.block, + this.textDirection, + this.padding, + this.decoration, + this.contentPadding, + List children, + ) : super(children: children); + final Block block; final TextDirection textDirection; final Tuple2 padding; final Decoration decoration; final EdgeInsets? contentPadding; - _EditableBlock(this.block, this.textDirection, this.padding, this.decoration, - this.contentPadding, List children) - : super(children: children); - EdgeInsets get _padding => EdgeInsets.only(top: padding.item1, bottom: padding.item2); @@ -548,15 +554,6 @@ class _EditableBlock extends MultiChildRenderObjectWidget { } class _NumberPoint extends StatelessWidget { - final int index; - final Map indentLevelCounts; - final int count; - final TextStyle style; - final double width; - final Map attrs; - final bool withDot; - final double padding; - const _NumberPoint({ required this.index, required this.indentLevelCounts, @@ -569,6 +566,15 @@ class _NumberPoint extends StatelessWidget { Key? key, }) : super(key: key); + final int index; + final Map indentLevelCounts; + final int count; + final TextStyle style; + final double width; + final Map attrs; + final bool withDot; + final double padding; + @override Widget build(BuildContext context) { var s = index.toString(); @@ -652,15 +658,15 @@ class _NumberPoint extends StatelessWidget { } class _BulletPoint extends StatelessWidget { - final TextStyle style; - final double width; - const _BulletPoint({ required this.style, required this.width, Key? key, }) : super(key: key); + final TextStyle style; + final double width; + @override Widget build(BuildContext context) { return Container( @@ -673,12 +679,13 @@ class _BulletPoint extends StatelessWidget { } class _Checkbox extends StatefulWidget { + const _Checkbox({Key? key, this.style, this.width, this.isChecked}) + : super(key: key); + final TextStyle? style; final double? width; final bool? isChecked; - const _Checkbox({Key? key, this.style, this.width, this.isChecked}) - : super(key: key); @override __CheckboxState createState() => __CheckboxState(); } diff --git a/lib/widgets/text_line.dart b/lib/widgets/text_line.dart index 304742ac..43cc6969 100644 --- a/lib/widgets/text_line.dart +++ b/lib/widgets/text_line.dart @@ -20,11 +20,6 @@ import 'proxy.dart'; import 'text_selection.dart'; class TextLine extends StatelessWidget { - final Line line; - final TextDirection? textDirection; - final EmbedBuilder embedBuilder; - final DefaultStyles styles; - const TextLine({ required this.line, required this.embedBuilder, @@ -33,6 +28,11 @@ class TextLine extends StatelessWidget { Key? key, }) : super(key: key); + final Line line; + final TextDirection? textDirection; + final EmbedBuilder embedBuilder; + final DefaultStyles styles; + @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); @@ -194,6 +194,21 @@ class TextLine extends StatelessWidget { } class EditableTextLine extends RenderObjectWidget { + const EditableTextLine( + this.line, + this.leading, + this.body, + this.indentWidth, + this.verticalSpacing, + this.textDirection, + this.textSelection, + this.color, + this.enableInteractiveSelection, + this.hasFocus, + this.devicePixelRatio, + this.cursorCont, + ); + final Line line; final Widget? leading; final Widget body; @@ -207,20 +222,6 @@ class EditableTextLine extends RenderObjectWidget { final double devicePixelRatio; final CursorCont cursorCont; - const EditableTextLine( - this.line, - this.leading, - this.body, - this.indentWidth, - this.verticalSpacing, - this.textDirection, - this.textSelection, - this.color, - this.enableInteractiveSelection, - this.hasFocus, - this.devicePixelRatio, - this.cursorCont); - @override RenderObjectElement createElement() { return _TextLineElement(this); @@ -266,6 +267,18 @@ class EditableTextLine extends RenderObjectWidget { enum TextLineSlot { LEADING, BODY } class RenderEditableTextLine extends RenderEditableBox { + RenderEditableTextLine( + this.line, + this.textDirection, + this.textSelection, + this.enableInteractiveSelection, + this.hasFocus, + this.devicePixelRatio, + this.padding, + this.color, + this.cursorCont, + ); + RenderBox? _leading; RenderContentProxyBox? _body; Line line; @@ -283,17 +296,6 @@ class RenderEditableTextLine extends RenderEditableBox { Rect? _caretPrototype; final Map children = {}; - RenderEditableTextLine( - this.line, - this.textDirection, - this.textSelection, - this.enableInteractiveSelection, - this.hasFocus, - this.devicePixelRatio, - this.padding, - this.color, - this.cursorCont); - Iterable get _children sync* { if (_leading != null) { yield _leading!; diff --git a/lib/widgets/text_selection.dart b/lib/widgets/text_selection.dart index d6d24467..fe28741b 100644 --- a/lib/widgets/text_selection.dart +++ b/lib/widgets/text_selection.dart @@ -24,6 +24,27 @@ TextSelection localSelection(Node node, TextSelection selection, fromParent) { enum _TextSelectionHandlePosition { START, END } class EditorTextSelectionOverlay { + EditorTextSelectionOverlay( + this.value, + this.handlesVisible, + this.context, + this.debugRequiredFor, + this.toolbarLayerLink, + this.startHandleLayerLink, + this.endHandleLayerLink, + this.renderObject, + this.selectionCtrls, + this.selectionDelegate, + this.dragStartBehavior, + this.onSelectionHandleTapped, + this.clipboardStatus, + ) { + final overlay = Overlay.of(context, rootOverlay: true)!; + + _toolbarController = AnimationController( + duration: const Duration(milliseconds: 150), vsync: overlay); + } + TextEditingValue value; bool handlesVisible = false; final BuildContext context; @@ -41,26 +62,6 @@ class EditorTextSelectionOverlay { List? _handles; OverlayEntry? toolbar; - EditorTextSelectionOverlay( - this.value, - this.handlesVisible, - this.context, - this.debugRequiredFor, - this.toolbarLayerLink, - this.startHandleLayerLink, - this.endHandleLayerLink, - this.renderObject, - this.selectionCtrls, - this.selectionDelegate, - this.dragStartBehavior, - this.onSelectionHandleTapped, - this.clipboardStatus) { - final overlay = Overlay.of(context, rootOverlay: true)!; - - _toolbarController = AnimationController( - duration: const Duration(milliseconds: 150), vsync: overlay); - } - TextSelection get _selection => value.selection; Animation get _toolbarOpacity => _toolbarController.view; diff --git a/lib/widgets/toolbar.dart b/lib/widgets/toolbar.dart index 73e0c9a7..71ddec1d 100644 --- a/lib/widgets/toolbar.dart +++ b/lib/widgets/toolbar.dart @@ -21,15 +21,15 @@ typedef OnImagePickCallback = Future Function(File file); typedef ImagePickImpl = Future Function(ImageSource source); class InsertEmbedButton extends StatelessWidget { - final QuillController controller; - final IconData icon; - const InsertEmbedButton({ required this.controller, required this.icon, Key? key, }) : super(key: key); + final QuillController controller; + final IconData icon; + @override Widget build(BuildContext context) { return QuillIconButton( @@ -52,15 +52,15 @@ class InsertEmbedButton extends StatelessWidget { } class LinkStyleButton extends StatefulWidget { - final QuillController controller; - final IconData? icon; - const LinkStyleButton({ required this.controller, this.icon, Key? key, }) : super(key: key); + final QuillController controller; + final IconData? icon; + @override _LinkStyleButtonState createState() => _LinkStyleButtonState(); } @@ -174,14 +174,6 @@ typedef ToggleStyleButtonBuilder = Widget Function( ); class ToggleStyleButton extends StatefulWidget { - final Attribute attribute; - - final IconData icon; - - final QuillController controller; - - final ToggleStyleButtonBuilder childBuilder; - const ToggleStyleButton({ required this.attribute, required this.icon, @@ -190,6 +182,14 @@ class ToggleStyleButton extends StatefulWidget { Key? key, }) : super(key: key); + final Attribute attribute; + + final IconData icon; + + final QuillController controller; + + final ToggleStyleButtonBuilder childBuilder; + @override _ToggleStyleButtonState createState() => _ToggleStyleButtonState(); } @@ -258,14 +258,6 @@ class _ToggleStyleButtonState extends State { } class ToggleCheckListButton extends StatefulWidget { - final IconData icon; - - final QuillController controller; - - final ToggleStyleButtonBuilder childBuilder; - - final Attribute attribute; - const ToggleCheckListButton({ required this.icon, required this.controller, @@ -274,6 +266,14 @@ class ToggleCheckListButton extends StatefulWidget { Key? key, }) : super(key: key); + final IconData icon; + + final QuillController controller; + + final ToggleStyleButtonBuilder childBuilder; + + final Attribute attribute; + @override _ToggleCheckListButtonState createState() => _ToggleCheckListButtonState(); } @@ -369,11 +369,11 @@ Widget defaultToggleStyleButtonBuilder( } class SelectHeaderStyleButton extends StatefulWidget { - final QuillController controller; - const SelectHeaderStyleButton({required this.controller, Key? key}) : super(key: key); + final QuillController controller; + @override _SelectHeaderStyleButtonState createState() => _SelectHeaderStyleButtonState(); @@ -490,6 +490,15 @@ Widget _selectHeadingStyleButtonBuilder(BuildContext context, Attribute? value, } class ImageButton extends StatefulWidget { + const ImageButton({ + required this.icon, + required this.controller, + required this.imageSource, + this.onImagePickCallback, + this.imagePickImpl, + Key? key, + }) : super(key: key); + final IconData icon; final QuillController controller; @@ -500,15 +509,6 @@ class ImageButton extends StatefulWidget { final ImageSource imageSource; - const ImageButton({ - required this.icon, - required this.controller, - required this.imageSource, - this.onImagePickCallback, - this.imagePickImpl, - Key? key, - }) : super(key: key); - @override _ImageButtonState createState() => _ImageButtonState(); } @@ -602,10 +602,6 @@ class _ImageButtonState extends State { /// When pressed, this button displays overlay toolbar with /// buttons for each color. class ColorButton extends StatefulWidget { - final IconData icon; - final bool background; - final QuillController controller; - const ColorButton({ required this.icon, required this.controller, @@ -613,6 +609,10 @@ class ColorButton extends StatefulWidget { Key? key, }) : super(key: key); + final IconData icon; + final bool background; + final QuillController controller; + @override _ColorButtonState createState() => _ColorButtonState(); } @@ -740,10 +740,6 @@ class _ColorButtonState extends State { } class HistoryButton extends StatefulWidget { - final IconData icon; - final bool undo; - final QuillController controller; - const HistoryButton({ required this.icon, required this.controller, @@ -751,6 +747,10 @@ class HistoryButton extends StatefulWidget { Key? key, }) : super(key: key); + final IconData icon; + final bool undo; + final QuillController controller; + @override _HistoryButtonState createState() => _HistoryButtonState(); } @@ -812,10 +812,6 @@ class _HistoryButtonState extends State { } class IndentButton extends StatefulWidget { - final IconData icon; - final QuillController controller; - final bool isIncrease; - const IndentButton({ required this.icon, required this.controller, @@ -823,6 +819,10 @@ class IndentButton extends StatefulWidget { Key? key, }) : super(key: key); + final IconData icon; + final QuillController controller; + final bool isIncrease; + @override _IndentButtonState createState() => _IndentButtonState(); } @@ -867,16 +867,16 @@ class _IndentButtonState extends State { } class ClearFormatButton extends StatefulWidget { - final IconData icon; - - final QuillController controller; - const ClearFormatButton({ required this.icon, required this.controller, Key? key, }) : super(key: key); + final IconData icon; + + final QuillController controller; + @override _ClearFormatButtonState createState() => _ClearFormatButtonState(); } @@ -903,8 +903,6 @@ class _ClearFormatButtonState extends State { } class QuillToolbar extends StatefulWidget implements PreferredSizeWidget { - final List children; - const QuillToolbar({required this.children, Key? key}) : super(key: key); factory QuillToolbar.basic({ @@ -1117,6 +1115,8 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget { ]); } + final List children; + @override _QuillToolbarState createState() => _QuillToolbarState(); @@ -1148,13 +1148,6 @@ class _QuillToolbarState extends State { } class QuillIconButton extends StatelessWidget { - final VoidCallback? onPressed; - final Widget? icon; - final double size; - final Color? fillColor; - final double hoverElevation; - final double highlightElevation; - const QuillIconButton({ required this.onPressed, this.icon, @@ -1165,6 +1158,13 @@ class QuillIconButton extends StatelessWidget { Key? key, }) : super(key: key); + final VoidCallback? onPressed; + final Widget? icon; + final double size; + final Color? fillColor; + final double hoverElevation; + final double highlightElevation; + @override Widget build(BuildContext context) { return ConstrainedBox( @@ -1184,15 +1184,6 @@ class QuillIconButton extends StatelessWidget { } class QuillDropdownButton extends StatefulWidget { - final double height; - final Color? fillColor; - final double hoverElevation; - final double highlightElevation; - final Widget child; - final T initialValue; - final List> items; - final ValueChanged onSelected; - const QuillDropdownButton({ required this.child, required this.initialValue, @@ -1205,6 +1196,15 @@ class QuillDropdownButton extends StatefulWidget { Key? key, }) : super(key: key); + final double height; + final Color? fillColor; + final double hoverElevation; + final double highlightElevation; + final Widget child; + final T initialValue; + final List> items; + final ValueChanged onSelected; + @override _QuillDropdownButtonState createState() => _QuillDropdownButtonState(); }