From ecfc5adc3e08d3a73b69c95647da0ae3f1f76ac2 Mon Sep 17 00:00:00 2001 From: John Wehrle Date: Sun, 21 Mar 2021 09:19:20 -0700 Subject: [PATCH] Migrated to null safety. Moved package universal_ui to universal_ui.dart since there was no null safe version available at this time. --- app/android/build.gradle | 3 +- app/ios/Flutter/Debug.xcconfig | 1 + app/ios/Flutter/Release.xcconfig | 1 + app/lib/pages/home_page.dart | 16 +- app/lib/widgets/demo_scaffold.dart | 16 +- app/lib/widgets/field.dart | 30 +-- app/pubspec.lock | 50 +--- app/pubspec.yaml | 2 +- lib/models/documents/attribute.dart | 114 ++++----- lib/models/documents/document.dart | 14 +- lib/models/documents/nodes/block.dart | 12 +- lib/models/documents/nodes/container.dart | 18 +- lib/models/documents/nodes/embed.dart | 6 +- lib/models/documents/nodes/leaf.dart | 93 +++---- lib/models/documents/nodes/line.dart | 92 ++++--- lib/models/documents/nodes/node.dart | 17 +- lib/models/documents/style.dart | 12 +- lib/models/quill_delta.dart | 119 +++++---- lib/models/rules/delete.dart | 48 ++-- lib/models/rules/format.dart | 51 ++-- lib/models/rules/insert.dart | 136 +++++------ lib/models/rules/rule.dart | 17 +- lib/universal_ui/fake_ui.dart | 4 + lib/universal_ui/real_ui.dart | 9 + lib/universal_ui/universal_ui.dart | 20 ++ lib/utils/diff_delta.dart | 7 +- lib/widgets/box.dart | 6 +- lib/widgets/controller.dart | 17 +- lib/widgets/cursor.dart | 61 ++--- lib/widgets/default_styles.dart | 60 +++-- lib/widgets/delegate.dart | 35 ++- lib/widgets/editor.dart | 275 ++++++++++----------- lib/widgets/image.dart | 2 +- lib/widgets/keyboard_listener.dart | 7 +- lib/widgets/proxy.dart | 71 +++--- lib/widgets/raw_editor.dart | 279 ++++++++++----------- lib/widgets/responsive_widget.dart | 8 +- lib/widgets/text_block.dart | 185 +++++++------- lib/widgets/text_line.dart | 265 ++++++++++---------- lib/widgets/text_selection.dart | 227 +++++++++-------- lib/widgets/toolbar.dart | 281 ++++++++++------------ pubspec.lock | 43 ++-- pubspec.yaml | 12 +- 43 files changed, 1300 insertions(+), 1442 deletions(-) create mode 100755 lib/universal_ui/fake_ui.dart create mode 100755 lib/universal_ui/real_ui.dart create mode 100755 lib/universal_ui/universal_ui.dart diff --git a/app/android/build.gradle b/app/android/build.gradle index 11e3d090..77a5b951 100644 --- a/app/android/build.gradle +++ b/app/android/build.gradle @@ -5,7 +5,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + //classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:4.1.0' } } diff --git a/app/ios/Flutter/Debug.xcconfig b/app/ios/Flutter/Debug.xcconfig index 592ceee8..ec97fc6f 100644 --- a/app/ios/Flutter/Debug.xcconfig +++ b/app/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/app/ios/Flutter/Release.xcconfig b/app/ios/Flutter/Release.xcconfig index 592ceee8..c4855bfe 100644 --- a/app/ios/Flutter/Release.xcconfig +++ b/app/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/app/lib/pages/home_page.dart b/app/lib/pages/home_page.dart index 60a42a64..59f750ed 100644 --- a/app/lib/pages/home_page.dart +++ b/app/lib/pages/home_page.dart @@ -23,7 +23,7 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State { - QuillController _controller; + QuillController? _controller; final FocusNode _focusNode = FocusNode(); @override @@ -75,15 +75,15 @@ class _HomePageState extends State { focusNode: FocusNode(), onKey: (RawKeyEvent event) { if (event.data.isControlPressed && event.character == 'b') { - if (_controller + if (_controller! .getSelectionStyle() .attributes .keys .contains("bold")) { - _controller + _controller! .formatSelection(Attribute.clone(Attribute.bold, null)); } else { - _controller.formatSelection(Attribute.bold); + _controller!.formatSelection(Attribute.bold); print("not bold"); } } @@ -104,7 +104,7 @@ class _HomePageState extends State { color: Colors.white, padding: const EdgeInsets.only(left: 16.0, right: 16.0), child: QuillEditor( - controller: _controller, + controller: _controller!, scrollController: ScrollController(), scrollable: true, focusNode: _focusNode, @@ -135,12 +135,12 @@ class _HomePageState extends State { child: Container( padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: QuillToolbar.basic( - controller: _controller, + controller: _controller!, onImagePickCallback: _onImagePickCallback), )) : Container( child: QuillToolbar.basic( - controller: _controller, + controller: _controller!, onImagePickCallback: _onImagePickCallback), ), ], @@ -150,7 +150,7 @@ class _HomePageState extends State { // Renders the image picked by imagePicker from local file storage // You can also upload the picked image to any server (eg : AWS s3 or Firebase) and then return the uploaded image URL - Future _onImagePickCallback(File file) async { + Future _onImagePickCallback(File? file) async { if (file == null) return null; // Copies the picked file from temporary cache to applications directory Directory appDocDir = await getApplicationDocumentsDirectory(); diff --git a/app/lib/widgets/demo_scaffold.dart b/app/lib/widgets/demo_scaffold.dart index 3caa00d5..a536078c 100644 --- a/app/lib/widgets/demo_scaffold.dart +++ b/app/lib/widgets/demo_scaffold.dart @@ -14,14 +14,14 @@ 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 List? actions; + final Widget? floatingActionButton; final bool showToolbar; const DemoScaffold({ - Key key, - @required this.documentFilename, - @required this.builder, + Key? key, + required this.documentFilename, + required this.builder, this.actions, this.showToolbar = true, this.floatingActionButton, @@ -33,7 +33,7 @@ class DemoScaffold extends StatefulWidget { class _DemoScaffoldState extends State { final _scaffoldKey = GlobalKey(); - QuillController _controller; + QuillController? _controller; bool _loading = false; @@ -92,13 +92,13 @@ class _DemoScaffoldState extends State { ), title: _loading || widget.showToolbar == false ? null - : QuillToolbar.basic(controller: _controller), + : QuillToolbar.basic(controller: _controller!), actions: actions, ), floatingActionButton: widget.floatingActionButton, body: _loading ? Center(child: Text('Loading...')) - : widget.builder(context, _controller), + : widget.builder(context, _controller!), ); } } diff --git a/app/lib/widgets/field.dart b/app/lib/widgets/field.dart index dd8b4bf4..c9187967 100644 --- a/app/lib/widgets/field.dart +++ b/app/lib/widgets/field.dart @@ -14,22 +14,22 @@ class QuillField extends StatefulWidget { final bool showCursor; final bool readOnly; final bool enableInteractiveSelection; - final double minHeight; - final double maxHeight; + final double? minHeight; + final double? maxHeight; final bool expands; final TextCapitalization textCapitalization; final Brightness keyboardAppearance; - final ScrollPhysics scrollPhysics; - final ValueChanged onLaunchUrl; - final InputDecoration decoration; - final Widget toolbar; - final EmbedBuilder embedBuilder; + final ScrollPhysics? scrollPhysics; + final ValueChanged? onLaunchUrl; + final InputDecoration? decoration; + final Widget? toolbar; + final EmbedBuilder? embedBuilder; QuillField({ - Key key, - @required this.controller, - this.focusNode, - this.scrollController, + Key? key, + required this.controller, + required this.focusNode, + required this.scrollController, this.scrollable = true, this.padding = EdgeInsets.zero, this.autofocus = false, @@ -53,7 +53,7 @@ class QuillField extends StatefulWidget { } class _QuillFieldState extends State { - bool _focused; + bool? _focused; void _editorFocusChanged() { setState(() { @@ -105,8 +105,8 @@ class _QuillFieldState extends State { children: [ child, Visibility( - child: widget.toolbar, - visible: _focused, + child: widget.toolbar!, + visible: _focused!, maintainSize: true, maintainAnimation: true, maintainState: true, @@ -118,7 +118,7 @@ class _QuillFieldState extends State { return AnimatedBuilder( animation: Listenable.merge([widget.focusNode, widget.controller]), - builder: (BuildContext context, Widget child) { + builder: (BuildContext context, Widget? child) { return InputDecorator( decoration: _getEffectiveDecoration(), isFocused: widget.focusNode.hasFocus, diff --git a/app/pubspec.lock b/app/pubspec.lock index a37fd0d0..a339caf1 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -43,27 +43,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "3.0.0" csslib: dependency: transitive description: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.16.2" + version: "0.17.0" cupertino_icons: dependency: "direct main" description: @@ -105,7 +98,7 @@ packages: name: filesystem_picker url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0-nullsafety.0" flutter: dependency: "direct main" description: flutter @@ -117,7 +110,7 @@ packages: name: flutter_colorpicker url: "https://pub.dartlang.org" source: hosted - version: "0.3.5" + version: "0.4.0-nullsafety.0" flutter_keyboard_visibility: dependency: transitive description: @@ -169,7 +162,7 @@ packages: name: html url: "https://pub.dartlang.org" source: hosted - version: "0.14.0+4" + version: "0.15.0" http: dependency: transitive description: @@ -302,14 +295,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" - quiver_hashcode: - dependency: transitive - description: - name: quiver_hashcode - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -349,7 +335,7 @@ packages: name: string_validator url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.3.0" term_glyph: dependency: transitive description: @@ -370,7 +356,7 @@ packages: name: tuple url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "2.0.0" typed_data: dependency: transitive description: @@ -384,21 +370,14 @@ packages: name: universal_html url: "https://pub.dartlang.org" source: hosted - version: "1.2.4" + version: "2.0.4" universal_io: dependency: transitive description: name: universal_io url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" - universal_ui: - dependency: transitive - description: - name: universal_ui - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.8" + version: "2.0.1" url_launcher: dependency: transitive description: @@ -462,13 +441,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" - zone_local: - dependency: transitive - description: - name: zone_local - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.2" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.22.0" + flutter: ">=1.24.0-10.2.pre" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 8858a8dc..0cb4c2bb 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: diff --git a/lib/models/documents/attribute.dart b/lib/models/documents/attribute.dart index 2821661a..3cf155f9 100644 --- a/lib/models/documents/attribute.dart +++ b/lib/models/documents/attribute.dart @@ -8,33 +8,33 @@ enum AttributeScope { } class Attribute { - final String key; - final AttributeScope scope; - final T 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, - Attribute.underline.key: Attribute.underline, - Attribute.strikeThrough.key: Attribute.strikeThrough, - Attribute.font.key: Attribute.font, - Attribute.size.key: Attribute.size, - Attribute.link.key: Attribute.link, - Attribute.color.key: Attribute.color, - Attribute.background.key: Attribute.background, - Attribute.placeholder.key: Attribute.placeholder, - Attribute.header.key: Attribute.header, - Attribute.indent.key: Attribute.indent, - Attribute.align.key: Attribute.align, - Attribute.list.key: Attribute.list, - Attribute.codeBlock.key: Attribute.codeBlock, - Attribute.blockQuote.key: Attribute.blockQuote, - Attribute.width.key: Attribute.width, - Attribute.height.key: Attribute.height, - Attribute.style.key: Attribute.style, - Attribute.token.key: Attribute.token, + Attribute.bold.key!: Attribute.bold, + Attribute.italic.key!: Attribute.italic, + Attribute.underline.key!: Attribute.underline, + Attribute.strikeThrough.key!: Attribute.strikeThrough, + Attribute.font.key!: Attribute.font, + Attribute.size.key!: Attribute.size, + Attribute.link.key!: Attribute.link, + Attribute.color.key!: Attribute.color, + Attribute.background.key!: Attribute.background, + Attribute.placeholder.key!: Attribute.placeholder, + Attribute.header.key!: Attribute.header, + Attribute.indent.key!: Attribute.indent, + Attribute.align.key!: Attribute.align, + Attribute.list.key!: Attribute.list, + Attribute.codeBlock.key!: Attribute.codeBlock, + Attribute.blockQuote.key!: Attribute.blockQuote, + Attribute.width.key!: Attribute.width, + Attribute.height.key!: Attribute.height, + Attribute.style.key!: Attribute.style, + Attribute.token.key!: Attribute.token, }; static final BoldAttribute bold = BoldAttribute(); @@ -78,31 +78,31 @@ class Attribute { static final TokenAttribute token = TokenAttribute(null); static final Set inlineKeys = { - Attribute.bold.key, - Attribute.italic.key, - Attribute.underline.key, - Attribute.strikeThrough.key, - Attribute.link.key, - Attribute.color.key, - Attribute.background.key, - Attribute.placeholder.key, + Attribute.bold.key!, + Attribute.italic.key!, + Attribute.underline.key!, + Attribute.strikeThrough.key!, + Attribute.link.key!, + Attribute.color.key!, + Attribute.background.key!, + Attribute.placeholder.key!, }; static final Set blockKeys = { - Attribute.header.key, - Attribute.indent.key, - Attribute.align.key, - Attribute.list.key, - Attribute.codeBlock.key, - Attribute.blockQuote.key, + Attribute.header.key!, + Attribute.indent.key!, + Attribute.align.key!, + Attribute.list.key!, + Attribute.codeBlock.key!, + Attribute.blockQuote.key!, }; static final Set blockKeysExceptHeader = { - Attribute.list.key, - Attribute.indent.key, - Attribute.align.key, - Attribute.codeBlock.key, - Attribute.blockQuote.key, + Attribute.list.key!, + Attribute.indent.key!, + Attribute.align.key!, + Attribute.codeBlock.key!, + Attribute.blockQuote.key!, }; static Attribute get h1 => HeaderAttribute(level: 1); @@ -158,13 +158,13 @@ class Attribute { bool get isBlockExceptHeader => blockKeysExceptHeader.contains(key); - Map toJson() => {key: value}; + Map toJson() => {key!: value}; static Attribute fromKeyValue(String key, dynamic value) { if (!_registry.containsKey(key)) { throw ArgumentError.value(key, 'key "$key" not found.'); } - Attribute origin = _registry[key]; + Attribute origin = _registry[key]!; Attribute attribute = clone(origin, value); return attribute; } @@ -209,23 +209,23 @@ class StrikeThroughAttribute extends Attribute { } class FontAttribute extends Attribute { - FontAttribute(String val) : super('font', AttributeScope.INLINE, val); + FontAttribute(String? val) : super('font', AttributeScope.INLINE, val); } class SizeAttribute extends Attribute { - SizeAttribute(String val) : super('size', AttributeScope.INLINE, val); + SizeAttribute(String? val) : super('size', AttributeScope.INLINE, val); } class LinkAttribute extends Attribute { - LinkAttribute(String val) : super('link', AttributeScope.INLINE, val); + LinkAttribute(String? val) : super('link', AttributeScope.INLINE, val); } class ColorAttribute extends Attribute { - ColorAttribute(String val) : super('color', AttributeScope.INLINE, val); + ColorAttribute(String? val) : super('color', AttributeScope.INLINE, val); } class BackgroundAttribute extends Attribute { - BackgroundAttribute(String val) + BackgroundAttribute(String? val) : super('background', AttributeScope.INLINE, val); } @@ -235,19 +235,19 @@ class PlaceholderAttribute extends Attribute { } class HeaderAttribute extends Attribute { - HeaderAttribute({int level}) : super('header', AttributeScope.BLOCK, level); + HeaderAttribute({int? level}) : super('header', AttributeScope.BLOCK, level); } class IndentAttribute extends Attribute { - IndentAttribute({int level}) : super('indent', AttributeScope.BLOCK, level); + IndentAttribute({int? level}) : super('indent', AttributeScope.BLOCK, level); } class AlignAttribute extends Attribute { - AlignAttribute(String val) : super('align', AttributeScope.BLOCK, val); + AlignAttribute(String? val) : super('align', AttributeScope.BLOCK, val); } class ListAttribute extends Attribute { - ListAttribute(String val) : super('list', AttributeScope.BLOCK, val); + ListAttribute(String? val) : super('list', AttributeScope.BLOCK, val); } class CodeBlockAttribute extends Attribute { @@ -259,17 +259,17 @@ class BlockQuoteAttribute extends Attribute { } class WidthAttribute extends Attribute { - WidthAttribute(String val) : super('width', AttributeScope.IGNORE, val); + WidthAttribute(String? val) : super('width', AttributeScope.IGNORE, val); } class HeightAttribute extends Attribute { - HeightAttribute(String val) : super('height', AttributeScope.IGNORE, val); + HeightAttribute(String? val) : super('height', AttributeScope.IGNORE, val); } class StyleAttribute extends Attribute { - StyleAttribute(String val) : super('style', AttributeScope.IGNORE, val); + StyleAttribute(String? val) : super('style', AttributeScope.IGNORE, val); } class TokenAttribute extends Attribute { - TokenAttribute(String val) : super('token', AttributeScope.IGNORE, val); + TokenAttribute(String? val) : super('token', AttributeScope.IGNORE, val); } diff --git a/lib/models/documents/document.dart b/lib/models/documents/document.dart index 73391d7b..2a965e2e 100644 --- a/lib/models/documents/document.dart +++ b/lib/models/documents/document.dart @@ -47,7 +47,7 @@ class Document { assert(index >= 0); assert(data is String || data is Embeddable); if (data is Embeddable) { - data = (data as Embeddable).toJson(); + data = data.toJson(); } else if ((data as String).isEmpty) { return Delta(); } @@ -89,7 +89,7 @@ class Document { } Delta format(int index, int len, Attribute attribute) { - assert(index >= 0 && len >= 0 && attribute != null); + assert(index >= 0 && len >= 0); Delta delta = Delta(); @@ -105,7 +105,7 @@ class Document { Style collectStyle(int index, int len) { ChildQuery res = queryChild(index); - return (res.node as Line).collectStyle(res.offset, len); + return (res.node as Line).collectStyle(res.offset!, len); } ChildQuery queryChild(int offset) { @@ -113,8 +113,8 @@ class Document { if (res.node is Line) { return res; } - Block block = res.node; - return block.queryChild(res.offset, true); + Block block = (res.node as Block); + return block.queryChild(res.offset!, true); } compose(Delta delta, ChangeSource changeSource) { @@ -126,7 +126,7 @@ class Document { delta = _transform(delta); Delta originalDelta = toDelta(); for (Operation op in delta.toList()) { - Style style = + Style? style = op.attributes != null ? Style.fromJson(op.attributes) : null; if (op.isInsert) { @@ -205,7 +205,7 @@ class Document { if (data is Embeddable) { return data; } - return Embeddable.fromJson(data); + return Embeddable.fromJson((data as Map)); } close() { diff --git a/lib/models/documents/nodes/block.dart b/lib/models/documents/nodes/block.dart index d48dc38d..61c7cc66 100644 --- a/lib/models/documents/nodes/block.dart +++ b/lib/models/documents/nodes/block.dart @@ -18,7 +18,7 @@ class Block extends Container { @override adjust() { if (isEmpty) { - Node sibling = previous; + Node? sibling = previous; unlink(); if (sibling != null) { sibling.adjust(); @@ -27,16 +27,16 @@ class Block extends Container { } Block block = this; - Node prev = block.previous; + Node? prev = block.previous; // merging it with previous block if style is the same if (!block.isFirst && block.previous is Block && - prev.style == block.style) { - block.moveChildToNewParent(prev); + prev!.style == block.style) { + block.moveChildToNewParent((prev as Container)); block.unlink(); - block = prev; + block = (prev as Block); } - Node next = block.next; + Node next = block.next!; // merging it with next block if style is the same if (!block.isLast && block.next is Block && next.style == block.style) { (next as Block).moveChildToNewParent(block); diff --git a/lib/models/documents/nodes/container.dart b/lib/models/documents/nodes/container.dart index b4a4aa58..a95ed7e0 100644 --- a/lib/models/documents/nodes/container.dart +++ b/lib/models/documents/nodes/container.dart @@ -48,9 +48,9 @@ abstract class Container extends Node { return; } - T last = newParent.isEmpty ? null : newParent.last; + T? last = (newParent.isEmpty ? null : newParent.last as T); while (isNotEmpty) { - T child = first; + T child = (first as T); child.unlink(); newParent.add(child); } @@ -80,12 +80,12 @@ abstract class Container extends Node { int get length => _children.fold(0, (cur, node) => cur + node.length); @override - insert(int index, Object data, Style style) { + insert(int index, Object data, Style? style) { assert(index == 0 || (index > 0 && index < length)); if (isNotEmpty) { ChildQuery child = queryChild(index, false); - child.node.insert(child.offset, data, style); + child.node!.insert(child.offset!, data, style); return; } @@ -97,17 +97,17 @@ abstract class Container extends Node { } @override - retain(int index, int length, Style attributes) { + retain(int index, int length, Style? attributes) { assert(isNotEmpty); ChildQuery child = queryChild(index, false); - child.node.retain(child.offset, length, attributes); + child.node!.retain(child.offset!, length, attributes); } @override delete(int index, int length) { assert(isNotEmpty); ChildQuery child = queryChild(index, false); - child.node.delete(child.offset, length); + child.node!.delete(child.offset!, length); } @override @@ -116,9 +116,9 @@ abstract class Container extends Node { /// Query of a child in a Container class ChildQuery { - final Node node; // null if not found + final Node? node; // null if not found - final int offset; + 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 a8dff833..e777474e 100644 --- a/lib/models/documents/nodes/embed.dart +++ b/lib/models/documents/nodes/embed.dart @@ -1,13 +1,13 @@ class Embeddable { - final String type; - final dynamic data; + final String? type; + final dynamic? data; Embeddable(this.type, this.data) : assert(type != null), assert(data != null); Map toJson() { - Map m = {type: data}; + Map m = {type!: data}; return m; } diff --git a/lib/models/documents/nodes/leaf.dart b/lib/models/documents/nodes/leaf.dart index 13c7b6f0..415c209e 100644 --- a/lib/models/documents/nodes/leaf.dart +++ b/lib/models/documents/nodes/leaf.dart @@ -13,11 +13,9 @@ abstract class Leaf extends Node { Object get value => _value; - Leaf.val(Object val) - : assert(val != null), - _value = val; + Leaf.val(Object val) : _value = val; - factory Leaf([Object data]) { + factory Leaf([Object? data]) { assert(data != null); if (data is Embeddable) { @@ -30,14 +28,13 @@ abstract class Leaf extends Node { @override void applyStyle(Style value) { - assert( - value != null && (value.isInline || value.isIgnored || value.isEmpty), + assert((value.isInline || value.isIgnored || value.isEmpty), 'Unable to apply Style to leaf: $value'); super.applyStyle(value); } @override - Line get parent => super.parent as Line; + Line? get parent => super.parent == null ? null : super.parent as Line; @override int get length { @@ -55,11 +52,11 @@ abstract class Leaf extends Node { } @override - insert(int index, Object data, Style style) { - assert(data != null && index >= 0 && index <= length); + insert(int index, Object data, Style? style) { + assert(index >= 0 && index <= length); Leaf node = Leaf(data); if (index < length) { - splitAt(index).insertBefore(node); + splitAt(index)!.insertBefore(node); } else { insertAfter(node); } @@ -67,20 +64,17 @@ abstract class Leaf extends Node { } @override - retain(int index, int len, Style style) { - if (style == null) { - return; - } - + retain(int index, int len, Style? style) { int local = math.min(this.length - index, len); int remain = len - local; - Leaf node = _isolate(index, local); - - if (remain > 0) { - assert(node.next != null); - node.next.retain(0, remain, style); + Leaf? node = _isolate(index, local); + if (node != null) { + if (remain > 0) { + assert(node.next != null); + node.next!.retain(0, remain, style); + } + node.format(style); } - node.format(style); } @override @@ -88,19 +82,22 @@ abstract class Leaf extends Node { assert(index < this.length); int local = math.min(this.length - index, len); - Leaf target = _isolate(index, local); - Leaf prev = target.previous; - Leaf next = target.next; - target.unlink(); - - int remain = len - local; - if (remain > 0) { - assert(next != null); - next.delete(0, remain); - } - - if (prev != null) { - prev.adjust(); + Leaf? target = _isolate(index, local); + if (target != null) { + Leaf? prev = (target.previous as Leaf?); + Leaf? next = (target.next as Leaf?); + + target.unlink(); + + if (next != null) { + int remain = len - local; + if (remain > 0) { + next.delete(0, remain); + } + } + if (prev != null) { + prev.adjust(); + } } } @@ -112,29 +109,35 @@ abstract class Leaf extends Node { Text node = this as Text; // merging it with previous node if style is the same - Node prev = node.previous; - if (!node.isFirst && prev is Text && prev.style == node.style) { + Node? prev = node.previous; + if (prev != null && + !node.isFirst && + prev is Text && + prev.style == node.style) { prev._value = prev.value + node.value; node.unlink(); node = prev; } // merging it with next node if style is the same - Node next = node.next; - if (!node.isLast && next is Text && next.style == node.style) { + Node? next = node.next; + if (next != null && + !node.isLast && + next is Text && + next.style == node.style) { node._value = node.value + next.value; next.unlink(); } } - Leaf cutAt(int index) { + Leaf? cutAt(int index) { assert(index >= 0 && index <= length); - Leaf cut = splitAt(index); + Leaf? cut = splitAt(index); cut?.unlink(); return cut; } - Leaf splitAt(int index) { + Leaf? splitAt(int index) { assert(index >= 0 && index <= length); if (index == 0) { return this; @@ -152,7 +155,7 @@ abstract class Leaf extends Node { return split; } - format(Style style) { + format(Style? style) { if (style != null && style.isNotEmpty) { applyStyle(style); } @@ -160,11 +163,11 @@ abstract class Leaf extends Node { adjust(); } - Leaf _isolate(int index, int length) { + Leaf? _isolate(int index, int length) { assert( index >= 0 && index < this.length && (index + length <= this.length)); - Leaf target = splitAt(index); - target.splitAt(length); + Leaf? target = splitAt(index); + target?.splitAt(length); return target; } } diff --git a/lib/models/documents/nodes/line.dart b/lib/models/documents/nodes/line.dart index 90b19f03..c4f316aa 100644 --- a/lib/models/documents/nodes/line.dart +++ b/lib/models/documents/nodes/line.dart @@ -25,28 +25,30 @@ class Line extends Container { return children.single is Embed; } - Line get nextLine { + Line? get nextLine { if (!isLast) { - return next is Block ? (next as Block).first : next; + return ((next is Block ? (next as Block).first : next) as Line?); } if (parent is! Block) { return null; } - if (parent.isLast) { + if (parent!.isLast) { return null; } - return parent.next is Block ? (parent.next as Block).first : parent.next; + return ((parent!.next is Block + ? (parent!.next as Block).first + : parent!.next) as Line?); } @override Delta toDelta() { final delta = children .map((child) => child.toDelta()) - .fold(Delta(), (a, b) => a.concat(b)); + .fold(Delta(), (a, b) => (a as Delta).concat(b)); var attributes = style; if (parent is Block) { - Block block = parent; + Block block = (parent as Block); attributes = attributes.mergeAll(block.style); } delta.insert('\n', attributes.toJson()); @@ -64,7 +66,7 @@ class Line extends Container { } @override - insert(int index, Object data, Style style) { + insert(int index, Object data, Style? style) { if (data is Embeddable) { _insert(index, data, style); return; @@ -91,7 +93,9 @@ class Line extends Container { _unwrap(); } - _format(style); + if (style != null) { + _format(style); + } // Continue with the remaining String remain = text.substring(lineBreak + 1); @@ -99,27 +103,25 @@ class Line extends Container { } @override - retain(int index, int len, Style style) { - if (style == null) { - return; - } + retain(int index, int len, Style? style) { int thisLen = this.length; int local = math.min(thisLen - index, len); if (index + local == thisLen && local == 1) { - assert(style.values.every((attr) => attr.scope == AttributeScope.BLOCK)); - _format(style); + assert(style != null && + style.values.every((attr) => attr.scope == AttributeScope.BLOCK)); + _format(style!); } else { - assert(style.values.every((attr) => attr.scope == AttributeScope.INLINE)); + assert(style != null && + style.values.every((attr) => attr.scope == AttributeScope.INLINE)); assert(index + local != thisLen); super.retain(index, local, style); } int remain = len - local; if (remain > 0) { - assert(nextLine != null); - nextLine.retain(0, remain, style); + nextLine!.retain(0, remain, style); } } @@ -138,37 +140,31 @@ class Line extends Container { int remain = len - local; if (remain > 0) { - assert(nextLine != null); - nextLine.delete(0, remain); + nextLine!.delete(0, remain); } if (deleted && isNotEmpty) { - assert(nextLine != null); - nextLine.moveChildToNewParent(this); - moveChildToNewParent(nextLine); + nextLine!.moveChildToNewParent(this); + moveChildToNewParent(nextLine!); } if (deleted) { - Node p = parent; + Node p = (parent as Node); unlink(); p.adjust(); } } void _format(Style newStyle) { - if (newStyle == null || newStyle.isEmpty) { + if (newStyle.isEmpty) { return; } - applyStyle(newStyle); - Attribute blockStyle = newStyle.getBlockExceptHeader(); - if (blockStyle == null) { - return; - } + Attribute? blockStyle = newStyle.getBlockExceptHeader(); if (parent is Block) { - Attribute parentStyle = (parent as Block).style.getBlockExceptHeader(); - if (blockStyle.value == null) { + Attribute? parentStyle = (parent as Block).style.getBlockExceptHeader(); + if (blockStyle!.value == null) { _unwrap(); } else if (blockStyle != parentStyle) { _unwrap(); @@ -177,7 +173,7 @@ class Line extends Container { _wrap(block); block.adjust(); } - } else if (blockStyle.value != null) { + } else if (blockStyle!.value != null) { Block block = Block(); block.applyAttribute(blockStyle); _wrap(block); @@ -196,7 +192,7 @@ class Line extends Container { if (parent is! Block) { throw ArgumentError('Invalid parent'); } - Block block = parent; + Block block = (parent as Block); assert(block.children.contains(this)); @@ -207,10 +203,10 @@ class Line extends Container { unlink(); block.insertAfter(this); } else { - Block before = block.clone(); + Block before = (block.clone() as Block); block.insertBefore(before); - Line child = block.first; + Line child = (block.first as Line); while (child != this) { child.unlink(); before.add(child); @@ -232,19 +228,19 @@ class Line extends Container { } ChildQuery query = queryChild(index, false); - while (!query.node.isLast) { - Leaf next = last; + while (!query.node!.isLast) { + Leaf next = (last as Leaf); next.unlink(); line.addFirst(next); } - Leaf child = query.node; - Leaf cut = child.splitAt(query.offset); + Leaf? child = (query.node as Leaf?); + Leaf? cut = child!.splitAt(query.offset!); cut?.unlink(); - line.addFirst(cut); + line.addFirst(cut!); return line; } - _insert(int index, Object data, Style style) { + _insert(int index, Object data, Style? style) { assert(index == 0 || (index > 0 && index < length)); if (data is String) { @@ -256,7 +252,7 @@ class Line extends Container { if (isNotEmpty) { ChildQuery result = queryChild(index, true); - result.node.insert(result.offset, data, style); + result.node!.insert(result.offset!, data, style); return; } @@ -280,7 +276,7 @@ class Line extends Container { excluded.addAll(style.values); } else { for (Attribute attr in res.values) { - if (!style.containsKey(attr.key)) { + if (!style.containsKey(attr.key!)) { excluded.add(attr); } } @@ -291,11 +287,11 @@ class Line extends Container { } ChildQuery data = queryChild(offset, true); - Leaf node = data.node; + Leaf? node = (data.node as Leaf?); if (node != null) { res = res.mergeAll(node.style); - int pos = node.length - data.offset; - while (!node.isLast && pos < local) { + int pos = node.length - data.offset!; + while (!node!.isLast && pos < local) { node = node.next as Leaf; _handle(node.style); pos += node.length; @@ -304,13 +300,13 @@ class Line extends Container { res = res.mergeAll(style); if (parent is Block) { - Block block = parent; + Block block = (parent as Block); res = res.mergeAll(block.style); } int remain = len - local; if (remain > 0) { - _handle(nextLine.collectStyle(0, remain)); + _handle(nextLine!.collectStyle(0, remain)); } return res; diff --git a/lib/models/documents/nodes/node.dart b/lib/models/documents/nodes/node.dart index 9c52f9c7..751d5687 100644 --- a/lib/models/documents/nodes/node.dart +++ b/lib/models/documents/nodes/node.dart @@ -9,7 +9,7 @@ import 'line.dart'; /* node in a document tree */ abstract class Node extends LinkedListEntry { - Container parent; + Container? parent; Style _style = Style(); Style get style => _style; @@ -19,9 +19,6 @@ abstract class Node extends LinkedListEntry { } void applyStyle(Style value) { - if (value == null) { - throw ArgumentError('null value'); - } _style = _style.mergeAll(value); } @@ -29,9 +26,9 @@ abstract class Node extends LinkedListEntry { _style = Style(); } - bool get isFirst => list.first == this; + bool get isFirst => list!.first == this; - bool get isLast => list.last == this; + bool get isLast => list!.last == this; int get length; @@ -50,14 +47,14 @@ abstract class Node extends LinkedListEntry { Node cur = this; do { - cur = cur.previous; + cur = cur.previous!; offset += cur.length; } while (!cur.isFirst); return offset; } int getDocumentOffset() { - final parentOffset = (parent is! Root) ? parent.getDocumentOffset() : 0; + final parentOffset = (parent is! Root) ? parent!.getDocumentOffset() : 0; return parentOffset + getOffset(); } @@ -99,9 +96,9 @@ abstract class Node extends LinkedListEntry { Delta toDelta(); - insert(int index, Object data, Style style); + insert(int index, Object data, Style? style); - retain(int index, int len, Style style); + retain(int index, int len, Style? style); delete(int index, int len); diff --git a/lib/models/documents/style.dart b/lib/models/documents/style.dart index aa3588d6..e9123f30 100644 --- a/lib/models/documents/style.dart +++ b/lib/models/documents/style.dart @@ -10,7 +10,7 @@ class Style { Style() : _attributes = {}; - static Style fromJson(Map attributes) { + static Style fromJson(Map? attributes) { if (attributes == null) { return Style(); } @@ -22,10 +22,10 @@ class Style { return Style.attr(result); } - Map toJson() => _attributes.isEmpty + Map? toJson() => _attributes.isEmpty ? null : _attributes.map((String _, Attribute attribute) => - MapEntry(attribute.key, attribute.value)); + MapEntry(attribute.key!, attribute.value)); Iterable get keys => _attributes.keys; @@ -46,7 +46,7 @@ class Style { bool containsKey(String key) => _attributes.containsKey(key); - Attribute getBlockExceptHeader() { + Attribute? getBlockExceptHeader() { for (Attribute val in values) { if (val.isBlockExceptHeader) { return val; @@ -60,7 +60,7 @@ class Style { if (attribute.value == null) { merged.remove(attribute.key); } else { - merged[attribute.key] = attribute; + merged[attribute.key!] = attribute; } return Style.attr(merged); } @@ -81,7 +81,7 @@ class Style { Style put(Attribute attribute) { Map m = Map.from(attributes); - m[attribute.key] = attribute; + m[attribute.key!] = attribute; return Style.attr(m); } diff --git a/lib/models/quill_delta.dart b/lib/models/quill_delta.dart index cbfee575..46d2c573 100644 --- a/lib/models/quill_delta.dart +++ b/lib/models/quill_delta.dart @@ -46,13 +46,12 @@ class Operation { final Object data; /// Rich-text attributes set by this operation, can be `null`. - Map get attributes => - _attributes == null ? null : Map.from(_attributes); - final Map _attributes; + Map? get attributes => + _attributes == null ? null : Map.from(_attributes!); + final Map? _attributes; - Operation._(this.key, this.length, this.data, Map attributes) - : assert(key != null && length != null && data != null), - assert(_validKeys.contains(key), 'Invalid operation key "$key".'), + 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; @@ -64,7 +63,7 @@ class Operation { /// /// If `dataDecoder` parameter is not null then it is used to additionally /// decode the operation's data object. Only applied to insert operations. - static Operation fromJson(Map data, {DataDecoder dataDecoder}) { + static Operation fromJson(Map data, {DataDecoder? dataDecoder}) { dataDecoder ??= _passThroughDataDecoder; final map = Map.from(data); if (map.containsKey(Operation.insertKey)) { @@ -95,13 +94,13 @@ class Operation { Operation._(Operation.deleteKey, length, '', null); /// Creates operation which inserts [text] with optional [attributes]. - factory Operation.insert(dynamic data, [Map 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]) => + factory Operation.retain(int length, [Map? attributes]) => Operation._(Operation.retainKey, length, '', attributes); /// Returns value of this operation. @@ -119,7 +118,7 @@ class Operation { bool get isRetain => key == Operation.retainKey; /// Returns `true` if this operation has no attributes, e.g. is plain text. - bool get isPlain => (_attributes == null || _attributes.isEmpty); + bool get isPlain => (_attributes == null || _attributes!.isEmpty); /// Returns `true` if this operation sets at least one attribute. bool get isNotPlain => !isPlain; @@ -144,7 +143,8 @@ class Operation { } /// Returns `true` if this operation has attribute specified by [name]. - bool hasAttribute(String name) => isNotPlain && _attributes.containsKey(name); + bool hasAttribute(String name) => + isNotPlain && _attributes!.containsKey(name); /// Returns `true` if [other] operation has the same attributes as this one. bool hasSameAttributes(Operation other) { @@ -153,9 +153,9 @@ class Operation { @override int get hashCode { - if (_attributes != null && _attributes.isNotEmpty) { + if (_attributes != null && _attributes!.isNotEmpty) { final attrsHash = - hashObjects(_attributes.entries.map((e) => hash2(e.key, e.value))); + hashObjects(_attributes!.entries.map((e) => hash2(e.key, e.value))); return hash3(key, value, attrsHash); } return hash2(key, value); @@ -181,8 +181,8 @@ class Operation { /// it is a "change delta". class Delta { /// Transforms two attribute sets. - static Map transformAttributes( - Map a, Map b, bool priority) { + static Map? transformAttributes( + Map? a, Map? b, bool priority) { if (a == null) return b; if (b == null) return null; @@ -197,8 +197,8 @@ class Delta { } /// Composes two attribute sets. - static Map composeAttributes( - Map a, Map b, + static Map? composeAttributes( + Map? a, Map? b, {bool keepNull = false}) { a ??= const {}; b ??= const {}; @@ -217,20 +217,20 @@ class Delta { ///get anti-attr result base on base static Map invertAttributes( - Map attr, Map base) { + Map? attr, Map? base) { attr ??= const {}; base ??= const {}; - var baseInverted = base.keys.fold({}, (memo, key) { - if (base[key] != attr[key] && attr.containsKey(key)) { - memo[key] = base[key]; + Map baseInverted = base.keys.fold({}, (memo, key) { + if (base![key] != attr![key] && attr.containsKey(key)) { + (memo)[key] = base[key]; } return memo; }); var inverted = Map.from(attr.keys.fold(baseInverted, (memo, key) { - if (base[key] != attr[key] && !base.containsKey(key)) { + if (base![key] != attr![key] && !base.containsKey(key)) { memo[key] = null; } return memo; @@ -242,9 +242,7 @@ class Delta { int _modificationCount = 0; - Delta._(List operations) - : assert(operations != null), - _operations = operations; + Delta._(List operations) : _operations = operations; /// Creates new empty [Delta]. factory Delta() => Delta._([]); @@ -257,7 +255,7 @@ class Delta { /// /// If `dataDecoder` parameter is not null then it is used to additionally /// decode the operation's data object. Only applied to insert operations. - static Delta fromJson(List data, {DataDecoder dataDecoder}) { + static Delta fromJson(List data, {DataDecoder? dataDecoder}) { return Delta._(data .map((op) => Operation.fromJson(op, dataDecoder: dataDecoder)) .toList()); @@ -304,29 +302,29 @@ class Delta { int get hashCode => hashObjects(_operations); /// Retain [count] of characters from current position. - void retain(int count, [Map attributes]) { + void retain(int count, [Map? attributes]) { assert(count >= 0); if (count == 0) return; // no-op push(Operation.retain(count, attributes)); } /// Insert [data] at current position. - void insert(dynamic data, [Map attributes]) { + void insert(dynamic data, [Map? attributes]) { assert(data != null); if (data is String && data.isEmpty) return; // no-op push(Operation.insert(data, attributes)); } /// Delete [count] characters from current position. - void delete(int count) { - assert(count >= 0); + void delete(int? count) { + assert(count != null && count >= 0); if (count == 0) return; - push(Operation.delete(count)); + push(Operation.delete(count!)); } void _mergeWithTail(Operation operation) { assert(isNotEmpty); - assert(operation != null && last.key == operation.key); + assert(last.key == operation.key); assert(operation.data is String && last.data is String); final length = operation.length + last.length; @@ -347,6 +345,7 @@ class Delta { /// tail is replaced with `insert('abc123')` - a compound result of the two /// operations. void push(Operation operation) { + //made it to here if (operation.isEmpty) return; var index = _operations.length; @@ -396,18 +395,19 @@ class Delta { /// Returns new operation or `null` if operations from [thisIter] and /// [otherIter] nullify each other. For instance, for the pair `insert('abc')` /// and `delete(3)` composition result would be empty string. - Operation _composeOperation(DeltaIterator thisIter, DeltaIterator otherIter) { + Operation? _composeOperation( + DeltaIterator thisIter, DeltaIterator otherIter) { if (otherIter.isNextInsert) return otherIter.next(); if (thisIter.isNextDelete) return thisIter.next(); final length = math.min(thisIter.peekLength(), otherIter.peekLength()); - final thisOp = thisIter.next(length); + final thisOp = thisIter.next((length as int)); final otherOp = otherIter.next(length); - assert(thisOp.length == otherOp.length); + assert(thisOp!.length == otherOp!.length); - if (otherOp.isRetain) { + if (otherOp!.isRetain) { final attributes = composeAttributes( - thisOp.attributes, + thisOp!.attributes, otherOp.attributes, keepNull: thisOp.isRetain, ); @@ -421,7 +421,7 @@ class Delta { } else { // otherOp == delete && thisOp in [retain, insert] assert(otherOp.isDelete); - if (thisOp.isRetain) return otherOp; + if (thisOp!.isRetain) return otherOp; assert(thisOp.isInsert); // otherOp(delete) + thisOp(insert) => null } @@ -448,24 +448,24 @@ class Delta { /// [thisIter]. /// /// Returns `null` if both operations nullify each other. - Operation _transformOperation( + Operation? _transformOperation( DeltaIterator thisIter, DeltaIterator otherIter, bool priority) { if (thisIter.isNextInsert && (priority || !otherIter.isNextInsert)) { - return Operation.retain(thisIter.next().length); + return Operation.retain(thisIter.next()!.length); } else if (otherIter.isNextInsert) { return otherIter.next(); } final length = math.min(thisIter.peekLength(), otherIter.peekLength()); - final thisOp = thisIter.next(length); + final thisOp = thisIter.next((length as int)); final otherOp = otherIter.next(length); - assert(thisOp.length == otherOp.length); + assert(thisOp!.length == otherOp!.length); // At this point only delete and retain operations are possible. - if (thisOp.isDelete) { + if (thisOp!.isDelete) { // otherOp is either delete or retain, so they nullify each other. return null; - } else if (otherOp.isDelete) { + } else if (otherOp!.isDelete) { return otherOp; } else { // Retain otherOp which is either retain or insert. @@ -547,7 +547,7 @@ class Delta { /// Returns slice of this delta from [start] index (inclusive) to [end] /// (exclusive). - Delta slice(int start, [int end]) { + Delta slice(int start, [int? end]) { final delta = Delta(); var index = 0; var opIterator = DeltaIterator(this); @@ -557,9 +557,9 @@ class Delta { while (index < actualEnd && opIterator.hasNext) { Operation op; if (index < start) { - op = opIterator.next(start - index); + op = opIterator.next(start - index)!; } else { - op = opIterator.next(actualEnd - index); + op = opIterator.next((actualEnd as int) - index)!; delta.push(op); } index += op.length; @@ -584,7 +584,7 @@ class Delta { var offset = 0; while (iter.hasNext && offset <= index) { final op = iter.next(); - if (op.isDelete) { + if (op!.isDelete) { index -= math.min(op.length, index - offset); continue; } else if (op.isInsert && (offset < index || force)) { @@ -614,7 +614,7 @@ class DeltaIterator { bool get isNextRetain => nextOperationKey == Operation.retainKey; - String get nextOperationKey { + String? get nextOperationKey { if (_index < delta.length) { return delta.elementAt(_index).key; } else { @@ -639,9 +639,7 @@ class DeltaIterator { /// /// Optional [length] specifies maximum length of operation to return. Note /// that actual length of returned operation may be less than specified value. - Operation next([int length = 4294967296]) { - assert(length != null); - + Operation? next([int length = 4294967296]) { if (_modificationCount != delta._modificationCount) { throw ConcurrentModificationError(delta); } @@ -659,13 +657,14 @@ class DeltaIterator { _offset += actualLength; } final opData = op.isInsert && op.data is String - ? (op.data as String) - .substring(_currentOffset, _currentOffset + actualLength) + ? (op.data as String).substring( + (_currentOffset as int), _currentOffset + (actualLength as int)) : op.data; final opIsNotEmpty = opData is String ? opData.isNotEmpty : true; // embeds are never empty final opLength = opData is String ? opData.length : 1; - final int opActualLength = opIsNotEmpty ? opLength : actualLength; + final int opActualLength = + opIsNotEmpty ? opLength : (actualLength as int); return Operation._(opKey, opActualLength, opData, opAttributes); } return Operation.retain(length); @@ -674,14 +673,14 @@ class DeltaIterator { /// Skips [length] characters in source delta. /// /// Returns last skipped operation, or `null` if there was nothing to skip. - Operation skip(int length) { + Operation? skip(int length) { var skipped = 0; - Operation op; + Operation? op; while (skipped < length && hasNext) { - final opLength = peekLength(); - final skip = math.min(length - skipped, opLength); + final int opLength = (peekLength() as int); + final int skip = math.min(length - skipped, opLength); op = next(skip); - skipped += op.length; + skipped += op!.length; } return op; } diff --git a/lib/models/rules/delete.dart b/lib/models/rules/delete.dart index 6cbb28ff..cbf337f7 100644 --- a/lib/models/rules/delete.dart +++ b/lib/models/rules/delete.dart @@ -7,21 +7,14 @@ abstract class DeleteRule extends Rule { @override RuleType get type => RuleType.DELETE; - - @override - validateArgs(int len, Object data, Attribute attribute) { - assert(len != null); - assert(data == null); - assert(attribute == null); - } } class CatchAllDeleteRule extends DeleteRule { const CatchAllDeleteRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { return Delta() ..retain(index) ..delete(len); @@ -32,25 +25,25 @@ class PreserveLineStyleOnMergeRule extends DeleteRule { const PreserveLineStyleOnMergeRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { DeltaIterator itr = DeltaIterator(document); itr.skip(index); - Operation op = itr.next(1); + Operation op = itr.next(1)!; if (op.data != '\n') { return null; } bool isNotPlain = op.isNotPlain; - Map attrs = op.attributes; - - itr.skip(len - 1); + Map attrs = op.attributes!; + assert(len != null); + itr.skip(len! - 1); Delta delta = Delta() ..retain(index) ..delete(len); while (itr.hasNext) { - op = itr.next(); + op = itr.next()!; String text = op.data is String ? op.data as String : ''; int lineBreak = text.indexOf('\n'); if (lineBreak == -1) { @@ -58,9 +51,9 @@ class PreserveLineStyleOnMergeRule extends DeleteRule { continue; } - Map attributes = op.attributes == null + Map? attributes = op.attributes == null ? null - : op.attributes.map((String key, dynamic value) => + : op.attributes!.map((String key, dynamic value) => MapEntry(key, null)); if (isNotPlain) { @@ -78,23 +71,24 @@ class EnsureEmbedLineRule extends DeleteRule { const EnsureEmbedLineRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { DeltaIterator itr = DeltaIterator(document); - Operation op = itr.skip(index); - int indexDelta = 0, lengthDelta = 0, remain = len; + Operation? op = itr.skip(index); + assert(len != null); + int indexDelta = 0, lengthDelta = 0, remain = len!; bool embedFound = op != null && op.data is! String; bool hasLineBreakBefore = - !embedFound && (op == null || (op?.data as String).endsWith('\n')); + !embedFound && (op == null || (op.data as String).endsWith('\n')); if (embedFound) { - Operation candidate = itr.next(1); + Operation candidate = itr.next(1)!; remain--; if (candidate.data == '\n') { indexDelta++; lengthDelta--; - candidate = itr.next(1); + candidate = itr.next(1)!; remain--; if (candidate.data == '\n') { lengthDelta++; @@ -104,8 +98,8 @@ class EnsureEmbedLineRule extends DeleteRule { op = itr.skip(remain); if (op != null && - (op?.data is String ? op.data as String : '').endsWith('\n')) { - Operation candidate = itr.next(1); + (op.data is String ? op.data as String : '').endsWith('\n')) { + Operation candidate = itr.next(1)!; if (candidate.data is! String && !hasLineBreakBefore) { embedFound = true; lengthDelta--; diff --git a/lib/models/rules/format.dart b/lib/models/rules/format.dart index 755bc0bb..0aa50d29 100644 --- a/lib/models/rules/format.dart +++ b/lib/models/rules/format.dart @@ -7,22 +7,15 @@ abstract class FormatRule extends Rule { @override RuleType get type => RuleType.FORMAT; - - @override - validateArgs(int len, Object data, Attribute attribute) { - assert(len != null); - assert(data == null); - assert(attribute != null); - } } class ResolveLineFormatRule extends FormatRule { const ResolveLineFormatRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (attribute.scope != AttributeScope.BLOCK) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (attribute != null && attribute.scope != AttributeScope.BLOCK) { return null; } @@ -30,20 +23,21 @@ class ResolveLineFormatRule extends FormatRule { DeltaIterator itr = DeltaIterator(document); itr.skip(index); Operation op; - for (int cur = 0; cur < len && itr.hasNext; cur += op.length) { - op = itr.next(len - cur); + assert(len != null); + for (int cur = 0; cur < len! && itr.hasNext; cur += op.length) { + op = itr.next(len - cur)!; if (op.data is! String || !(op.data as String).contains('\n')) { delta.retain(op.length); continue; } - String text = op.data; + String text = (op.data as String); Delta tmp = Delta(); int offset = 0; for (int lineBreak = text.indexOf('\n'); lineBreak >= 0; lineBreak = text.indexOf('\n', offset)) { - tmp..retain(lineBreak - offset)..retain(1, attribute.toJson()); + tmp..retain(lineBreak - offset)..retain(1, attribute!.toJson()); offset = lineBreak + 1; } tmp.retain(text.length - offset); @@ -51,14 +45,14 @@ class ResolveLineFormatRule extends FormatRule { } while (itr.hasNext) { - op = itr.next(); + op = itr.next()!; String text = op.data is String ? op.data as String : ''; int lineBreak = text.indexOf('\n'); if (lineBreak < 0) { delta..retain(op.length); continue; } - delta..retain(lineBreak)..retain(1, attribute.toJson()); + delta..retain(lineBreak)..retain(1, attribute!.toJson()); break; } return delta; @@ -69,21 +63,23 @@ class FormatLinkAtCaretPositionRule extends FormatRule { const FormatLinkAtCaretPositionRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (attribute.key != Attribute.link.key || len > 0) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + assert(len != null); + if (attribute != null && attribute.key != Attribute.link.key || len! > 0) { return null; } Delta delta = Delta(); DeltaIterator itr = DeltaIterator(document); - Operation before = itr.skip(index), after = itr.next(); + Operation? before = itr.skip(index), after = itr.next(); int beg = index, retain = 0; - if (before != null && before.hasAttribute(attribute.key)) { + assert(attribute != null); + if (before != null && before.hasAttribute(attribute!.key!)) { beg -= before.length; retain = before.length; } - if (after != null && after.hasAttribute(attribute.key)) { + if (after!.hasAttribute(attribute!.key!)) { retain += after.length; } if (retain == 0) { @@ -99,9 +95,10 @@ class ResolveInlineFormatRule extends FormatRule { const ResolveInlineFormatRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (attribute.scope != AttributeScope.INLINE) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + assert(attribute != null && len != null); + if (attribute!.scope != AttributeScope.INLINE) { return null; } @@ -110,8 +107,8 @@ class ResolveInlineFormatRule extends FormatRule { itr.skip(index); Operation op; - for (int cur = 0; cur < len && itr.hasNext; cur += op.length) { - op = itr.next(len - cur); + for (int cur = 0; cur < len! && itr.hasNext; cur += op.length) { + op = itr.next(len - cur)!; String text = op.data is String ? op.data as String : ''; int lineBreak = text.indexOf('\n'); if (lineBreak < 0) { diff --git a/lib/models/rules/insert.dart b/lib/models/rules/insert.dart index 1973d981..414debfb 100644 --- a/lib/models/rules/insert.dart +++ b/lib/models/rules/insert.dart @@ -9,36 +9,27 @@ abstract class InsertRule extends Rule { @override RuleType get type => RuleType.INSERT; - - @override - validateArgs(int len, Object data, Attribute attribute) { - assert(len == null); - assert(data != null); - assert(attribute == null); - } } class PreserveLineStyleOnSplitRule extends InsertRule { const PreserveLineStyleOnSplitRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || (data as String) != '\n') { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || data != '\n') { return null; } DeltaIterator itr = DeltaIterator(document); - Operation before = itr.skip(index); + Operation? before = itr.skip(index); if (before == null || before.data is! String || (before.data as String).endsWith('\n')) { return null; } - Operation after = itr.next(); - if (after == null || - after.data is! String || - (after.data as String).startsWith('\n')) { + Operation after = itr.next()!; + if (after.data is! String || (after.data as String).startsWith('\n')) { return null; } @@ -50,8 +41,8 @@ class PreserveLineStyleOnSplitRule extends InsertRule { delta..insert('\n'); return delta; } - Tuple2 nextNewLine = _getNextNewLine(itr); - Map attributes = nextNewLine?.item1?.attributes; + Tuple2 nextNewLine = _getNextNewLine(itr); + Map? attributes = nextNewLine.item1!.attributes; return delta..insert('\n', attributes); } @@ -61,33 +52,33 @@ class PreserveBlockStyleOnInsertRule extends InsertRule { const PreserveBlockStyleOnInsertRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || !(data as String).contains('\n')) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || !data.contains('\n')) { return null; } DeltaIterator itr = DeltaIterator(document); itr.skip(index); - Tuple2 nextNewLine = _getNextNewLine(itr); + Tuple2 nextNewLine = _getNextNewLine(itr); Style lineStyle = Style.fromJson(nextNewLine.item1?.attributes ?? {}); - Attribute attribute = lineStyle.getBlockExceptHeader(); + Attribute? attribute = lineStyle.getBlockExceptHeader(); if (attribute == null) { return null; } - var blockStyle = {attribute.key: attribute.value}; + var blockStyle = {attribute.key!: attribute.value}; - Map resetStyle; + Map? resetStyle; - if (lineStyle.containsKey(Attribute.header.key)) { + if (lineStyle.containsKey(Attribute.header.key!)) { resetStyle = Attribute.header.toJson(); } - List lines = (data as String).split('\n'); + List lines = data.split('\n'); Delta delta = Delta()..retain(index); for (int i = 0; i < lines.length; i++) { String line = lines[i]; @@ -102,9 +93,9 @@ class PreserveBlockStyleOnInsertRule extends InsertRule { } if (resetStyle != null) { - delta.retain(nextNewLine.item2); + delta.retain(nextNewLine.item2!); delta - ..retain((nextNewLine.item1.data as String).indexOf('\n')) + ..retain((nextNewLine.item1!.data as String).indexOf('\n')) ..retain(1, resetStyle); } @@ -115,7 +106,7 @@ class PreserveBlockStyleOnInsertRule extends InsertRule { class AutoExitBlockRule extends InsertRule { const AutoExitBlockRule(); - bool _isEmptyLine(Operation before, Operation after) { + bool _isEmptyLine(Operation? before, Operation after) { if (before == null) { return true; } @@ -126,16 +117,16 @@ class AutoExitBlockRule extends InsertRule { } @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || (data as String) != '\n') { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || data != '\n') { return null; } DeltaIterator itr = DeltaIterator(document); - Operation prev = itr.skip(index), cur = itr.next(); - Attribute blockStyle = - Style.fromJson(cur.attributes).getBlockExceptHeader(); + Operation? prev = itr.skip(index), cur = itr.next(); + Attribute? blockStyle = + Style.fromJson(cur!.attributes).getBlockExceptHeader(); if (cur.isPlain || blockStyle == null) { return null; } @@ -147,10 +138,10 @@ class AutoExitBlockRule extends InsertRule { return null; } - Tuple2 nextNewLine = _getNextNewLine(itr); + Tuple2 nextNewLine = _getNextNewLine(itr); if (nextNewLine.item1 != null && - nextNewLine.item1.attributes != null && - Style.fromJson(nextNewLine.item1.attributes).getBlockExceptHeader() == + nextNewLine.item1!.attributes != null && + Style.fromJson(nextNewLine.item1!.attributes).getBlockExceptHeader() == blockStyle) { return null; } @@ -168,22 +159,22 @@ class ResetLineFormatOnNewLineRule extends InsertRule { const ResetLineFormatOnNewLineRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || (data as String) != '\n') { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || data != '\n') { return null; } DeltaIterator itr = DeltaIterator(document); itr.skip(index); - Operation cur = itr.next(); + Operation cur = itr.next()!; if (cur.data is! String || !(cur.data as String).startsWith('\n')) { return null; } - Map resetStyle; + Map? resetStyle; if (cur.attributes != null && - cur.attributes.containsKey(Attribute.header.key)) { + cur.attributes!.containsKey(Attribute.header.key)) { resetStyle = Attribute.header.toJson(); } return Delta() @@ -198,18 +189,18 @@ class InsertEmbedsRule extends InsertRule { const InsertEmbedsRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { if (data is String) { return null; } Delta delta = Delta()..retain(index); DeltaIterator itr = DeltaIterator(document); - Operation prev = itr.skip(index), cur = itr.next(); + Operation? prev = itr.skip(index), cur = itr.next(); - String textBefore = prev?.data is String ? prev.data as String : ''; - String textAfter = cur.data is String ? cur.data as String : ''; + String textBefore = prev?.data is String ? prev!.data as String : ''; + String textAfter = cur!.data is String ? cur.data as String : ''; final isNewlineBefore = prev == null || textBefore.endsWith('\n'); final isNewlineAfter = textAfter.startsWith('\n'); @@ -218,12 +209,12 @@ class InsertEmbedsRule extends InsertRule { return delta..insert(data); } - Map lineStyle; + Map? lineStyle; if (textAfter.contains('\n')) { lineStyle = cur.attributes; } else { while (itr.hasNext) { - Operation op = itr.next(); + Operation op = itr.next()!; if ((op.data is String ? op.data as String : '').indexOf('\n') >= 0) { lineStyle = op.attributes; break; @@ -246,17 +237,17 @@ class ForceNewlineForInsertsAroundEmbedRule extends InsertRule { const ForceNewlineForInsertsAroundEmbedRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { if (data is! String) { return null; } - String text = data as String; + String text = data; DeltaIterator itr = DeltaIterator(document); final prev = itr.skip(index); final cur = itr.next(); - bool cursorBeforeEmbed = cur.data is! String; + bool cursorBeforeEmbed = cur!.data is! String; bool cursorAfterEmbed = prev != null && prev.data is! String; if (!cursorBeforeEmbed && !cursorAfterEmbed) { @@ -277,14 +268,14 @@ class AutoFormatLinksRule extends InsertRule { const AutoFormatLinksRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || (data as String) != ' ') { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || data != ' ') { return null; } DeltaIterator itr = DeltaIterator(document); - Operation prev = itr.skip(index); + Operation? prev = itr.skip(index); if (prev == null || prev.data is! String) { return null; } @@ -305,7 +296,7 @@ class AutoFormatLinksRule extends InsertRule { return Delta() ..retain(index - cand.length) ..retain(cand.length, attributes) - ..insert(data as String, prev.attributes); + ..insert(data, prev.attributes); } on FormatException { return null; } @@ -316,22 +307,22 @@ class PreserveInlineStylesRule extends InsertRule { const PreserveInlineStylesRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { - if (data is! String || (data as String).contains('\n')) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { + if (data is! String || data.contains('\n')) { return null; } DeltaIterator itr = DeltaIterator(document); - Operation prev = itr.skip(index); + Operation? prev = itr.skip(index); if (prev == null || prev.data is! String || (prev.data as String).contains('\n')) { return null; } - Map attributes = prev.attributes; - String text = data as String; + Map? attributes = prev.attributes; + String text = data; if (attributes == null || !attributes.containsKey(Attribute.link.key)) { return Delta() ..retain(index) @@ -342,7 +333,8 @@ class PreserveInlineStylesRule extends InsertRule { Delta delta = Delta() ..retain(index) ..insert(text, attributes.isEmpty ? null : attributes); - Operation next = itr.next(); + Operation? next = itr.next(); + //DeltaIterator method next() never returns null. Yet, this looks like null is sometimes expected? Should maybe be taken out. if (next == null) { return delta; } @@ -364,19 +356,19 @@ class CatchAllInsertRule extends InsertRule { const CatchAllInsertRule(); @override - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}) { + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { return Delta() ..retain(index) ..insert(data); } } -Tuple2 _getNextNewLine(DeltaIterator iterator) { - Operation op; +Tuple2 _getNextNewLine(DeltaIterator iterator) { + Operation? op; for (int skipped = 0; iterator.hasNext; skipped += op.length) { op = iterator.next(); - int lineBreak = (op.data is String ? op.data as String : '').indexOf('\n'); + int lineBreak = (op!.data is String ? op.data as String : '').indexOf('\n'); if (lineBreak >= 0) { return Tuple2(op, skipped); } diff --git a/lib/models/rules/rule.dart b/lib/models/rules/rule.dart index 13c7d12e..f5c27759 100644 --- a/lib/models/rules/rule.dart +++ b/lib/models/rules/rule.dart @@ -11,19 +11,16 @@ enum RuleType { INSERT, DELETE, FORMAT } abstract class Rule { const Rule(); - Delta apply(Delta document, int index, - {int len, Object data, Attribute attribute}) { - assert(document != null); - assert(index != null); - validateArgs(len, data, attribute); + Delta? apply(Delta document, int index, + {int? len, Object? data, Attribute? attribute}) { return applyRule(document, index, len: len, data: data, attribute: attribute); } - validateArgs(int len, Object data, Attribute attribute); + // validateArgs(int len, Object data, Attribute attribute); - Delta applyRule(Delta document, int index, - {int len, Object data, Attribute attribute}); + Delta? applyRule(Delta document, int index, + {int? len, Object? data, Attribute? attribute}); RuleType get type; } @@ -53,7 +50,7 @@ class Rules { static Rules getInstance() => _instance; Delta apply(RuleType ruleType, Document document, int index, - {int len, Object data, Attribute attribute}) { + {int? len, Object? data, Attribute? attribute}) { final delta = document.toDelta(); for (var rule in _rules) { if (rule.type != ruleType) { @@ -63,7 +60,7 @@ class Rules { final result = rule.apply(delta, index, len: len, data: data, attribute: attribute); if (result != null) { - print("Rule $rule applied"); + print("Rule $rule applied"); //made to here return result..trim(); } } catch (e) { diff --git a/lib/universal_ui/fake_ui.dart b/lib/universal_ui/fake_ui.dart new file mode 100755 index 00000000..bc9799af --- /dev/null +++ b/lib/universal_ui/fake_ui.dart @@ -0,0 +1,4 @@ +// ignore: camel_case_types +class platformViewRegistry { + static registerViewFactory(String viewId, dynamic cb) {} +} diff --git a/lib/universal_ui/real_ui.dart b/lib/universal_ui/real_ui.dart new file mode 100755 index 00000000..c2b8ea23 --- /dev/null +++ b/lib/universal_ui/real_ui.dart @@ -0,0 +1,9 @@ +import 'dart:ui' as ui; + +// ignore: camel_case_types +class platformViewRegistry { + static registerViewFactory(String viewId, dynamic cb) { + // ignore:undefined_prefixed_name + ui.platformViewRegistry.registerViewFactory(viewId, cb); + } +} diff --git a/lib/universal_ui/universal_ui.dart b/lib/universal_ui/universal_ui.dart new file mode 100755 index 00000000..20cf5ded --- /dev/null +++ b/lib/universal_ui/universal_ui.dart @@ -0,0 +1,20 @@ +import 'package:flutter/foundation.dart'; +import 'fake_ui.dart' if (dart.library.html) 'real_ui.dart' as ui_instance; + +class PlatformViewRegistryFix { + registerViewFactory(dynamic x, dynamic y) { + if (kIsWeb) { + // ignore: undefined_prefixed_name + ui_instance.platformViewRegistry.registerViewFactory( + x, + y, + ); + } else {} + } +} + +class UniversalUI { + PlatformViewRegistryFix platformViewRegistry = PlatformViewRegistryFix(); +} + +var ui = UniversalUI(); diff --git a/lib/utils/diff_delta.dart b/lib/utils/diff_delta.dart index 673dacd2..ce415874 100644 --- a/lib/utils/diff_delta.dart +++ b/lib/utils/diff_delta.dart @@ -75,9 +75,10 @@ int getPositionDelta(Delta user, Delta actual) { DeltaIterator actualItr = DeltaIterator(actual); int diff = 0; while (userItr.hasNext || actualItr.hasNext) { - final length = math.min(userItr.peekLength(), actualItr.peekLength()); - Operation userOperation = userItr.next(length); - Operation actualOperation = actualItr.next(length); + final int length = + math.min(userItr.peekLength(), actualItr.peekLength()) as int; + Operation userOperation = userItr.next(length)!; + Operation actualOperation = actualItr.next(length)!; if (userOperation.length != actualOperation.length) { throw ('userOp ' + userOperation.length.toString() + diff --git a/lib/widgets/box.dart b/lib/widgets/box.dart index 9a28d1e1..d8366c51 100644 --- a/lib/widgets/box.dart +++ b/lib/widgets/box.dart @@ -8,7 +8,7 @@ abstract class RenderContentProxyBox implements RenderBox { TextPosition getPositionForOffset(Offset offset); - double getFullHeightForCaret(TextPosition position); + double? getFullHeightForCaret(TextPosition position); TextRange getWordBoundary(TextPosition position); @@ -24,9 +24,9 @@ abstract class RenderEditableBox extends RenderBox { TextPosition getPositionForOffset(Offset offset); - TextPosition getPositionAbove(TextPosition position); + TextPosition? getPositionAbove(TextPosition position); - TextPosition getPositionBelow(TextPosition position); + TextPosition? getPositionBelow(TextPosition position); TextRange getWordBoundary(TextPosition position); diff --git a/lib/widgets/controller.dart b/lib/widgets/controller.dart index 9c23d327..4726c4db 100644 --- a/lib/widgets/controller.dart +++ b/lib/widgets/controller.dart @@ -14,9 +14,7 @@ class QuillController extends ChangeNotifier { TextSelection selection; Style toggledStyle = Style(); - QuillController({@required this.document, @required this.selection}) - : assert(document != null), - assert(selection != null); + QuillController({required this.document, required this.selection}); factory QuillController.basic() { return QuillController( @@ -75,19 +73,18 @@ class QuillController extends ChangeNotifier { get hasRedo => document.hasRedo; - replaceText(int index, int len, Object data, TextSelection textSelection) { + replaceText(int index, int len, Object data, TextSelection? textSelection) { assert(data is String || data is Embeddable); - Delta delta; - if (len > 0 || data is! String || (data as String).isNotEmpty) { + Delta? delta; + if (len > 0 || data is! String || data.isNotEmpty) { try { delta = document.replace(index, len, data); } catch (e) { print('document.replace failed: $e'); throw e; } - bool shouldRetainDelta = delta != null && - toggledStyle.isNotEmpty && + bool shouldRetainDelta = toggledStyle.isNotEmpty && delta.isNotEmpty && delta.length <= 2 && delta.last.isInsert; @@ -161,7 +158,7 @@ class QuillController extends ChangeNotifier { notifyListeners(); } - compose(Delta delta, TextSelection textSelection, ChangeSource source) { + compose(Delta delta, TextSelection? textSelection, ChangeSource source) { if (delta.isNotEmpty) { document.compose(delta, source); } @@ -187,8 +184,6 @@ class QuillController extends ChangeNotifier { } _updateSelection(TextSelection textSelection, ChangeSource source) { - assert(textSelection != null); - assert(source != null); selection = textSelection; int end = document.length - 1; selection = selection.copyWith( diff --git a/lib/widgets/cursor.dart b/lib/widgets/cursor.dart index 6318dba6..97e24407 100644 --- a/lib/widgets/cursor.dart +++ b/lib/widgets/cursor.dart @@ -11,25 +11,22 @@ class CursorStyle { final Color color; final Color backgroundColor; final double width; - final double height; - final Radius radius; - final Offset offset; + final double? height; + final Radius? radius; + final Offset? offset; final bool opacityAnimates; final bool paintAboveText; const CursorStyle({ - @required this.color, - @required this.backgroundColor, + required this.color, + required this.backgroundColor, this.width = 1.0, this.height, this.radius, this.offset, this.opacityAnimates = false, this.paintAboveText = false, - }) : assert(color != null), - assert(backgroundColor != null), - assert(opacityAnimates != null), - assert(paintAboveText != null); + }); @override bool operator ==(Object other) => @@ -61,25 +58,22 @@ class CursorCont extends ChangeNotifier { final ValueNotifier show; final ValueNotifier _blink; final ValueNotifier color; - AnimationController _blinkOpacityCont; - Timer _cursorTimer; + AnimationController? _blinkOpacityCont; + Timer? _cursorTimer; bool _targetCursorVisibility = false; CursorStyle _style; CursorCont({ - @required ValueNotifier show, - @required CursorStyle style, - @required TickerProvider tickerProvider, - }) : assert(show != null), - assert(style != null), - assert(tickerProvider != null), - show = show ?? ValueNotifier(false), + required ValueNotifier show, + required CursorStyle style, + required TickerProvider tickerProvider, + }) : show = show, _style = style, _blink = ValueNotifier(false), color = ValueNotifier(style.color) { _blinkOpacityCont = AnimationController(vsync: tickerProvider, duration: _FADE_DURATION); - _blinkOpacityCont.addListener(_onColorTick); + _blinkOpacityCont!.addListener(_onColorTick); } ValueNotifier get cursorBlink => _blink; @@ -89,7 +83,6 @@ class CursorCont extends ChangeNotifier { CursorStyle get style => _style; set style(CursorStyle value) { - assert(value != null); if (_style == value) return; _style = value; notifyListeners(); @@ -97,9 +90,9 @@ class CursorCont extends ChangeNotifier { @override dispose() { - _blinkOpacityCont.removeListener(_onColorTick); + _blinkOpacityCont!.removeListener(_onColorTick); stopCursorTimer(); - _blinkOpacityCont.dispose(); + _blinkOpacityCont!.dispose(); assert(_cursorTimer == null); super.dispose(); } @@ -108,9 +101,9 @@ class CursorCont extends ChangeNotifier { _targetCursorVisibility = !_targetCursorVisibility; double targetOpacity = _targetCursorVisibility ? 1.0 : 0.0; if (style.opacityAnimates) { - _blinkOpacityCont.animateTo(targetOpacity, curve: Curves.easeOut); + _blinkOpacityCont!.animateTo(targetOpacity, curve: Curves.easeOut); } else { - _blinkOpacityCont.value = targetOpacity; + _blinkOpacityCont!.value = targetOpacity; } } @@ -121,7 +114,7 @@ class CursorCont extends ChangeNotifier { void startCursorTimer() { _targetCursorVisibility = true; - _blinkOpacityCont.value = 1.0; + _blinkOpacityCont!.value = 1.0; if (style.opacityAnimates) { _cursorTimer = @@ -135,11 +128,11 @@ class CursorCont extends ChangeNotifier { _cursorTimer?.cancel(); _cursorTimer = null; _targetCursorVisibility = false; - _blinkOpacityCont.value = 0.0; + _blinkOpacityCont!.value = 0.0; if (style.opacityAnimates) { - _blinkOpacityCont.stop(); - _blinkOpacityCont.value = 0.0; + _blinkOpacityCont!.stop(); + _blinkOpacityCont!.value = 0.0; } } @@ -155,8 +148,8 @@ class CursorCont extends ChangeNotifier { } _onColorTick() { - color.value = _style.color.withOpacity(_blinkOpacityCont.value); - _blink.value = show.value && _blinkOpacityCont.value > 0; + color.value = _style.color.withOpacity(_blinkOpacityCont!.value); + _blink.value = show.value && _blinkOpacityCont!.value > 0; } } @@ -171,20 +164,18 @@ class CursorPainter { this.devicePixelRatio); paint(Canvas canvas, Offset offset, TextPosition position) { - assert(prototype != null); - Offset caretOffset = editable.getOffsetForCaret(position, prototype) + offset; Rect caretRect = prototype.shift(caretOffset); if (style.offset != null) { - caretRect = caretRect.shift(style.offset); + caretRect = caretRect.shift(style.offset!); } if (caretRect.left < 0.0) { caretRect = caretRect.shift(Offset(-caretRect.left, 0.0)); } - double caretHeight = editable.getFullHeightForCaret(position); + double? caretHeight = editable.getFullHeightForCaret(position); if (caretHeight != null) { switch (defaultTargetPlatform) { case TargetPlatform.android: @@ -230,7 +221,7 @@ class CursorPainter { return; } - RRect caretRRect = RRect.fromRectAndRadius(caretRect, style.radius); + RRect caretRRect = RRect.fromRectAndRadius(caretRect, style.radius!); canvas.drawRRect(caretRRect, paint); } } diff --git a/lib/widgets/default_styles.dart b/lib/widgets/default_styles.dart index 4cad7bbb..7beb9f5c 100644 --- a/lib/widgets/default_styles.dart +++ b/lib/widgets/default_styles.dart @@ -6,25 +6,23 @@ class QuillStyles extends InheritedWidget { final DefaultStyles data; QuillStyles({ - Key key, - @required this.data, - @required Widget child, - }) : assert(data != null), - assert(child != null), - super(key: key, child: child); + Key? key, + required this.data, + required Widget child, + }) : super(key: key, child: child); @override bool updateShouldNotify(QuillStyles oldWidget) { return data != oldWidget.data; } - static DefaultStyles getStyles(BuildContext context, bool nullOk) { + static DefaultStyles? getStyles(BuildContext context, bool nullOk) { var widget = context.dependOnInheritedWidgetOfExactType(); if (widget == null && nullOk) { return null; } assert(widget != null); - return widget.data; + return widget!.data; } } @@ -35,31 +33,31 @@ class DefaultTextBlockStyle { final Tuple2 lineSpacing; - final BoxDecoration decoration; + final BoxDecoration? decoration; DefaultTextBlockStyle( this.style, this.verticalSpacing, this.lineSpacing, this.decoration); } class DefaultStyles { - final DefaultTextBlockStyle h1; - final DefaultTextBlockStyle h2; - final DefaultTextBlockStyle h3; - final DefaultTextBlockStyle paragraph; - final TextStyle bold; - final TextStyle italic; - final TextStyle underline; - final TextStyle strikeThrough; - final TextStyle sizeSmall; // 'small' - final TextStyle sizeLarge; // 'large' - final TextStyle sizeHuge; // 'huge' - final TextStyle link; - final DefaultTextBlockStyle placeHolder; - final DefaultTextBlockStyle lists; - final DefaultTextBlockStyle quote; - final DefaultTextBlockStyle code; - final DefaultTextBlockStyle indent; - final DefaultTextBlockStyle align; + final DefaultTextBlockStyle? h1; + final DefaultTextBlockStyle? h2; + final DefaultTextBlockStyle? h3; + final DefaultTextBlockStyle? paragraph; + final TextStyle? bold; + final TextStyle? italic; + final TextStyle? underline; + final TextStyle? strikeThrough; + final TextStyle? sizeSmall; // 'small' + final TextStyle? sizeLarge; // 'large' + final TextStyle? sizeHuge; // 'huge' + final TextStyle? link; + final DefaultTextBlockStyle? placeHolder; + final DefaultTextBlockStyle? lists; + final DefaultTextBlockStyle? quote; + final DefaultTextBlockStyle? code; + final DefaultTextBlockStyle? indent; + final DefaultTextBlockStyle? align; DefaultStyles( {this.h1, @@ -109,7 +107,7 @@ class DefaultStyles { h1: DefaultTextBlockStyle( defaultTextStyle.style.copyWith( fontSize: 34.0, - color: defaultTextStyle.style.color.withOpacity(0.70), + color: defaultTextStyle.style.color!.withOpacity(0.70), height: 1.15, fontWeight: FontWeight.w300, ), @@ -119,7 +117,7 @@ class DefaultStyles { h2: DefaultTextBlockStyle( defaultTextStyle.style.copyWith( fontSize: 24.0, - color: defaultTextStyle.style.color.withOpacity(0.70), + color: defaultTextStyle.style.color!.withOpacity(0.70), height: 1.15, fontWeight: FontWeight.normal, ), @@ -129,7 +127,7 @@ class DefaultStyles { h3: DefaultTextBlockStyle( defaultTextStyle.style.copyWith( fontSize: 20.0, - color: defaultTextStyle.style.color.withOpacity(0.70), + color: defaultTextStyle.style.color!.withOpacity(0.70), height: 1.25, fontWeight: FontWeight.w500, ), @@ -158,7 +156,7 @@ class DefaultStyles { lists: DefaultTextBlockStyle( baseStyle, baseSpacing, Tuple2(0.0, 6.0), null), quote: DefaultTextBlockStyle( - TextStyle(color: baseStyle.color.withOpacity(0.6)), + TextStyle(color: baseStyle.color!.withOpacity(0.6)), baseSpacing, Tuple2(6.0, 2.0), BoxDecoration( diff --git a/lib/widgets/delegate.dart b/lib/widgets/delegate.dart index aee7a058..daf49be1 100644 --- a/lib/widgets/delegate.dart +++ b/lib/widgets/delegate.dart @@ -21,21 +21,20 @@ class EditorTextSelectionGestureDetectorBuilder { final EditorTextSelectionGestureDetectorBuilderDelegate delegate; bool shouldShowSelectionToolbar = true; - EditorTextSelectionGestureDetectorBuilder(this.delegate) - : assert(delegate != null); + EditorTextSelectionGestureDetectorBuilder(this.delegate); - EditorState getEditor() { + EditorState? getEditor() { return delegate.getEditableTextKey().currentState; } - RenderEditor getRenderEditor() { - return this.getEditor().getRenderEditor(); + RenderEditor? getRenderEditor() { + return this.getEditor()?.getRenderEditor(); } onTapDown(TapDownDetails details) { - getRenderEditor().handleTapDown(details); + getRenderEditor()?.handleTapDown(details); - PointerDeviceKind kind = details.kind; + PointerDeviceKind? kind = details.kind; shouldShowSelectionToolbar = kind == null || kind == PointerDeviceKind.touch || kind == PointerDeviceKind.stylus; @@ -45,7 +44,7 @@ class EditorTextSelectionGestureDetectorBuilder { assert(delegate.getForcePressEnabled()); shouldShowSelectionToolbar = true; if (delegate.getSelectionEnabled()) { - getRenderEditor().selectWordsInRange( + getRenderEditor()?.selectWordsInRange( details.globalPosition, null, SelectionChangedCause.forcePress, @@ -55,19 +54,19 @@ class EditorTextSelectionGestureDetectorBuilder { onForcePressEnd(ForcePressDetails details) { assert(delegate.getForcePressEnabled()); - getRenderEditor().selectWordsInRange( + getRenderEditor()?.selectWordsInRange( details.globalPosition, null, SelectionChangedCause.forcePress, ); if (shouldShowSelectionToolbar) { - getEditor().showToolbar(); + getEditor()?.showToolbar(); } } onSingleTapUp(TapUpDetails details) { if (delegate.getSelectionEnabled()) { - getRenderEditor().selectWordEdge(SelectionChangedCause.tap); + getRenderEditor()?.selectWordEdge(SelectionChangedCause.tap); } } @@ -75,7 +74,7 @@ class EditorTextSelectionGestureDetectorBuilder { onSingleLongTapStart(LongPressStartDetails details) { if (delegate.getSelectionEnabled()) { - getRenderEditor().selectPositionAt( + getRenderEditor()?.selectPositionAt( details.globalPosition, null, SelectionChangedCause.longPress, @@ -85,7 +84,7 @@ class EditorTextSelectionGestureDetectorBuilder { onSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) { if (delegate.getSelectionEnabled()) { - getRenderEditor().selectPositionAt( + getRenderEditor()?.selectPositionAt( details.globalPosition, null, SelectionChangedCause.longPress, @@ -95,21 +94,21 @@ class EditorTextSelectionGestureDetectorBuilder { onSingleLongTapEnd(LongPressEndDetails details) { if (shouldShowSelectionToolbar) { - getEditor().showToolbar(); + getEditor()?.showToolbar(); } } onDoubleTapDown(TapDownDetails details) { if (delegate.getSelectionEnabled()) { - getRenderEditor().selectWord(SelectionChangedCause.tap); + getRenderEditor()?.selectWord(SelectionChangedCause.tap); if (shouldShowSelectionToolbar) { - getEditor().showToolbar(); + getEditor()?.showToolbar(); } } } onDragSelectionStart(DragStartDetails details) { - getRenderEditor().selectPositionAt( + getRenderEditor()?.selectPositionAt( details.globalPosition, null, SelectionChangedCause.drag, @@ -118,7 +117,7 @@ class EditorTextSelectionGestureDetectorBuilder { onDragSelectionUpdate( DragStartDetails startDetails, DragUpdateDetails updateDetails) { - getRenderEditor().selectPositionAt( + getRenderEditor()?.selectPositionAt( startDetails.globalPosition, updateDetails.globalPosition, SelectionChangedCause.drag, diff --git a/lib/widgets/editor.dart b/lib/widgets/editor.dart index 6c355b22..b07e090c 100644 --- a/lib/widgets/editor.dart +++ b/lib/widgets/editor.dart @@ -21,8 +21,9 @@ import 'package:flutter_quill/widgets/raw_editor.dart'; import 'package:flutter_quill/widgets/responsive_widget.dart'; import 'package:flutter_quill/widgets/text_selection.dart'; import 'package:string_validator/string_validator.dart'; -import 'package:universal_html/prefer_universal/html.dart' as html; -import 'package:universal_ui/universal_ui.dart'; +import 'package:universal_html/html.dart' as html; +//import 'package:universal_ui/universal_ui.dart'; +import 'package:flutter_quill/universal_ui/universal_ui.dart'; import 'package:url_launcher/url_launcher.dart'; import 'box.dart'; @@ -53,9 +54,9 @@ abstract class EditorState extends State { void setTextEditingValue(TextEditingValue value); - RenderEditor getRenderEditor(); + RenderEditor? getRenderEditor(); - EditorTextSelectionOverlay getSelectionOverlay(); + EditorTextSelectionOverlay? getSelectionOverlay(); bool showToolbar(); @@ -146,51 +147,44 @@ class QuillEditor extends StatefulWidget { final bool scrollable; final EdgeInsetsGeometry padding; final bool autoFocus; - final bool showCursor; + final bool? showCursor; final bool readOnly; - final String placeholder; - final bool enableInteractiveSelection; - final double minHeight; - final double maxHeight; - final DefaultStyles customStyles; + final String? placeholder; + final bool? enableInteractiveSelection; + final double? minHeight; + final double? maxHeight; + final DefaultStyles? customStyles; final bool expands; final TextCapitalization textCapitalization; final Brightness keyboardAppearance; - final ScrollPhysics scrollPhysics; - final ValueChanged onLaunchUrl; - final EmbedBuilder embedBuilder; + final ScrollPhysics? scrollPhysics; + final ValueChanged? onLaunchUrl; + final EmbedBuilder? embedBuilder; QuillEditor( - {@required this.controller, - @required this.focusNode, - @required this.scrollController, - @required this.scrollable, - @required this.padding, - @required this.autoFocus, + {required this.controller, + required this.focusNode, + required this.scrollController, + required this.scrollable, + required this.padding, + required this.autoFocus, this.showCursor, - @required this.readOnly, + required this.readOnly, this.placeholder, this.enableInteractiveSelection, this.minHeight, this.maxHeight, this.customStyles, - @required this.expands, + required this.expands, this.textCapitalization = TextCapitalization.sentences, this.keyboardAppearance = Brightness.light, this.scrollPhysics, this.onLaunchUrl, this.embedBuilder = - kIsWeb ? _defaultEmbedBuilderWeb : _defaultEmbedBuilder}) - : assert(controller != null), - assert(scrollController != null), - assert(scrollable != null), - assert(focusNode != null), - assert(autoFocus != null), - assert(readOnly != null), - assert(embedBuilder != null); + kIsWeb ? _defaultEmbedBuilderWeb : _defaultEmbedBuilder}); factory QuillEditor.basic( - {@required QuillController controller, bool readOnly}) { + {required QuillController controller, required bool readOnly}) { return QuillEditor( controller: controller, scrollController: ScrollController(), @@ -210,7 +204,7 @@ class QuillEditor extends StatefulWidget { class _QuillEditorState extends State implements EditorTextSelectionGestureDetectorBuilderDelegate { final GlobalKey _editorKey = GlobalKey(); - EditorTextSelectionGestureDetectorBuilder _selectionGestureDetectorBuilder; + EditorTextSelectionGestureDetectorBuilder? _selectionGestureDetectorBuilder; @override void initState() { @@ -227,10 +221,10 @@ class _QuillEditorState extends State TextSelectionControls textSelectionControls; bool paintCursorAboveText; bool cursorOpacityAnimates; - Offset cursorOffset; - Color cursorColor; + Offset? cursorOffset; + Color? cursorColor; Color selectionColor; - Radius cursorRadius; + Radius? cursorRadius; switch (theme.platform) { case TargetPlatform.android: @@ -262,7 +256,7 @@ class _QuillEditorState extends State throw UnimplementedError(); } - return _selectionGestureDetectorBuilder.build( + return _selectionGestureDetectorBuilder!.build( HitTestBehavior.translucent, RawEditor( _editorKey, @@ -272,7 +266,7 @@ class _QuillEditorState extends State widget.scrollable, widget.padding, widget.readOnly, - widget.placeholder, + widget.placeholder!, widget.onLaunchUrl, ToolbarOptions( copy: widget.enableInteractiveSelection ?? true, @@ -293,17 +287,17 @@ class _QuillEditorState extends State opacityAnimates: cursorOpacityAnimates, ), widget.textCapitalization, - widget.maxHeight, - widget.minHeight, + widget.maxHeight ?? double.maxFinite, + widget.minHeight ?? 0.0, widget.customStyles, widget.expands, widget.autoFocus, selectionColor, textSelectionControls, widget.keyboardAppearance, - widget.enableInteractiveSelection, + widget.enableInteractiveSelection!, widget.scrollPhysics, - widget.embedBuilder), + widget.embedBuilder!), ); } @@ -319,11 +313,11 @@ class _QuillEditorState extends State @override bool getSelectionEnabled() { - return widget.enableInteractiveSelection; + return widget.enableInteractiveSelection!; } _requestKeyboard() { - _editorKey.currentState.requestKeyboard(); + _editorKey.currentState!.requestKeyboard(); } } @@ -337,7 +331,7 @@ class _QuillEditorSelectionGestureDetectorBuilder onForcePressStart(ForcePressDetails details) { super.onForcePressStart(details); if (delegate.getSelectionEnabled() && shouldShowSelectionToolbar) { - getEditor().showToolbar(); + getEditor()?.showToolbar(); } } @@ -352,7 +346,7 @@ class _QuillEditorSelectionGestureDetectorBuilder switch (Theme.of(_state.context).platform) { case TargetPlatform.iOS: case TargetPlatform.macOS: - getRenderEditor().selectPositionAt( + getRenderEditor()?.selectPositionAt( details.globalPosition, null, SelectionChangedCause.longPress, @@ -362,7 +356,7 @@ class _QuillEditorSelectionGestureDetectorBuilder case TargetPlatform.fuchsia: case TargetPlatform.linux: case TargetPlatform.windows: - getRenderEditor().selectWordsInRange( + getRenderEditor()?.selectWordsInRange( details.globalPosition - details.offsetFromOrigin, details.globalPosition, SelectionChangedCause.longPress, @@ -378,59 +372,60 @@ class _QuillEditorSelectionGestureDetectorBuilder return false; } TextPosition pos = - getRenderEditor().getPositionForOffset(details.globalPosition); + getRenderEditor()!.getPositionForOffset(details.globalPosition); containerNode.ChildQuery result = - getEditor().widget.controller.document.queryChild(pos.offset); + getEditor()!.widget.controller.document.queryChild(pos.offset); if (result.node == null) { return false; } Line line = result.node as Line; containerNode.ChildQuery segmentResult = - line.queryChild(result.offset, false); + line.queryChild(result.offset!, false); if (segmentResult.node == null) { if (line.length == 1) { // tapping when no text yet on this line _flipListCheckbox(pos, line, segmentResult); - getEditor().widget.controller.updateSelection( + getEditor()?.widget.controller.updateSelection( TextSelection.collapsed(offset: pos.offset), ChangeSource.LOCAL); return true; } return false; } leaf.Leaf segment = segmentResult.node as leaf.Leaf; - if (segment.style.containsKey(Attribute.link.key)) { - var launchUrl = getEditor().widget.onLaunchUrl; + if (segment.style.containsKey(Attribute.link.key!)) { + var launchUrl = getEditor()!.widget.onLaunchUrl; if (launchUrl == null) { launchUrl = _launchUrl; } - String link = segment.style.attributes[Attribute.link.key].value; - if (getEditor().widget.readOnly && link != null) { + String? link = segment.style.attributes[Attribute.link.key]!.value; + if (getEditor()!.widget.readOnly && link != null) { link = link.trim(); if (!linkPrefixes - .any((linkPrefix) => link.toLowerCase().startsWith(linkPrefix))) { + .any((linkPrefix) => link!.toLowerCase().startsWith(linkPrefix))) { link = 'https://$link'; } launchUrl(link); } return false; } - if (getEditor().widget.readOnly && segment.value is BlockEmbed) { + if (getEditor()!.widget.readOnly && segment.value is BlockEmbed) { BlockEmbed blockEmbed = segment.value as BlockEmbed; if (blockEmbed.type == 'image') { final String imageUrl = blockEmbed.data; Navigator.push( - getEditor().context, + getEditor()!.context, MaterialPageRoute( builder: (context) => ImageTapWrapper( imageProvider: imageUrl.startsWith('http') ? NetworkImage(imageUrl) : isBase64(imageUrl) - ? Image.memory(base64.decode(imageUrl)) + ? (Image.memory(base64.decode(imageUrl)) + as ImageProvider) : FileImage(io.File(imageUrl)), ), ), ); - } + } //ImageProvider? return false; } if (_flipListCheckbox(pos, line, segmentResult)) { @@ -441,25 +436,25 @@ class _QuillEditorSelectionGestureDetectorBuilder bool _flipListCheckbox( TextPosition pos, Line line, containerNode.ChildQuery segmentResult) { - if (getEditor().widget.readOnly || - !line.style.containsKey(Attribute.list.key) || + if (getEditor()!.widget.readOnly || + !line.style.containsKey(Attribute.list.key!) || segmentResult.offset != 0) { return false; } // segmentResult.offset == 0 means tap at the beginning of the TextLine - String listVal = line.style.attributes[Attribute.list.key].value; + String listVal = line.style.attributes[Attribute.list.key]!.value; if (listVal == Attribute.unchecked.value) { - getEditor() + getEditor()! .widget .controller .formatText(pos.offset, 0, Attribute.checked); } else if (listVal == Attribute.checked.value) { - getEditor() + getEditor()! .widget .controller .formatText(pos.offset, 0, Attribute.unchecked); } - getEditor().widget.controller.updateSelection( + getEditor()!.widget.controller.updateSelection( TextSelection.collapsed(offset: pos.offset), ChangeSource.LOCAL); return true; } @@ -470,7 +465,7 @@ class _QuillEditorSelectionGestureDetectorBuilder @override onSingleTapUp(TapUpDetails details) { - getEditor().hideToolbar(); + getEditor()!.hideToolbar(); bool positionSelected = _onTapping(details); @@ -482,11 +477,11 @@ class _QuillEditorSelectionGestureDetectorBuilder case PointerDeviceKind.mouse: case PointerDeviceKind.stylus: case PointerDeviceKind.invertedStylus: - getRenderEditor().selectPosition(SelectionChangedCause.tap); + getRenderEditor()!.selectPosition(SelectionChangedCause.tap); break; case PointerDeviceKind.touch: case PointerDeviceKind.unknown: - getRenderEditor().selectWordEdge(SelectionChangedCause.tap); + getRenderEditor()!.selectWordEdge(SelectionChangedCause.tap); break; } break; @@ -494,7 +489,7 @@ class _QuillEditorSelectionGestureDetectorBuilder case TargetPlatform.fuchsia: case TargetPlatform.linux: case TargetPlatform.windows: - getRenderEditor().selectPosition(SelectionChangedCause.tap); + getRenderEditor()!.selectPosition(SelectionChangedCause.tap); break; } } @@ -507,7 +502,7 @@ class _QuillEditorSelectionGestureDetectorBuilder switch (Theme.of(_state.context).platform) { case TargetPlatform.iOS: case TargetPlatform.macOS: - getRenderEditor().selectPositionAt( + getRenderEditor()!.selectPositionAt( details.globalPosition, null, SelectionChangedCause.longPress, @@ -517,7 +512,7 @@ class _QuillEditorSelectionGestureDetectorBuilder case TargetPlatform.fuchsia: case TargetPlatform.linux: case TargetPlatform.windows: - getRenderEditor().selectWord(SelectionChangedCause.longPress); + getRenderEditor()!.selectWord(SelectionChangedCause.longPress); Feedback.forLongPress(_state.context); break; default: @@ -537,7 +532,7 @@ class RenderEditor extends RenderEditableContainerBox bool _hasFocus = false; LayerLink _startHandleLayerLink; LayerLink _endHandleLayerLink; - TextSelectionChangedHandler onSelectionChanged; + TextSelectionChangedHandler? onSelectionChanged; final ValueNotifier _selectionStartInViewport = ValueNotifier(true); @@ -548,7 +543,7 @@ class RenderEditor extends RenderEditableContainerBox final ValueNotifier _selectionEndInViewport = ValueNotifier(true); RenderEditor( - List children, + List? children, TextDirection textDirection, EdgeInsetsGeometry padding, this.document, @@ -558,11 +553,7 @@ class RenderEditor extends RenderEditableContainerBox this._startHandleLayerLink, this._endHandleLayerLink, EdgeInsets floatingCursorAddedMargin) - : assert(document != null), - assert(textDirection != null), - assert(_hasFocus != null), - assert(floatingCursorAddedMargin != null), - super( + : super( children, document.root, textDirection, @@ -570,7 +561,6 @@ class RenderEditor extends RenderEditableContainerBox ); setDocument(Document doc) { - assert(doc != null); if (document == doc) { return; } @@ -579,7 +569,6 @@ class RenderEditor extends RenderEditableContainerBox } setHasFocus(bool h) { - assert(h != null); if (_hasFocus == h) { return; } @@ -614,15 +603,13 @@ class RenderEditor extends RenderEditableContainerBox @override List getEndpointsForSelection( TextSelection textSelection) { - assert(constraints != null); - if (textSelection.isCollapsed) { RenderEditableBox child = childAtPosition(textSelection.extent); TextPosition localPosition = TextPosition( offset: textSelection.extentOffset - child.getContainer().getOffset()); Offset localOffset = child.getOffsetForCaret(localPosition); - BoxParentData parentData = child.parentData; + BoxParentData parentData = (child.parentData as BoxParentData); return [ TextSelectionPoint( Offset(0.0, child.preferredLineHeight(localPosition)) + @@ -632,7 +619,7 @@ class RenderEditor extends RenderEditableContainerBox ]; } - Node baseNode = _container.queryChild(textSelection.start, false).node; + Node? baseNode = _container.queryChild(textSelection.start, false).node; var baseChild = firstChild; while (baseChild != null) { @@ -643,7 +630,7 @@ class RenderEditor extends RenderEditableContainerBox } assert(baseChild != null); - BoxParentData baseParentData = baseChild.parentData; + BoxParentData baseParentData = (baseChild!.parentData as BoxParentData); TextSelection baseSelection = localSelection(baseChild.getContainer(), textSelection, true); TextSelectionPoint basePoint = @@ -651,17 +638,20 @@ class RenderEditor extends RenderEditableContainerBox basePoint = TextSelectionPoint( basePoint.point + baseParentData.offset, basePoint.direction); - Node extentNode = _container.queryChild(textSelection.end, false).node; + Node? extentNode = _container.queryChild(textSelection.end, false).node; var extentChild = baseChild; + //This may not work as intended with null-safety. + // ignore: unnecessary_null_comparison while (extentChild != null) { if (extentChild.getContainer() == extentNode) { break; } - extentChild = childAfter(extentChild); + extentChild = (childAfter(extentChild) as RenderEditableBox); } + // ignore: unnecessary_null_comparison assert(extentChild != null); - BoxParentData extentParentData = extentChild.parentData; + BoxParentData extentParentData = (extentChild.parentData as BoxParentData); TextSelection extentSelection = localSelection(extentChild.getContainer(), textSelection, true); TextSelectionPoint extentPoint = @@ -672,7 +662,7 @@ class RenderEditor extends RenderEditableContainerBox return [basePoint, extentPoint]; } - Offset _lastTapDownPosition; + Offset? _lastTapDownPosition; @override handleTapDown(TapDownDetails details) { @@ -682,11 +672,9 @@ class RenderEditor extends RenderEditableContainerBox @override selectWordsInRange( Offset from, - Offset to, + Offset? to, SelectionChangedCause cause, ) { - assert(cause != null); - assert(from != null); if (onSelectionChanged == null) { return; } @@ -718,18 +706,17 @@ class RenderEditor extends RenderEditableContainerBox return; } if (onSelectionChanged != null) { - onSelectionChanged(nextSelection, cause); + onSelectionChanged!(nextSelection, cause); } } @override selectWordEdge(SelectionChangedCause cause) { - assert(cause != null); assert(_lastTapDownPosition != null); if (onSelectionChanged == null) { return; } - TextPosition position = getPositionForOffset(_lastTapDownPosition); + TextPosition position = getPositionForOffset(_lastTapDownPosition!); RenderEditableBox child = childAtPosition(position); int nodeOffset = child.getContainer().getOffset(); TextPosition localPosition = TextPosition( @@ -759,16 +746,14 @@ class RenderEditor extends RenderEditableContainerBox @override selectPositionAt( Offset from, - Offset to, + Offset? to, SelectionChangedCause cause, ) { - assert(cause != null); - assert(from != null); if (onSelectionChanged == null) { return; } TextPosition fromPosition = getPositionForOffset(from); - TextPosition toPosition = to == null ? null : getPositionForOffset(to); + TextPosition? toPosition = to == null ? null : getPositionForOffset(to); int baseOffset = fromPosition.offset; int extentOffset = fromPosition.offset; @@ -787,12 +772,12 @@ class RenderEditor extends RenderEditableContainerBox @override selectWord(SelectionChangedCause cause) { - selectWordsInRange(_lastTapDownPosition, null, cause); + selectWordsInRange(_lastTapDownPosition!, null, cause); } @override selectPosition(SelectionChangedCause cause) { - selectPositionAt(_lastTapDownPosition, null, cause); + selectPositionAt(_lastTapDownPosition!, null, cause); } @override @@ -837,7 +822,7 @@ class RenderEditor extends RenderEditableContainerBox } @override - bool hitTestChildren(BoxHitTestResult result, {Offset position}) { + bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { return defaultHitTestChildren(result, position: position); } @@ -877,9 +862,9 @@ class RenderEditor extends RenderEditableContainerBox @override TextPosition getPositionForOffset(Offset offset) { Offset local = globalToLocal(offset); - RenderEditableBox child = childAtOffset(local); + RenderEditableBox child = childAtOffset(local)!; - BoxParentData parentData = child.parentData; + BoxParentData parentData = (child.parentData as BoxParentData); Offset localOffset = local - parentData.offset; TextPosition localPosition = child.getPositionForOffset(localOffset); return TextPosition( @@ -888,7 +873,7 @@ class RenderEditor extends RenderEditableContainerBox ); } - double getOffsetToRevealCursor( + double? getOffsetToRevealCursor( double viewportHeight, double scrollOffset, double offsetInViewport) { List endpoints = getEndpointsForSelection(selection); TextSelectionPoint endpoint = endpoints.first; @@ -902,7 +887,7 @@ class RenderEditor extends RenderEditableContainerBox kMargin + offsetInViewport; final caretBottom = endpoint.point.dy + kMargin + offsetInViewport; - double dy; + double? dy; if (caretTop < scrollOffset) { dy = caretTop; } else if (caretBottom > scrollOffset + viewportHeight) { @@ -927,15 +912,14 @@ class RenderEditableContainerBox extends RenderBox containerNode.Container _container; TextDirection textDirection; EdgeInsetsGeometry _padding; - EdgeInsets _resolvedPadding; + EdgeInsets? _resolvedPadding; - RenderEditableContainerBox(List children, this._container, + RenderEditableContainerBox(List? children, this._container, this.textDirection, this._padding) - : assert(_container != null), - assert(textDirection != null), - assert(_padding != null), - assert(_padding.isNonNegative) { - addAll(children); + : assert(_padding.isNonNegative) { + if (children != null) { + addAll(children); + } } containerNode.Container getContainer() { @@ -943,7 +927,6 @@ class RenderEditableContainerBox extends RenderBox } setContainer(containerNode.Container c) { - assert(c != null); if (_container == c) { return; } @@ -954,7 +937,6 @@ class RenderEditableContainerBox extends RenderBox EdgeInsetsGeometry getPadding() => _padding; setPadding(EdgeInsetsGeometry value) { - assert(value != null); assert(value.isNonNegative); if (_padding == value) { return; @@ -963,22 +945,22 @@ class RenderEditableContainerBox extends RenderBox _markNeedsPaddingResolution(); } - EdgeInsets get resolvedPadding => _resolvedPadding; + EdgeInsets? get resolvedPadding => _resolvedPadding; _resolvePadding() { if (_resolvedPadding != null) { return; } _resolvedPadding = _padding.resolve(textDirection); - _resolvedPadding = _resolvedPadding.copyWith(left: _resolvedPadding.left); + _resolvedPadding = _resolvedPadding!.copyWith(left: _resolvedPadding!.left); - assert(_resolvedPadding.isNonNegative); + assert(_resolvedPadding!.isNonNegative); } RenderEditableBox childAtPosition(TextPosition position) { assert(firstChild != null); - Node targetNode = _container.queryChild(position.offset, false).node; + Node? targetNode = _container.queryChild(position.offset, false).node; var targetChild = firstChild; while (targetChild != null) { @@ -998,19 +980,19 @@ class RenderEditableContainerBox extends RenderBox markNeedsLayout(); } - RenderEditableBox childAtOffset(Offset offset) { + RenderEditableBox? childAtOffset(Offset offset) { assert(firstChild != null); _resolvePadding(); - if (offset.dy <= _resolvedPadding.top) { + if (offset.dy <= _resolvedPadding!.top) { return firstChild; } - if (offset.dy >= size.height - _resolvedPadding.bottom) { + if (offset.dy >= size.height - _resolvedPadding!.bottom) { return lastChild; } var child = firstChild; - double dx = -offset.dx, dy = _resolvedPadding.top; + double dx = -offset.dx, dy = _resolvedPadding!.top; while (child != null) { if (child.size.contains(offset.translate(dx, -dy))) { return child; @@ -1037,20 +1019,21 @@ class RenderEditableContainerBox extends RenderBox _resolvePadding(); assert(_resolvedPadding != null); - double mainAxisExtent = _resolvedPadding.top; + double mainAxisExtent = _resolvedPadding!.top; var child = firstChild; BoxConstraints innerConstraints = BoxConstraints.tightFor(width: constraints.maxWidth) - .deflate(_resolvedPadding); + .deflate(_resolvedPadding!); while (child != null) { child.layout(innerConstraints, parentUsesSize: true); - final EditableContainerParentData childParentData = child.parentData; - childParentData.offset = Offset(_resolvedPadding.left, mainAxisExtent); + final EditableContainerParentData childParentData = + (child.parentData as EditableContainerParentData); + childParentData.offset = Offset(_resolvedPadding!.left, mainAxisExtent); mainAxisExtent += child.size.height; assert(child.parentData == childParentData); child = childParentData.nextSibling; } - mainAxisExtent += _resolvedPadding.bottom; + mainAxisExtent += _resolvedPadding!.bottom; size = constraints.constrain(Size(constraints.maxWidth, mainAxisExtent)); assert(size.isFinite); @@ -1061,7 +1044,8 @@ class RenderEditableContainerBox extends RenderBox var child = firstChild; while (child != null) { extent = math.max(extent, childSize(child)); - EditableContainerParentData childParentData = child.parentData; + EditableContainerParentData childParentData = + (child.parentData as EditableContainerParentData); child = childParentData.nextSibling; } return extent; @@ -1072,7 +1056,8 @@ class RenderEditableContainerBox extends RenderBox var child = firstChild; while (child != null) { extent += childSize(child); - EditableContainerParentData childParentData = child.parentData; + EditableContainerParentData childParentData = + (child.parentData as EditableContainerParentData); child = childParentData.nextSibling; } return extent; @@ -1083,10 +1068,10 @@ class RenderEditableContainerBox extends RenderBox _resolvePadding(); return _getIntrinsicCrossAxis((RenderBox child) { double childHeight = math.max( - 0.0, height - _resolvedPadding.top + _resolvedPadding.bottom); + 0.0, height - _resolvedPadding!.top + _resolvedPadding!.bottom); return child.getMinIntrinsicWidth(childHeight) + - _resolvedPadding.left + - _resolvedPadding.right; + _resolvedPadding!.left + + _resolvedPadding!.right; }); } @@ -1095,10 +1080,10 @@ class RenderEditableContainerBox extends RenderBox _resolvePadding(); return _getIntrinsicCrossAxis((RenderBox child) { double childHeight = math.max( - 0.0, height - _resolvedPadding.top + _resolvedPadding.bottom); + 0.0, height - _resolvedPadding!.top + _resolvedPadding!.bottom); return child.getMaxIntrinsicWidth(childHeight) + - _resolvedPadding.left + - _resolvedPadding.right; + _resolvedPadding!.left + + _resolvedPadding!.right; }); } @@ -1106,11 +1091,11 @@ class RenderEditableContainerBox extends RenderBox double computeMinIntrinsicHeight(double width) { _resolvePadding(); return _getIntrinsicMainAxis((RenderBox child) { - double childWidth = - math.max(0.0, width - _resolvedPadding.left + _resolvedPadding.right); + double childWidth = math.max( + 0.0, width - _resolvedPadding!.left + _resolvedPadding!.right); return child.getMinIntrinsicHeight(childWidth) + - _resolvedPadding.top + - _resolvedPadding.bottom; + _resolvedPadding!.top + + _resolvedPadding!.bottom; }); } @@ -1118,18 +1103,18 @@ class RenderEditableContainerBox extends RenderBox double computeMaxIntrinsicHeight(double width) { _resolvePadding(); return _getIntrinsicMainAxis((RenderBox child) { - final childWidth = - math.max(0.0, width - _resolvedPadding.left + _resolvedPadding.right); + final childWidth = math.max( + 0.0, width - _resolvedPadding!.left + _resolvedPadding!.right); return child.getMaxIntrinsicHeight(childWidth) + - _resolvedPadding.top + - _resolvedPadding.bottom; + _resolvedPadding!.top + + _resolvedPadding!.bottom; }); } @override double computeDistanceToActualBaseline(TextBaseline baseline) { _resolvePadding(); - return defaultComputeDistanceToFirstActualBaseline(baseline) + - _resolvedPadding.top; + return defaultComputeDistanceToFirstActualBaseline(baseline)! + + _resolvedPadding!.top; } } diff --git a/lib/widgets/image.dart b/lib/widgets/image.dart index 2a6785f0..b9df48ce 100644 --- a/lib/widgets/image.dart +++ b/lib/widgets/image.dart @@ -8,7 +8,7 @@ class ImageTapWrapper extends StatelessWidget { this.imageProvider, }); - final ImageProvider imageProvider; + final ImageProvider? imageProvider; @override Widget build(BuildContext context) { diff --git a/lib/widgets/keyboard_listener.dart b/lib/widgets/keyboard_listener.dart index 329132ab..1ec60c75 100644 --- a/lib/widgets/keyboard_listener.dart +++ b/lib/widgets/keyboard_listener.dart @@ -58,10 +58,7 @@ class KeyboardListener { LogicalKeyboardKey.keyA: InputShortcut.SELECT_ALL, }; - KeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete) - : assert(onCursorMove != null), - assert(onShortcut != null), - assert(onDelete != null); + KeyboardListener(this.onCursorMove, this.onShortcut, this.onDelete); bool handleRawKeyEvent(RawKeyEvent event) { if (event is! RawKeyDownEvent) { @@ -90,7 +87,7 @@ class KeyboardListener { } else if (isMacOS ? event.isMetaPressed : event.isControlPressed && _shortcutKeys.contains(key)) { - onShortcut(_keyToShortcut[key]); + onShortcut(_keyToShortcut[key]!); } else if (key == LogicalKeyboardKey.delete) { onDelete(true); } else if (key == LogicalKeyboardKey.backspace) { diff --git a/lib/widgets/proxy.dart b/lib/widgets/proxy.dart index b710e8d3..9e665354 100644 --- a/lib/widgets/proxy.dart +++ b/lib/widgets/proxy.dart @@ -7,8 +7,12 @@ class BaselineProxy extends SingleChildRenderObjectWidget { final TextStyle textStyle; final EdgeInsets padding; - BaselineProxy({Key key, Widget child, this.textStyle, this.padding}) - : super(key: key, child: child); + BaselineProxy({ + Key? key, + Widget? child, + required this.textStyle, + required this.padding, + }) : super(key: key, child: child); @override RenderBaselineProxy createRenderObject(BuildContext context) { @@ -30,9 +34,9 @@ class BaselineProxy extends SingleChildRenderObjectWidget { class RenderBaselineProxy extends RenderProxyBox { RenderBaselineProxy( - RenderParagraph child, + RenderParagraph? child, TextStyle textStyle, - EdgeInsets padding, + EdgeInsets? padding, ) : _prototypePainter = TextPainter( text: TextSpan(text: ' ', style: textStyle), textDirection: TextDirection.ltr, @@ -43,18 +47,16 @@ class RenderBaselineProxy extends RenderProxyBox { final TextPainter _prototypePainter; set textStyle(TextStyle value) { - assert(value != null); - if (_prototypePainter.text.style == value) { + if (_prototypePainter.text!.style == value) { return; } _prototypePainter.text = TextSpan(text: ' ', style: value); markNeedsLayout(); } - EdgeInsets _padding; + EdgeInsets? _padding; set padding(EdgeInsets value) { - assert(value != null); if (_padding == value) { return; } @@ -65,8 +67,7 @@ class RenderBaselineProxy extends RenderProxyBox { @override double computeDistanceToActualBaseline(TextBaseline baseline) => _prototypePainter.computeDistanceToActualBaseline(baseline) + - _padding?.top ?? - 0.0; + (_padding == null ? 0.0 : _padding!.top); @override performLayout() { @@ -84,7 +85,7 @@ class EmbedProxy extends SingleChildRenderObjectWidget { } class RenderEmbedProxy extends RenderProxyBox implements RenderContentProxyBox { - RenderEmbedProxy(RenderBox child) : super(child); + RenderEmbedProxy(RenderBox? child) : super(child); @override List getBoxesForSelection(TextSelection selection) { @@ -106,9 +107,7 @@ class RenderEmbedProxy extends RenderProxyBox implements RenderContentProxyBox { @override Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) { - assert(position.offset != null && - position.offset <= 1 && - position.offset >= 0); + assert(position.offset <= 1 && position.offset >= 0); return position.offset == 0 ? Offset.zero : Offset(size.width, 0.0); } @@ -134,7 +133,7 @@ class RichTextProxy extends SingleChildRenderObjectWidget { final Locale locale; final StrutStyle strutStyle; final TextWidthBasis textWidthBasis; - final TextHeightBehavior textHeightBehavior; + final TextHeightBehavior? textHeightBehavior; @override RenderParagraphProxy createRenderObject(BuildContext context) { @@ -160,17 +159,13 @@ class RichTextProxy extends SingleChildRenderObjectWidget { this.strutStyle, this.textWidthBasis, this.textHeightBehavior) - : assert(child != null), - assert(textStyle != null), - assert(textAlign != null), - assert(textDirection != null), - assert(locale != null), - assert(strutStyle != null), - super(child: child); + : super(child: child); @override void updateRenderObject( - BuildContext context, covariant RenderParagraphProxy renderObject) { + BuildContext context, + covariant RenderParagraphProxy renderObject, + ) { renderObject.textStyle = textStyle; renderObject.textAlign = textAlign; renderObject.textDirection = textDirection; @@ -178,14 +173,16 @@ class RichTextProxy extends SingleChildRenderObjectWidget { renderObject.locale = locale; renderObject.strutStyle = strutStyle; renderObject.textWidthBasis = textWidthBasis; - renderObject.textHeightBehavior = textHeightBehavior; + if (textHeightBehavior != null) { + renderObject.textHeightBehavior = textHeightBehavior!; + } } } class RenderParagraphProxy extends RenderProxyBox implements RenderContentProxyBox { RenderParagraphProxy( - RenderParagraph child, + RenderParagraph? child, TextStyle textStyle, TextAlign textAlign, TextDirection textDirection, @@ -193,7 +190,7 @@ class RenderParagraphProxy extends RenderProxyBox StrutStyle strutStyle, Locale locale, TextWidthBasis textWidthBasis, - TextHeightBehavior textHeightBehavior, + TextHeightBehavior? textHeightBehavior, ) : _prototypePainter = TextPainter( text: TextSpan(text: ' ', style: textStyle), textAlign: textAlign, @@ -208,8 +205,7 @@ class RenderParagraphProxy extends RenderProxyBox final TextPainter _prototypePainter; set textStyle(TextStyle value) { - assert(value != null); - if (_prototypePainter.text.style == value) { + if (_prototypePainter.text!.style == value) { return; } _prototypePainter.text = TextSpan(text: ' ', style: value); @@ -217,7 +213,6 @@ class RenderParagraphProxy extends RenderProxyBox } set textAlign(TextAlign value) { - assert(value != null); if (_prototypePainter.textAlign == value) { return; } @@ -226,7 +221,6 @@ class RenderParagraphProxy extends RenderProxyBox } set textDirection(TextDirection value) { - assert(value != null); if (_prototypePainter.textDirection == value) { return; } @@ -235,7 +229,6 @@ class RenderParagraphProxy extends RenderProxyBox } set textScaleFactor(double value) { - assert(value != null); if (_prototypePainter.textScaleFactor == value) { return; } @@ -244,7 +237,6 @@ class RenderParagraphProxy extends RenderProxyBox } set strutStyle(StrutStyle value) { - assert(value != null); if (_prototypePainter.strutStyle == value) { return; } @@ -261,7 +253,6 @@ class RenderParagraphProxy extends RenderProxyBox } set textWidthBasis(TextWidthBasis value) { - assert(value != null); if (_prototypePainter.textWidthBasis == value) { return; } @@ -278,7 +269,7 @@ class RenderParagraphProxy extends RenderProxyBox } @override - RenderParagraph get child => super.child; + RenderParagraph? get child => super.child as RenderParagraph?; @override double getPreferredLineHeight() { @@ -287,23 +278,23 @@ class RenderParagraphProxy extends RenderProxyBox @override Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) => - child.getOffsetForCaret(position, caretPrototype); + child!.getOffsetForCaret(position, caretPrototype); @override TextPosition getPositionForOffset(Offset offset) => - child.getPositionForOffset(offset); + child!.getPositionForOffset(offset); @override - double getFullHeightForCaret(TextPosition position) => - child.getFullHeightForCaret(position); + double? getFullHeightForCaret(TextPosition position) => + child!.getFullHeightForCaret(position); @override TextRange getWordBoundary(TextPosition position) => - child.getWordBoundary(position); + child!.getWordBoundary(position); @override List getBoxesForSelection(TextSelection selection) => - child.getBoxesForSelection(selection); + child!.getBoxesForSelection(selection); @override performLayout() { diff --git a/lib/widgets/raw_editor.dart b/lib/widgets/raw_editor.dart index c282d2e5..369f0b06 100644 --- a/lib/widgets/raw_editor.dart +++ b/lib/widgets/raw_editor.dart @@ -32,12 +32,12 @@ import 'keyboard_listener.dart'; class RawEditor extends StatefulWidget { final QuillController controller; final FocusNode focusNode; - final ScrollController scrollController; + final ScrollController? scrollController; final bool scrollable; final EdgeInsetsGeometry padding; final bool readOnly; final String placeholder; - final ValueChanged onLaunchUrl; + final ValueChanged? onLaunchUrl; final ToolbarOptions toolbarOptions; final bool showSelectionHandles; final bool showCursor; @@ -45,14 +45,14 @@ class RawEditor extends StatefulWidget { final TextCapitalization textCapitalization; final double maxHeight; final double minHeight; - final DefaultStyles customStyles; + final DefaultStyles? customStyles; final bool expands; final bool autoFocus; final Color selectionColor; - final TextSelectionControls selectionCtrls; + final TextSelectionControls? selectionCtrls; final Brightness keyboardAppearance; final bool enableInteractiveSelection; - final ScrollPhysics scrollPhysics; + final ScrollPhysics? scrollPhysics; final EmbedBuilder embedBuilder; RawEditor( @@ -67,7 +67,7 @@ class RawEditor extends StatefulWidget { this.onLaunchUrl, this.toolbarOptions, this.showSelectionHandles, - bool showCursor, + bool? showCursor, this.cursorStyle, this.textCapitalization, this.maxHeight, @@ -81,26 +81,10 @@ class RawEditor extends StatefulWidget { this.enableInteractiveSelection, this.scrollPhysics, this.embedBuilder) - : assert(controller != null, 'controller cannot be null'), - assert(focusNode != null, 'focusNode cannot be null'), - assert(scrollable || scrollController != null, - 'scrollController cannot be null'), - assert(selectionColor != null, 'selectionColor cannot be null'), - assert(enableInteractiveSelection != null, - 'enableInteractiveSelection cannot be null'), - assert(showSelectionHandles != null, - 'showSelectionHandles cannot be null'), - assert(readOnly != null, 'readOnly cannot be null'), - 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'), - assert(autoFocus != null, 'autoFocus cannot be null'), - assert(toolbarOptions != null, 'toolbarOptions cannot be null'), + : assert(maxHeight > 0, 'maxHeight cannot be null'), + assert(minHeight >= 0, 'minHeight cannot be null'), + assert(maxHeight >= minHeight, 'maxHeight cannot be null'), showCursor = showCursor ?? !readOnly, - assert(embedBuilder != null, 'embedBuilder cannot be null'), - assert(expands != null, 'expands cannot be null'), - assert(padding != null), super(key: key); @override @@ -117,20 +101,20 @@ class RawEditorState extends EditorState implements TextSelectionDelegate, TextInputClient { final GlobalKey _editorKey = GlobalKey(); final List _sentRemoteValues = []; - TextInputConnection _textInputConnection; - TextEditingValue _lastKnownRemoteTextEditingValue; + TextInputConnection? _textInputConnection; + TextEditingValue? _lastKnownRemoteTextEditingValue; int _cursorResetLocation = -1; bool _wasSelectingVerticallyWithKeyboard = false; - EditorTextSelectionOverlay _selectionOverlay; - FocusAttachment _focusAttachment; - CursorCont _cursorCont; - ScrollController _scrollController; - KeyboardVisibilityController _keyboardVisibilityController; - StreamSubscription _keyboardVisibilitySubscription; - KeyboardListener _keyboardListener; + EditorTextSelectionOverlay? _selectionOverlay; + FocusAttachment? _focusAttachment; + CursorCont? _cursorCont; + ScrollController? _scrollController; + KeyboardVisibilityController? _keyboardVisibilityController; + StreamSubscription? _keyboardVisibilitySubscription; + KeyboardListener? _keyboardListener; bool _didAutoFocus = false; bool _keyboardVisible = false; - DefaultStyles _styles; + DefaultStyles? _styles; final ClipboardStatusNotifier _clipboardStatus = ClipboardStatusNotifier(); final LayerLink _toolbarLayerLink = LayerLink(); final LayerLink _startHandleLayerLink = LayerLink(); @@ -140,7 +124,6 @@ class RawEditorState extends EditorState TextDirection get _textDirection { TextDirection result = Directionality.of(context); - assert(result != null); return result; } @@ -154,7 +137,6 @@ class RawEditorState extends EditorState return; } TextSelection selection = widget.controller.selection; - assert(selection != null); TextSelection newSelection = widget.controller.selection; @@ -210,19 +192,20 @@ class RawEditorState extends EditorState TextPosition originPosition = TextPosition( offset: upKey ? selection.baseOffset : selection.extentOffset); - RenderEditableBox child = getRenderEditor().childAtPosition(originPosition); + RenderEditableBox child = + getRenderEditor()!.childAtPosition(originPosition); TextPosition localPosition = TextPosition( offset: originPosition.offset - child.getContainer().getDocumentOffset()); - TextPosition position = upKey + TextPosition? position = upKey ? child.getPositionAbove(localPosition) : child.getPositionBelow(localPosition); if (position == null) { var sibling = upKey - ? getRenderEditor().childBefore(child) - : getRenderEditor().childAfter(child); + ? getRenderEditor()!.childBefore(child) + : getRenderEditor()!.childAfter(child); if (sibling == null) { position = TextPosition(offset: upKey ? 0 : plainText.length - 1); } else { @@ -273,20 +256,20 @@ class RawEditorState extends EditorState bool shift) { if (wordModifier) { if (leftKey) { - TextSelection textSelection = getRenderEditor().selectWordAtPosition( + TextSelection textSelection = getRenderEditor()!.selectWordAtPosition( TextPosition( offset: _previousCharacter( newSelection.extentOffset, plainText, false))); return newSelection.copyWith(extentOffset: textSelection.baseOffset); } - TextSelection textSelection = getRenderEditor().selectWordAtPosition( + TextSelection textSelection = getRenderEditor()!.selectWordAtPosition( TextPosition( offset: _nextCharacter(newSelection.extentOffset, plainText, false))); return newSelection.copyWith(extentOffset: textSelection.extentOffset); } else if (lineModifier) { if (leftKey) { - TextSelection textSelection = getRenderEditor().selectLineAtPosition( + TextSelection textSelection = getRenderEditor()!.selectLineAtPosition( TextPosition( offset: _previousCharacter( newSelection.extentOffset, plainText, false))); @@ -294,7 +277,7 @@ class RawEditorState extends EditorState } int startPoint = newSelection.extentOffset; if (startPoint < plainText.length) { - TextSelection textSelection = getRenderEditor() + TextSelection textSelection = getRenderEditor()! .selectLineAtPosition(TextPosition(offset: startPoint)); return newSelection.copyWith(extentOffset: textSelection.extentOffset); } @@ -352,7 +335,7 @@ class RawEditorState extends EditorState } int count = 0; - int lastNonWhitespace; + int? lastNonWhitespace; for (String currentString in string.characters) { if (!includeWhitespace && !WHITE_SPACE.contains( @@ -368,7 +351,7 @@ class RawEditorState extends EditorState } bool get hasConnection => - _textInputConnection != null && _textInputConnection.attached; + _textInputConnection != null && _textInputConnection!.attached; openConnectionIfNeeded() { if (widget.readOnly) { @@ -390,17 +373,17 @@ class RawEditorState extends EditorState ), ); - _textInputConnection.setEditingState(_lastKnownRemoteTextEditingValue); + _textInputConnection!.setEditingState(_lastKnownRemoteTextEditingValue!); // _sentRemoteValues.add(_lastKnownRemoteTextEditingValue); } - _textInputConnection.show(); + _textInputConnection!.show(); } closeConnectionIfNeeded() { if (!hasConnection) { return; } - _textInputConnection.close(); + _textInputConnection!.close(); _textInputConnection = null; _lastKnownRemoteTextEditingValue = null; _sentRemoteValues.clear(); @@ -412,7 +395,7 @@ class RawEditorState extends EditorState } TextEditingValue actualValue = textEditingValue.copyWith( - composing: _lastKnownRemoteTextEditingValue.composing, + composing: _lastKnownRemoteTextEditingValue!.composing, ); if (actualValue == _lastKnownRemoteTextEditingValue) { @@ -420,9 +403,9 @@ class RawEditorState extends EditorState } bool shouldRemember = - textEditingValue.text != _lastKnownRemoteTextEditingValue.text; + textEditingValue.text != _lastKnownRemoteTextEditingValue!.text; _lastKnownRemoteTextEditingValue = actualValue; - _textInputConnection.setEditingState(actualValue); + _textInputConnection!.setEditingState(actualValue); if (shouldRemember) { _sentRemoteValues.add(actualValue); } @@ -430,10 +413,10 @@ class RawEditorState extends EditorState @override TextEditingValue get currentTextEditingValue => - _lastKnownRemoteTextEditingValue; + _lastKnownRemoteTextEditingValue!; @override - AutofillScope get currentAutofillScope => null; + AutofillScope? get currentAutofillScope => null; @override void updateEditingValue(TextEditingValue value) { @@ -450,13 +433,14 @@ class RawEditorState extends EditorState return; } - if (_lastKnownRemoteTextEditingValue.text == value.text && - _lastKnownRemoteTextEditingValue.selection == value.selection) { + if (_lastKnownRemoteTextEditingValue!.text == value.text && + _lastKnownRemoteTextEditingValue!.selection == value.selection) { _lastKnownRemoteTextEditingValue = value; return; } - TextEditingValue effectiveLastKnownValue = _lastKnownRemoteTextEditingValue; + TextEditingValue effectiveLastKnownValue = + _lastKnownRemoteTextEditingValue!; _lastKnownRemoteTextEditingValue = value; String oldText = effectiveLastKnownValue.text; String text = value.text; @@ -500,7 +484,7 @@ class RawEditorState extends EditorState if (!hasConnection) { return; } - _textInputConnection.connectionClosedReceived(); + _textInputConnection!.connectionClosedReceived(); _textInputConnection = null; _lastKnownRemoteTextEditingValue = null; _sentRemoteValues.clear(); @@ -509,13 +493,11 @@ class RawEditorState extends EditorState @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - _focusAttachment.reparent(); + _focusAttachment!.reparent(); super.build(context); Document _doc = widget.controller.document; - if (_doc.isEmpty() && - !widget.focusNode.hasFocus && - widget.placeholder != null) { + if (_doc.isEmpty() && !widget.focusNode.hasFocus) { _doc = Document.fromJson(jsonDecode( '[{"attributes":{"placeholder":true},"insert":"${widget.placeholder}\\n"}]')); } @@ -540,9 +522,9 @@ class RawEditorState extends EditorState if (widget.scrollable) { EdgeInsets baselinePadding = - EdgeInsets.only(top: _styles.paragraph.verticalSpacing.item1); + EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1); child = BaselineProxy( - textStyle: _styles.paragraph.style, + textStyle: _styles!.paragraph!.style, padding: baselinePadding, child: SingleChildScrollView( controller: _scrollController, @@ -555,11 +537,10 @@ class RawEditorState extends EditorState BoxConstraints constraints = widget.expands ? BoxConstraints.expand() : BoxConstraints( - minHeight: widget.minHeight ?? 0.0, - maxHeight: widget.maxHeight ?? double.infinity); + minHeight: widget.minHeight, maxHeight: widget.maxHeight); return QuillStyles( - data: _styles, + data: _styles!, child: MouseRegion( cursor: SystemMouseCursors.text, child: Container( @@ -594,17 +575,18 @@ class RawEditorState extends EditorState EditableTextBlock editableTextBlock = EditableTextBlock( node, _textDirection, - _getVerticalSpacingForBlock(node, _styles), + _getVerticalSpacingForBlock(node, _styles!), widget.controller.selection, widget.selectionColor, - _styles, + _styles!, widget.enableInteractiveSelection, _hasFocus, attrs.containsKey(Attribute.codeBlock.key) ? EdgeInsets.all(16.0) - : null, + : EdgeInsets.all( + 0.0), //CANNOT BE NULL - there's an assert in text_block.dart widget.embedBuilder, - _cursorCont, + _cursorCont!, indentLevelCounts); result.add(editableTextBlock); } else { @@ -620,21 +602,21 @@ class RawEditorState extends EditorState line: node, textDirection: _textDirection, embedBuilder: widget.embedBuilder, - styles: _styles, + styles: _styles!, ); EditableTextLine editableTextLine = EditableTextLine( node, null, textLine, 0, - _getVerticalSpacingForLine(node, _styles), + _getVerticalSpacingForLine(node, _styles!), _textDirection, widget.controller.selection, widget.selectionColor, widget.enableInteractiveSelection, _hasFocus, MediaQuery.of(context).devicePixelRatio, - _cursorCont); + _cursorCont!); return editableTextLine; } @@ -642,54 +624,49 @@ class RawEditorState extends EditorState Line line, DefaultStyles defaultStyles) { Map attrs = line.style.attributes; if (attrs.containsKey(Attribute.header.key)) { - int level = attrs[Attribute.header.key].value; + int level = attrs[Attribute.header.key]!.value; switch (level) { case 1: - return defaultStyles.h1.verticalSpacing; + return defaultStyles.h1!.verticalSpacing; case 2: - return defaultStyles.h2.verticalSpacing; + return defaultStyles.h2!.verticalSpacing; case 3: - return defaultStyles.h3.verticalSpacing; + return defaultStyles.h3!.verticalSpacing; default: throw ('Invalid level $level'); } } - return defaultStyles.paragraph.verticalSpacing; + return defaultStyles.paragraph!.verticalSpacing; } Tuple2 _getVerticalSpacingForBlock( Block node, DefaultStyles defaultStyles) { Map attrs = node.style.attributes; if (attrs.containsKey(Attribute.blockQuote.key)) { - return defaultStyles.quote.verticalSpacing; + return defaultStyles.quote!.verticalSpacing; } else if (attrs.containsKey(Attribute.codeBlock.key)) { - return defaultStyles.code.verticalSpacing; + return defaultStyles.code!.verticalSpacing; } else if (attrs.containsKey(Attribute.indent.key)) { - return defaultStyles.indent.verticalSpacing; + return defaultStyles.indent!.verticalSpacing; } - return defaultStyles.lists.verticalSpacing; + return defaultStyles.lists!.verticalSpacing; } @override void initState() { super.initState(); - _clipboardStatus?.addListener(_onChangedClipboardStatus); + _clipboardStatus.addListener(_onChangedClipboardStatus); widget.controller.addListener(_didChangeTextEditingValue); _scrollController = widget.scrollController ?? ScrollController(); - _scrollController.addListener(_updateSelectionOverlayForScroll); + _scrollController!.addListener(_updateSelectionOverlayForScroll); _cursorCont = CursorCont( - show: ValueNotifier(widget.showCursor ?? false), - style: widget.cursorStyle ?? - CursorStyle( - color: Colors.blueAccent, - backgroundColor: Colors.grey, - width: 2.0, - ), + show: ValueNotifier(widget.showCursor), + style: widget.cursorStyle, tickerProvider: this, ); @@ -707,7 +684,7 @@ class RawEditorState extends EditorState } else { _keyboardVisibilityController = KeyboardVisibilityController(); _keyboardVisibilitySubscription = - _keyboardVisibilityController.onChange.listen((bool visible) { + _keyboardVisibilityController!.onChange.listen((bool visible) { _keyboardVisible = visible; if (visible) { _onChangeTextEditingValue(); @@ -716,21 +693,21 @@ class RawEditorState extends EditorState } _focusAttachment = widget.focusNode.attach(context, - onKey: (node, event) => _keyboardListener.handleRawKeyEvent(event)); + onKey: (node, event) => _keyboardListener!.handleRawKeyEvent(event)); widget.focusNode.addListener(_handleFocusChanged); } @override didChangeDependencies() { super.didChangeDependencies(); - DefaultStyles parentStyles = QuillStyles.getStyles(context, true); + DefaultStyles? parentStyles = QuillStyles.getStyles(context, true); DefaultStyles defaultStyles = DefaultStyles.getInstance(context); _styles = (parentStyles != null) ? defaultStyles.merge(parentStyles) : defaultStyles; if (widget.customStyles != null) { - _styles = _styles.merge(widget.customStyles); + _styles = _styles!.merge(widget.customStyles!); } if (!_didAutoFocus && widget.autoFocus) { @@ -743,8 +720,8 @@ class RawEditorState extends EditorState void didUpdateWidget(RawEditor oldWidget) { super.didUpdateWidget(oldWidget); - _cursorCont.show.value = widget.showCursor; - _cursorCont.style = widget.cursorStyle; + _cursorCont!.show.value = widget.showCursor; + _cursorCont!.style = widget.cursorStyle; if (widget.controller != oldWidget.controller) { oldWidget.controller.removeListener(_didChangeTextEditingValue); @@ -754,16 +731,16 @@ class RawEditorState extends EditorState if (widget.scrollController != null && widget.scrollController != _scrollController) { - _scrollController.removeListener(_updateSelectionOverlayForScroll); + _scrollController!.removeListener(_updateSelectionOverlayForScroll); _scrollController = widget.scrollController; - _scrollController.addListener(_updateSelectionOverlayForScroll); + _scrollController!.addListener(_updateSelectionOverlayForScroll); } if (widget.focusNode != oldWidget.focusNode) { oldWidget.focusNode.removeListener(_handleFocusChanged); _focusAttachment?.detach(); _focusAttachment = widget.focusNode.attach(context, - onKey: (node, event) => _keyboardListener.handleRawKeyEvent(event)); + onKey: (node, event) => _keyboardListener!.handleRawKeyEvent(event)); widget.focusNode.addListener(_handleFocusChanged); updateKeepAlive(); } @@ -790,7 +767,6 @@ class RawEditorState extends EditorState handleDelete(bool forward) { TextSelection selection = widget.controller.selection; String plainText = textEditingValue.text; - assert(selection != null); int cursorPosition = selection.start; String textBefore = selection.textBefore(plainText); String textAfter = selection.textAfter(plainText); @@ -820,7 +796,6 @@ class RawEditorState extends EditorState Future handleShortcut(InputShortcut shortcut) async { TextSelection selection = widget.controller.selection; - assert(selection != null); String plainText = textEditingValue.text; if (shortcut == InputShortcut.COPY) { if (!selection.isCollapsed) { @@ -849,13 +824,14 @@ class RawEditorState extends EditorState return; } if (shortcut == InputShortcut.PASTE && !widget.readOnly) { - ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain); + ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); if (data != null) { widget.controller.replaceText( selection.start, selection.end - selection.start, - data.text, - TextSelection.collapsed(offset: selection.start + data.text.length), + data.text as String, + TextSelection.collapsed( + offset: selection.start + (data.text as String).length), ); } return; @@ -881,10 +857,10 @@ class RawEditorState extends EditorState _selectionOverlay = null; widget.controller.removeListener(_didChangeTextEditingValue); widget.focusNode.removeListener(_handleFocusChanged); - _focusAttachment.detach(); - _cursorCont.dispose(); - _clipboardStatus?.removeListener(_onChangedClipboardStatus); - _clipboardStatus?.dispose(); + _focusAttachment!.detach(); + _cursorCont!.dispose(); + _clipboardStatus.removeListener(_onChangedClipboardStatus); + _clipboardStatus.dispose(); super.dispose(); } @@ -909,14 +885,14 @@ class RawEditorState extends EditorState _onChangeTextEditingValue() { _showCaretOnScreen(); updateRemoteValueIfNeeded(); - _cursorCont.startOrStopCursorTimerIfNeeded( - _hasFocus, widget.controller.selection); + _cursorCont! + .startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection); if (hasConnection) { - _cursorCont.stopCursorTimer(resetCharTicks: false); - _cursorCont.startCursorTimer(); + _cursorCont!.stopCursorTimer(resetCharTicks: false); + _cursorCont!.startCursorTimer(); } - SchedulerBinding.instance.addPostFrameCallback( + SchedulerBinding.instance!.addPostFrameCallback( (Duration _) => _updateOrDisposeSelectionOverlayIfNeeded()); if (!mounted) return; setState(() { @@ -928,9 +904,9 @@ class RawEditorState extends EditorState _updateOrDisposeSelectionOverlayIfNeeded() { if (_selectionOverlay != null) { if (_hasFocus) { - _selectionOverlay.update(textEditingValue); + _selectionOverlay!.update(textEditingValue); } else { - _selectionOverlay.dispose(); + _selectionOverlay!.dispose(); _selectionOverlay = null; } } else if (_hasFocus) { @@ -952,22 +928,22 @@ class RawEditorState extends EditorState DragStartBehavior.start, null, _clipboardStatus); - _selectionOverlay.handlesVisible = _shouldShowSelectionHandles(); - _selectionOverlay.showHandles(); + _selectionOverlay!.handlesVisible = _shouldShowSelectionHandles(); + _selectionOverlay!.showHandles(); } } } _handleFocusChanged() { openOrCloseConnection(); - _cursorCont.startOrStopCursorTimerIfNeeded( - _hasFocus, widget.controller.selection); + _cursorCont! + .startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection); _updateOrDisposeSelectionOverlayIfNeeded(); if (_hasFocus) { - WidgetsBinding.instance.addObserver(this); + WidgetsBinding.instance!.addObserver(this); _showCaretOnScreen(); } else { - WidgetsBinding.instance.removeObserver(this); + WidgetsBinding.instance!.removeObserver(this); } updateKeepAlive(); } @@ -988,23 +964,23 @@ class RawEditorState extends EditorState } _showCaretOnScreenScheduled = true; - SchedulerBinding.instance.addPostFrameCallback((Duration _) { + SchedulerBinding.instance!.addPostFrameCallback((Duration _) { _showCaretOnScreenScheduled = false; final viewport = RenderAbstractViewport.of(getRenderEditor()); assert(viewport != null); - final editorOffset = - getRenderEditor().localToGlobal(Offset(0.0, 0.0), ancestor: viewport); - final offsetInViewport = _scrollController.offset + editorOffset.dy; + final editorOffset = getRenderEditor()! + .localToGlobal(Offset(0.0, 0.0), ancestor: viewport); + final offsetInViewport = _scrollController!.offset + editorOffset.dy; - final offset = getRenderEditor().getOffsetToRevealCursor( - _scrollController.position.viewportDimension, - _scrollController.offset, + final offset = getRenderEditor()!.getOffsetToRevealCursor( + _scrollController!.position.viewportDimension, + _scrollController!.offset, offsetInViewport, ); if (offset != null) { - _scrollController.animateTo( + _scrollController!.animateTo( offset, duration: Duration(milliseconds: 100), curve: Curves.fastOutSlowIn, @@ -1014,12 +990,12 @@ class RawEditorState extends EditorState } @override - RenderEditor getRenderEditor() { - return _editorKey.currentContext.findRenderObject(); + RenderEditor? getRenderEditor() { + return _editorKey.currentContext!.findRenderObject() as RenderEditor?; } @override - EditorTextSelectionOverlay getSelectionOverlay() { + EditorTextSelectionOverlay? getSelectionOverlay() { return _selectionOverlay; } @@ -1075,37 +1051,38 @@ class RawEditorState extends EditorState ); } else { final TextEditingValue value = textEditingValue; - final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain); + final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); if (data != null) { final length = textEditingValue.selection.end - textEditingValue.selection.start; widget.controller.replaceText( value.selection.start, length, - data.text, + data.text as String, value.selection, ); // move cursor to the end of pasted text selection widget.controller.updateSelection( TextSelection.collapsed( - offset: value.selection.start + data.text.length), + offset: value.selection.start + (data.text as String).length), ChangeSource.LOCAL); } } } Future __isItCut(TextEditingValue value) async { - final ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain); - return textEditingValue.text.length - value.text.length == data.text.length; + final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); + return textEditingValue.text.length - value.text.length == + (data!.text as String).length; } @override bool showToolbar() { - if (_selectionOverlay == null || _selectionOverlay.toolbar != null) { + if (_selectionOverlay == null || _selectionOverlay!.toolbar != null) { return false; } - _selectionOverlay.showToolbar(); + _selectionOverlay!.showToolbar(); return true; } @@ -1123,15 +1100,15 @@ class RawEditorState extends EditorState class _Editor extends MultiChildRenderObjectWidget { _Editor({ - @required Key key, - @required List children, - @required this.document, - @required this.textDirection, - @required this.hasFocus, - @required this.selection, - @required this.startHandleLayerLink, - @required this.endHandleLayerLink, - @required this.onSelectionChanged, + required Key key, + required List children, + required this.document, + required this.textDirection, + required this.hasFocus, + required this.selection, + required this.startHandleLayerLink, + required this.endHandleLayerLink, + required this.onSelectionChanged, this.padding = EdgeInsets.zero, }) : super(key: key, children: children); diff --git a/lib/widgets/responsive_widget.dart b/lib/widgets/responsive_widget.dart index a047deab..806883ec 100644 --- a/lib/widgets/responsive_widget.dart +++ b/lib/widgets/responsive_widget.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; class ResponsiveWidget extends StatelessWidget { final Widget largeScreen; - final Widget mediumScreen; - final Widget smallScreen; + final Widget? mediumScreen; + final Widget? smallScreen; const ResponsiveWidget( - {Key key, - @required this.largeScreen, + {Key? key, + required this.largeScreen, this.mediumScreen, this.smallScreen}) : super(key: key); diff --git a/lib/widgets/text_block.dart b/lib/widgets/text_block.dart index f0bc6487..698405b2 100644 --- a/lib/widgets/text_block.dart +++ b/lib/widgets/text_block.dart @@ -50,11 +50,11 @@ const List romanNumbers = [ class EditableTextBlock extends StatelessWidget { final Block block; final TextDirection textDirection; - final Tuple2 verticalSpacing; - final TextSelection textSelection; - final Color color; + final Tuple2 verticalSpacing; + final TextSelection? textSelection; + final Color? color; final DefaultStyles styles; - final bool enableInteractiveSelection; + final bool? enableInteractiveSelection; final bool hasFocus; final EdgeInsets contentPadding; final EmbedBuilder embedBuilder; @@ -73,16 +73,13 @@ class EditableTextBlock extends StatelessWidget { this.contentPadding, this.embedBuilder, this.cursorCont, - this.indentLevelCounts) - : assert(hasFocus != null), - assert(embedBuilder != null), - assert(cursorCont != null); + this.indentLevelCounts); @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); - DefaultStyles defaultStyles = QuillStyles.getStyles(context, false); + DefaultStyles? defaultStyles = QuillStyles.getStyles(context, false); return _EditableBlock( block, textDirection, @@ -92,25 +89,28 @@ class EditableTextBlock extends StatelessWidget { _buildChildren(context, this.indentLevelCounts)); } - BoxDecoration _getDecorationForBlock( - Block node, DefaultStyles defaultStyles) { + BoxDecoration? _getDecorationForBlock( + Block node, DefaultStyles? defaultStyles) { + if (defaultStyles == null) { + return null; + } Map attrs = block.style.attributes; if (attrs.containsKey(Attribute.blockQuote.key)) { - return defaultStyles.quote.decoration; + return defaultStyles.quote!.decoration; } if (attrs.containsKey(Attribute.codeBlock.key)) { - return defaultStyles.code.decoration; + return defaultStyles.code!.decoration; } return null; } List _buildChildren( BuildContext context, Map indentLevelCounts) { - DefaultStyles defaultStyles = QuillStyles.getStyles(context, false); + DefaultStyles? defaultStyles = QuillStyles.getStyles(context, false); int count = block.children.length; var children = []; int index = 0; - for (Line line in block.children) { + for (Line line in block.children as List) { index++; EditableTextLine editableTextLine = EditableTextLine( line, @@ -122,11 +122,11 @@ class EditableTextBlock extends StatelessWidget { styles: styles, ), _getIndentWidth(), - _getSpacingForLine(line, index, count, defaultStyles), + _getSpacingForLine(line, index, count, defaultStyles!), textDirection, - textSelection, - color, - enableInteractiveSelection, + textSelection!, + color!, + enableInteractiveSelection!, hasFocus, MediaQuery.of(context).devicePixelRatio, cursorCont); @@ -135,16 +135,16 @@ class EditableTextBlock extends StatelessWidget { return children.toList(growable: false); } - Widget _buildLeading(BuildContext context, Line line, int index, + Widget? _buildLeading(BuildContext context, Line line, int index, Map indentLevelCounts, int count) { - DefaultStyles defaultStyles = QuillStyles.getStyles(context, false); + DefaultStyles? defaultStyles = QuillStyles.getStyles(context, false); Map attrs = line.style.attributes; if (attrs[Attribute.list.key] == Attribute.ol) { return _NumberPoint( index: index, indentLevelCounts: indentLevelCounts, count: count, - style: defaultStyles.paragraph.style, + style: defaultStyles!.paragraph!.style, attrs: attrs, width: 32.0, padding: 8.0, @@ -153,20 +153,20 @@ class EditableTextBlock extends StatelessWidget { if (attrs[Attribute.list.key] == Attribute.ul) { return _BulletPoint( - style: - defaultStyles.paragraph.style.copyWith(fontWeight: FontWeight.bold), + style: defaultStyles!.paragraph!.style + .copyWith(fontWeight: FontWeight.bold), width: 32, ); } if (attrs[Attribute.list.key] == Attribute.checked) { return _Checkbox( - style: defaultStyles.paragraph.style, width: 32, isChecked: true); + style: defaultStyles!.paragraph!.style, width: 32, isChecked: true); } if (attrs[Attribute.list.key] == Attribute.unchecked) { return _Checkbox( - style: defaultStyles.paragraph.style, width: 32, isChecked: false); + style: defaultStyles!.paragraph!.style, width: 32, isChecked: false); } if (attrs.containsKey(Attribute.codeBlock.key)) { @@ -174,8 +174,8 @@ class EditableTextBlock extends StatelessWidget { index: index, indentLevelCounts: indentLevelCounts, count: count, - style: defaultStyles.code.style - .copyWith(color: defaultStyles.code.style.color.withOpacity(0.4)), + style: defaultStyles!.code!.style + .copyWith(color: defaultStyles.code!.style.color!.withOpacity(0.4)), width: 32.0, attrs: attrs, padding: 16.0, @@ -188,7 +188,7 @@ class EditableTextBlock extends StatelessWidget { double _getIndentWidth() { Map attrs = block.style.attributes; - Attribute indent = attrs[Attribute.indent.key]; + Attribute? indent = attrs[Attribute.indent.key]; double extraIndent = 0.0; if (indent != null && indent.value != null) { extraIndent = 16.0 * indent.value; @@ -207,37 +207,37 @@ class EditableTextBlock extends StatelessWidget { Map attrs = block.style.attributes; if (attrs.containsKey(Attribute.header.key)) { - int level = attrs[Attribute.header.key].value; + int level = attrs[Attribute.header.key]!.value; switch (level) { case 1: - top = defaultStyles.h1.verticalSpacing.item1; - bottom = defaultStyles.h1.verticalSpacing.item2; + top = defaultStyles.h1!.verticalSpacing.item1; + bottom = defaultStyles.h1!.verticalSpacing.item2; break; case 2: - top = defaultStyles.h2.verticalSpacing.item1; - bottom = defaultStyles.h2.verticalSpacing.item2; + top = defaultStyles.h2!.verticalSpacing.item1; + bottom = defaultStyles.h2!.verticalSpacing.item2; break; case 3: - top = defaultStyles.h3.verticalSpacing.item1; - bottom = defaultStyles.h3.verticalSpacing.item2; + top = defaultStyles.h3!.verticalSpacing.item1; + bottom = defaultStyles.h3!.verticalSpacing.item2; break; default: throw ('Invalid level $level'); } } else { - Tuple2 lineSpacing; + Tuple2? lineSpacing; if (attrs.containsKey(Attribute.blockQuote.key)) { - lineSpacing = defaultStyles.quote.lineSpacing; + lineSpacing = defaultStyles.quote!.lineSpacing; } else if (attrs.containsKey(Attribute.indent.key)) { - lineSpacing = defaultStyles.indent.lineSpacing; + lineSpacing = defaultStyles.indent!.lineSpacing; } else if (attrs.containsKey(Attribute.list.key)) { - lineSpacing = defaultStyles.lists.lineSpacing; + lineSpacing = defaultStyles.lists!.lineSpacing; } else if (attrs.containsKey(Attribute.codeBlock.key)) { - lineSpacing = defaultStyles.code.lineSpacing; + lineSpacing = defaultStyles.code!.lineSpacing; } else if (attrs.containsKey(Attribute.align.key)) { - lineSpacing = defaultStyles.align.lineSpacing; + lineSpacing = defaultStyles.align!.lineSpacing; } - top = lineSpacing.item1; + top = lineSpacing!.item1; bottom = lineSpacing.item2; } @@ -256,19 +256,14 @@ class EditableTextBlock extends StatelessWidget { class RenderEditableTextBlock extends RenderEditableContainerBox implements RenderEditableBox { RenderEditableTextBlock({ - List children, - @required Block block, - @required TextDirection textDirection, - @required EdgeInsetsGeometry padding, - @required Decoration decoration, + List? children, + required Block block, + required TextDirection textDirection, + required EdgeInsetsGeometry padding, + required Decoration decoration, ImageConfiguration configuration = ImageConfiguration.empty, EdgeInsets contentPadding = EdgeInsets.zero, - }) : assert(block != null), - assert(textDirection != null), - assert(decoration != null), - assert(padding != null), - assert(contentPadding != null), - _decoration = decoration, + }) : _decoration = decoration, _configuration = configuration, _savedPadding = padding, _contentPadding = contentPadding, @@ -283,7 +278,6 @@ class RenderEditableTextBlock extends RenderEditableContainerBox EdgeInsets _contentPadding; set contentPadding(EdgeInsets value) { - assert(value != null); if (_contentPadding == value) return; _contentPadding = value; super.setPadding(_savedPadding.add(_contentPadding)); @@ -295,13 +289,12 @@ class RenderEditableTextBlock extends RenderEditableContainerBox _savedPadding = value; } - BoxPainter _painter; + BoxPainter? _painter; Decoration get decoration => _decoration; Decoration _decoration; set decoration(Decoration value) { - assert(value != null); if (value == _decoration) return; _painter?.dispose(); _painter = null; @@ -313,7 +306,6 @@ class RenderEditableTextBlock extends RenderEditableContainerBox ImageConfiguration _configuration; set configuration(ImageConfiguration value) { - assert(value != null); if (value == _configuration) return; _configuration = value; markNeedsPaint(); @@ -344,8 +336,8 @@ class RenderEditableTextBlock extends RenderEditableContainerBox @override TextPosition getPositionForOffset(Offset offset) { - RenderEditableBox child = childAtOffset(offset); - BoxParentData parentData = child.parentData; + RenderEditableBox? child = childAtOffset(offset); + BoxParentData parentData = child!.parentData as BoxParentData; TextPosition localPosition = child.getPositionForOffset(offset - parentData.offset); return TextPosition( @@ -367,19 +359,19 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } @override - TextPosition getPositionAbove(TextPosition position) { + TextPosition? getPositionAbove(TextPosition position) { assert(position.offset < getContainer().length); RenderEditableBox child = childAtPosition(position); TextPosition childLocalPosition = TextPosition( offset: position.offset - child.getContainer().getOffset()); - TextPosition result = child.getPositionAbove(childLocalPosition); + TextPosition? result = child.getPositionAbove(childLocalPosition); if (result != null) { return TextPosition( offset: result.offset + child.getContainer().getOffset()); } - RenderEditableBox sibling = childBefore(child); + RenderEditableBox? sibling = childBefore(child); if (sibling == null) { return null; } @@ -395,19 +387,19 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } @override - TextPosition getPositionBelow(TextPosition position) { + TextPosition? getPositionBelow(TextPosition position) { assert(position.offset < getContainer().length); RenderEditableBox child = childAtPosition(position); TextPosition childLocalPosition = TextPosition( offset: position.offset - child.getContainer().getOffset()); - TextPosition result = child.getPositionBelow(childLocalPosition); + TextPosition? result = child.getPositionBelow(childLocalPosition); if (result != null) { return TextPosition( offset: result.offset + child.getContainer().getOffset()); } - RenderEditableBox sibling = childAfter(child); + RenderEditableBox? sibling = childAfter(child); if (sibling == null) { return null; } @@ -436,7 +428,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox null); } - Node baseNode = getContainer().queryChild(selection.start, false).node; + Node? baseNode = getContainer().queryChild(selection.start, false).node; var baseChild = firstChild; while (baseChild != null) { if (baseChild.getContainer() == baseNode) { @@ -446,7 +438,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } assert(baseChild != null); - TextSelectionPoint basePoint = baseChild.getBaseEndpointForSelection( + TextSelectionPoint basePoint = baseChild!.getBaseEndpointForSelection( localSelection(baseChild.getContainer(), selection, true)); return TextSelectionPoint( basePoint.point + (baseChild.parentData as BoxParentData).offset, @@ -462,7 +454,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox null); } - Node extentNode = getContainer().queryChild(selection.end, false).node; + Node? extentNode = getContainer().queryChild(selection.end, false).node; var extentChild = firstChild; while (extentChild != null) { @@ -473,7 +465,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } assert(extentChild != null); - TextSelectionPoint extentPoint = extentChild.getExtentEndpointForSelection( + TextSelectionPoint extentPoint = extentChild!.getExtentEndpointForSelection( localSelection(extentChild.getContainer(), selection, true)); return TextSelectionPoint( extentPoint.point + (extentChild.parentData as BoxParentData).offset, @@ -495,11 +487,9 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } _paintDecoration(PaintingContext context, Offset offset) { - assert(size.width != null); - assert(size.height != null); _painter ??= _decoration.createBoxPainter(markNeedsPaint); - EdgeInsets decorationPadding = resolvedPadding - _contentPadding; + EdgeInsets decorationPadding = resolvedPadding! - _contentPadding; ImageConfiguration filledConfiguration = configuration.copyWith(size: decorationPadding.deflateSize(size)); @@ -507,7 +497,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox final decorationOffset = offset.translate(decorationPadding.left, decorationPadding.top); - _painter.paint(context.canvas, decorationOffset, filledConfiguration); + _painter!.paint(context.canvas, decorationOffset, filledConfiguration); if (debugSaveCount != context.canvas.getSaveCount()) { throw ('${_decoration.runtimeType} painter had mismatching save and restore calls.'); } @@ -517,7 +507,7 @@ class RenderEditableTextBlock extends RenderEditableContainerBox } @override - bool hitTestChildren(BoxHitTestResult result, {Offset position}) { + bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { return defaultHitTestChildren(result, position: position); } } @@ -527,16 +517,11 @@ class _EditableBlock extends MultiChildRenderObjectWidget { final TextDirection textDirection; final Tuple2 padding; final Decoration decoration; - final EdgeInsets contentPadding; + final EdgeInsets? contentPadding; _EditableBlock(this.block, this.textDirection, this.padding, this.decoration, this.contentPadding, List children) - : assert(block != null), - assert(textDirection != null), - assert(padding != null), - assert(decoration != null), - assert(children != null), - super(children: children); + : super(children: children); EdgeInsets get _padding => EdgeInsets.only(top: padding.item1, bottom: padding.item2); @@ -576,13 +561,13 @@ class _NumberPoint extends StatelessWidget { final double padding; const _NumberPoint({ - Key key, - @required this.index, - @required this.indentLevelCounts, - @required this.count, - @required this.style, - @required this.width, - @required this.attrs, + Key? key, + required this.index, + required this.indentLevelCounts, + required this.count, + required this.style, + required this.width, + required this.attrs, this.withDot = true, this.padding = 0.0, }) : super(key: key); @@ -602,7 +587,7 @@ class _NumberPoint extends StatelessWidget { ); } if (this.attrs.containsKey(Attribute.indent.key)) { - level = this.attrs[Attribute.indent.key].value; + level = this.attrs[Attribute.indent.key]!.value; } else { // first level but is back from previous indent level // supposed to be "2." @@ -674,9 +659,9 @@ class _BulletPoint extends StatelessWidget { final double width; const _BulletPoint({ - Key key, - @required this.style, - @required this.width, + Key? key, + required this.style, + required this.width, }) : super(key: key); @override @@ -691,23 +676,23 @@ class _BulletPoint extends StatelessWidget { } class _Checkbox extends StatefulWidget { - final TextStyle style; - final double width; - final bool isChecked; + final TextStyle? style; + final double? width; + final bool? isChecked; - const _Checkbox({Key key, this.style, this.width, this.isChecked}) + const _Checkbox({Key? key, this.style, this.width, this.isChecked}) : super(key: key); @override __CheckboxState createState() => __CheckboxState(); } class __CheckboxState extends State<_Checkbox> { - bool isChecked; + bool? isChecked; - void _onCheckboxClicked(bool newValue) => setState(() { + void _onCheckboxClicked(bool? newValue) => setState(() { isChecked = newValue; - if (isChecked) { + if (isChecked!) { // check list } else { // uncheck list diff --git a/lib/widgets/text_line.dart b/lib/widgets/text_line.dart index ffe7ee93..3d5637b2 100644 --- a/lib/widgets/text_line.dart +++ b/lib/widgets/text_line.dart @@ -27,12 +27,13 @@ class TextLine extends StatelessWidget { final EmbedBuilder embedBuilder; final DefaultStyles styles; - const TextLine( - {Key key, this.line, this.textDirection, this.embedBuilder, this.styles}) - : assert(line != null), - assert(embedBuilder != null), - assert(styles != null), - super(key: key); + const TextLine({ + Key? key, + required this.line, + required this.textDirection, + required this.embedBuilder, + required this.styles, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -45,7 +46,7 @@ class TextLine extends StatelessWidget { TextSpan textSpan = _buildTextSpan(context); StrutStyle strutStyle = - StrutStyle.fromTextStyle(textSpan.style, forceStrutHeight: true); + StrutStyle.fromTextStyle(textSpan.style!, forceStrutHeight: true); final textAlign = _getTextAlign(); RichText child = RichText( text: TextSpan(children: [textSpan]), @@ -56,7 +57,7 @@ class TextLine extends StatelessWidget { ); return RichTextProxy( child, - textSpan.style, + textSpan.style!, textAlign, textDirection, 1.0, @@ -88,28 +89,28 @@ class TextLine extends StatelessWidget { TextStyle textStyle = TextStyle(); - if (line.style.containsKey(Attribute.placeholder.key)) { - textStyle = defaultStyles.placeHolder.style; + if (line.style.containsKey(Attribute.placeholder.key!)) { + textStyle = defaultStyles.placeHolder!.style; return TextSpan(children: children, style: textStyle); } - Attribute header = line.style.attributes[Attribute.header.key]; + Attribute? header = line.style.attributes[Attribute.header.key!]; Map m = { - Attribute.h1: defaultStyles.h1.style, - Attribute.h2: defaultStyles.h2.style, - Attribute.h3: defaultStyles.h3.style, + Attribute.h1: defaultStyles.h1!.style, + Attribute.h2: defaultStyles.h2!.style, + Attribute.h3: defaultStyles.h3!.style, }; - textStyle = textStyle.merge(m[header] ?? defaultStyles.paragraph.style); + textStyle = textStyle.merge(m[header] ?? defaultStyles.paragraph!.style); - Attribute block = line.style.getBlockExceptHeader(); - TextStyle toMerge; + Attribute? block = line.style.getBlockExceptHeader(); + TextStyle? toMerge; if (block == Attribute.blockQuote) { - toMerge = defaultStyles.quote.style; + toMerge = defaultStyles.quote!.style; } else if (block == Attribute.codeBlock) { - toMerge = defaultStyles.code.style; + toMerge = defaultStyles.code!.style; } else if (block != null) { - toMerge = defaultStyles.lists.style; + toMerge = defaultStyles.lists!.style; } textStyle = textStyle.merge(toMerge); @@ -123,11 +124,11 @@ class TextLine extends StatelessWidget { TextStyle res = TextStyle(); Map m = { - Attribute.bold.key: defaultStyles.bold, - Attribute.italic.key: defaultStyles.italic, - Attribute.link.key: defaultStyles.link, - Attribute.underline.key: defaultStyles.underline, - Attribute.strikeThrough.key: defaultStyles.strikeThrough, + Attribute.bold.key!: defaultStyles.bold!, + Attribute.italic.key!: defaultStyles.italic!, + Attribute.link.key!: defaultStyles.link!, + Attribute.underline.key!: defaultStyles.underline!, + Attribute.strikeThrough.key!: defaultStyles.strikeThrough!, }; m.forEach((k, s) { if (style.values.any((v) => v.key == k)) { @@ -135,12 +136,12 @@ class TextLine extends StatelessWidget { } }); - Attribute font = textNode.style.attributes[Attribute.font.key]; + Attribute? font = textNode.style.attributes[Attribute.font.key]; if (font != null && font.value != null) { res = res.merge(TextStyle(fontFamily: font.value)); } - Attribute size = textNode.style.attributes[Attribute.size.key]; + Attribute? size = textNode.style.attributes[Attribute.size.key]; if (size != null && size.value != null) { switch (size.value) { case 'small': @@ -153,7 +154,7 @@ class TextLine extends StatelessWidget { res = res.merge(defaultStyles.sizeHuge); break; default: - double fontSize = double.tryParse(size.value); + double? fontSize = double.tryParse(size.value); if (fontSize != null) { res = res.merge(TextStyle(fontSize: fontSize)); } else { @@ -162,13 +163,13 @@ class TextLine extends StatelessWidget { } } - Attribute color = textNode.style.attributes[Attribute.color.key]; + Attribute? color = textNode.style.attributes[Attribute.color.key]; if (color != null && color.value != null) { final textColor = stringToColor(color.value); res = res.merge(new TextStyle(color: textColor)); } - Attribute background = textNode.style.attributes[Attribute.background.key]; + Attribute? background = textNode.style.attributes[Attribute.background.key]; if (background != null && background.value != null) { final backgroundColor = stringToColor(background.value); res = res.merge(new TextStyle(backgroundColor: backgroundColor)); @@ -180,10 +181,10 @@ class TextLine extends StatelessWidget { TextStyle _merge(TextStyle a, TextStyle b) { final decorations = []; if (a.decoration != null) { - decorations.add(a.decoration); + decorations.add(a.decoration!); } if (b.decoration != null) { - decorations.add(b.decoration); + decorations.add(b.decoration!); } return a.merge(b).apply(decoration: TextDecoration.combine(decorations)); } @@ -191,8 +192,8 @@ class TextLine extends StatelessWidget { class EditableTextLine extends RenderObjectWidget { final Line line; - final Widget leading; - final Widget body; + final Widget? leading; + final Widget? body; final double indentWidth; final Tuple2 verticalSpacing; final TextDirection textDirection; @@ -215,14 +216,7 @@ class EditableTextLine extends RenderObjectWidget { this.enableInteractiveSelection, this.hasFocus, this.devicePixelRatio, - this.cursorCont) - : assert(line != null), - assert(indentWidth != null), - assert(textSelection != null), - assert(color != null), - assert(enableInteractiveSelection != null), - assert(hasFocus != null), - assert(cursorCont != null); + this.cursorCont); @override RenderObjectElement createElement() { @@ -268,21 +262,21 @@ class EditableTextLine extends RenderObjectWidget { enum TextLineSlot { LEADING, BODY } class RenderEditableTextLine extends RenderEditableBox { - RenderBox _leading; - RenderContentProxyBox _body; + RenderBox? _leading; + RenderContentProxyBox? _body; Line line; - TextDirection textDirection; - TextSelection textSelection; + TextDirection? textDirection; + TextSelection? textSelection; Color color; - bool enableInteractiveSelection; + bool? enableInteractiveSelection; bool hasFocus = false; double devicePixelRatio; EdgeInsetsGeometry padding; CursorCont cursorCont; - EdgeInsets _resolvedPadding; - bool _containsCursor; - List _selectedRects; - Rect _caretPrototype; + EdgeInsets? _resolvedPadding; + bool? _containsCursor; + List? _selectedRects; + Rect? _caretPrototype; final Map children = {}; RenderEditableTextLine( @@ -295,25 +289,18 @@ class RenderEditableTextLine extends RenderEditableBox { this.padding, this.color, this.cursorCont) - : assert(line != null), - assert(padding != null), - assert(padding.isNonNegative), - assert(devicePixelRatio != null), - assert(hasFocus != null), - assert(color != null), - assert(cursorCont != null); + : assert(padding.isNonNegative); Iterable get _children sync* { if (_leading != null) { - yield _leading; + yield _leading!; } if (_body != null) { - yield _body; + yield _body!; } } setCursorCont(CursorCont c) { - assert(c != null); if (cursorCont == c) { return; } @@ -383,7 +370,6 @@ class RenderEditableTextLine extends RenderEditableBox { } setLine(Line l) { - assert(l != null); if (line == l) { return; } @@ -393,7 +379,6 @@ class RenderEditableTextLine extends RenderEditableBox { } setPadding(EdgeInsetsGeometry p) { - assert(p != null); assert(p.isNonNegative); if (padding == p) { return; @@ -408,20 +393,21 @@ class RenderEditableTextLine extends RenderEditableBox { } setBody(RenderContentProxyBox b) { - _body = _updateChild(_body, b, TextLineSlot.BODY); + _body = _updateChild(_body, b, TextLineSlot.BODY) as RenderContentProxyBox; } bool containsTextSelection() { - return line.getDocumentOffset() <= textSelection.end && - textSelection.start <= line.getDocumentOffset() + line.length - 1; + return line.getDocumentOffset() <= textSelection!.end && + textSelection!.start <= line.getDocumentOffset() + line.length - 1; } bool containsCursor() { - return _containsCursor ??= textSelection.isCollapsed && - line.containsOffset(textSelection.baseOffset); + return _containsCursor ??= textSelection!.isCollapsed && + line.containsOffset(textSelection!.baseOffset); } - RenderBox _updateChild(RenderBox old, RenderBox newChild, TextLineSlot slot) { + RenderBox? _updateChild( + RenderBox? old, RenderBox? newChild, TextLineSlot slot) { if (old != null) { dropChild(old); children.remove(slot); @@ -434,8 +420,8 @@ class RenderEditableTextLine extends RenderEditableBox { } List _getBoxes(TextSelection textSelection) { - BoxParentData parentData = _body.parentData as BoxParentData; - return _body.getBoxesForSelection(textSelection).map((box) { + BoxParentData parentData = _body!.parentData as BoxParentData; + return _body!.getBoxesForSelection(textSelection).map((box) { return TextBox.fromLTRBD( box.left + parentData.offset.dx, box.top + parentData.offset.dy, @@ -451,7 +437,7 @@ class RenderEditableTextLine extends RenderEditableBox { return; } _resolvedPadding = padding.resolve(textDirection); - assert(_resolvedPadding.isNonNegative); + assert(_resolvedPadding!.isNonNegative); } @override @@ -498,26 +484,26 @@ class RenderEditableTextLine extends RenderEditableBox { @override Offset getOffsetForCaret(TextPosition position) { - return _body.getOffsetForCaret(position, _caretPrototype) + - (_body.parentData as BoxParentData).offset; + return _body!.getOffsetForCaret(position, _caretPrototype!) + + (_body!.parentData as BoxParentData).offset; } @override - TextPosition getPositionAbove(TextPosition position) { + TextPosition? getPositionAbove(TextPosition position) { return _getPosition(position, -0.5); } @override - TextPosition getPositionBelow(TextPosition position) { + TextPosition? getPositionBelow(TextPosition position) { return _getPosition(position, 1.5); } - TextPosition _getPosition(TextPosition textPosition, double dyScale) { + TextPosition? _getPosition(TextPosition textPosition, double dyScale) { assert(textPosition.offset < line.length); Offset offset = getOffsetForCaret(textPosition) .translate(0, dyScale * preferredLineHeight(textPosition)); - if (_body.size - .contains(offset - (_body.parentData as BoxParentData).offset)) { + if (_body!.size + .contains(offset - (_body!.parentData as BoxParentData).offset)) { return getPositionForOffset(offset); } return null; @@ -525,18 +511,18 @@ class RenderEditableTextLine extends RenderEditableBox { @override TextPosition getPositionForOffset(Offset offset) { - return _body.getPositionForOffset( - offset - (_body.parentData as BoxParentData).offset); + return _body!.getPositionForOffset( + offset - (_body!.parentData as BoxParentData).offset); } @override TextRange getWordBoundary(TextPosition position) { - return _body.getWordBoundary(position); + return _body!.getWordBoundary(position); } @override double preferredLineHeight(TextPosition position) { - return _body.getPreferredLineHeight(); + return _body!.getPreferredLineHeight(); } @override @@ -550,7 +536,6 @@ class RenderEditableTextLine extends RenderEditableBox { cursorCont.style.height ?? preferredLineHeight(TextPosition(offset: 0)); _computeCaretPrototype() { - assert(defaultTargetPlatform != null); switch (defaultTargetPlatform) { case TargetPlatform.iOS: case TargetPlatform.macOS: @@ -606,14 +591,14 @@ class RenderEditableTextLine extends RenderEditableBox { @override List debugDescribeChildren() { var value = []; - void add(RenderBox child, String name) { + void add(RenderBox? child, String name) { if (child != null) { value.add(child.toDiagnosticsNode(name: name)); } } - add(_leading, 'leading'); - add(_body, 'body'); + add(_leading!, 'leading'); + add(_body!, 'body'); return value; } @@ -623,38 +608,40 @@ class RenderEditableTextLine extends RenderEditableBox { @override double computeMinIntrinsicWidth(double height) { _resolvePadding(); - double horizontalPadding = _resolvedPadding.left + _resolvedPadding.right; - double verticalPadding = _resolvedPadding.top + _resolvedPadding.bottom; + double horizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right; + double verticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom; int leadingWidth = _leading == null ? 0 - : _leading.getMinIntrinsicWidth(height - verticalPadding); + : (_leading!.getMinIntrinsicWidth(height - verticalPadding) as int); int bodyWidth = _body == null ? 0 - : _body.getMinIntrinsicWidth(math.max(0.0, height - verticalPadding)); + : (_body!.getMinIntrinsicWidth(math.max(0.0, height - verticalPadding)) + as int); return horizontalPadding + leadingWidth + bodyWidth; } @override double computeMaxIntrinsicWidth(double height) { _resolvePadding(); - double horizontalPadding = _resolvedPadding.left + _resolvedPadding.right; - double verticalPadding = _resolvedPadding.top + _resolvedPadding.bottom; + double horizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right; + double verticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom; int leadingWidth = _leading == null ? 0 - : _leading.getMaxIntrinsicWidth(height - verticalPadding); + : (_leading!.getMaxIntrinsicWidth(height - verticalPadding) as int); int bodyWidth = _body == null ? 0 - : _body.getMaxIntrinsicWidth(math.max(0.0, height - verticalPadding)); + : (_body!.getMaxIntrinsicWidth(math.max(0.0, height - verticalPadding)) + as int); return horizontalPadding + leadingWidth + bodyWidth; } @override double computeMinIntrinsicHeight(double width) { _resolvePadding(); - double horizontalPadding = _resolvedPadding.left + _resolvedPadding.right; - double verticalPadding = _resolvedPadding.top + _resolvedPadding.bottom; + double horizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right; + double verticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom; if (_body != null) { - return _body + return _body! .getMinIntrinsicHeight(math.max(0.0, width - horizontalPadding)) + verticalPadding; } @@ -664,10 +651,10 @@ class RenderEditableTextLine extends RenderEditableBox { @override double computeMaxIntrinsicHeight(double width) { _resolvePadding(); - double horizontalPadding = _resolvedPadding.left + _resolvedPadding.right; - double verticalPadding = _resolvedPadding.top + _resolvedPadding.bottom; + double horizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right; + double verticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom; if (_body != null) { - return _body + return _body! .getMaxIntrinsicHeight(math.max(0.0, width - horizontalPadding)) + verticalPadding; } @@ -677,7 +664,8 @@ class RenderEditableTextLine extends RenderEditableBox { @override double computeDistanceToActualBaseline(TextBaseline baseline) { _resolvePadding(); - return _body.getDistanceToActualBaseline(baseline) + _resolvedPadding.top; + return _body!.getDistanceToActualBaseline(baseline)! + + _resolvedPadding!.top; } @override @@ -690,43 +678,44 @@ class RenderEditableTextLine extends RenderEditableBox { if (_body == null && _leading == null) { size = constraints.constrain(Size( - _resolvedPadding.left + _resolvedPadding.right, - _resolvedPadding.top + _resolvedPadding.bottom, + _resolvedPadding!.left + _resolvedPadding!.right, + _resolvedPadding!.top + _resolvedPadding!.bottom, )); return; } - final innerConstraints = constraints.deflate(_resolvedPadding); + final innerConstraints = constraints.deflate(_resolvedPadding!); final indentWidth = textDirection == TextDirection.ltr - ? _resolvedPadding.left - : _resolvedPadding.right; + ? _resolvedPadding!.left + : _resolvedPadding!.right; - _body.layout(innerConstraints, parentUsesSize: true); - final bodyParentData = _body.parentData as BoxParentData; - bodyParentData.offset = Offset(_resolvedPadding.left, _resolvedPadding.top); + _body!.layout(innerConstraints, parentUsesSize: true); + final bodyParentData = _body!.parentData as BoxParentData; + bodyParentData.offset = + Offset(_resolvedPadding!.left, _resolvedPadding!.top); if (_leading != null) { final leadingConstraints = innerConstraints.copyWith( minWidth: indentWidth, maxWidth: indentWidth, - maxHeight: _body.size.height); - _leading.layout(leadingConstraints, parentUsesSize: true); - final parentData = _leading.parentData as BoxParentData; - parentData.offset = Offset(0.0, _resolvedPadding.top); + maxHeight: _body!.size.height); + _leading!.layout(leadingConstraints, parentUsesSize: true); + final parentData = _leading!.parentData as BoxParentData; + parentData.offset = Offset(0.0, _resolvedPadding!.top); } size = constraints.constrain(Size( - _resolvedPadding.left + _body.size.width + _resolvedPadding.right, - _resolvedPadding.top + _body.size.height + _resolvedPadding.bottom, + _resolvedPadding!.left + _body!.size.width + _resolvedPadding!.right, + _resolvedPadding!.top + _body!.size.height + _resolvedPadding!.bottom, )); _computeCaretPrototype(); } CursorPainter get _cursorPainter => CursorPainter( - _body, + _body!, cursorCont.style, - _caretPrototype, + _caretPrototype!, cursorCont.cursorColor.value, devicePixelRatio, ); @@ -734,19 +723,19 @@ class RenderEditableTextLine extends RenderEditableBox { @override paint(PaintingContext context, Offset offset) { if (_leading != null) { - final parentData = _leading.parentData as BoxParentData; + final parentData = _leading!.parentData as BoxParentData; final effectiveOffset = offset + parentData.offset; - context.paintChild(_leading, effectiveOffset); + context.paintChild(_leading!, effectiveOffset); } if (_body != null) { - final parentData = _body.parentData as BoxParentData; + final parentData = _body!.parentData as BoxParentData; final effectiveOffset = offset + parentData.offset; if ((enableInteractiveSelection ?? true) && - line.getDocumentOffset() <= textSelection.end && - textSelection.start <= line.getDocumentOffset() + line.length - 1) { - final local = localSelection(line, textSelection, false); - _selectedRects ??= _body.getBoxesForSelection( + line.getDocumentOffset() <= textSelection!.end && + textSelection!.start <= line.getDocumentOffset() + line.length - 1) { + final local = localSelection(line, textSelection!, false); + _selectedRects ??= _body!.getBoxesForSelection( local, ); _paintSelection(context, effectiveOffset); @@ -759,7 +748,7 @@ class RenderEditableTextLine extends RenderEditableBox { _paintCursor(context, effectiveOffset); } - context.paintChild(_body, effectiveOffset); + context.paintChild(_body!, effectiveOffset); if (hasFocus && cursorCont.show.value && @@ -773,15 +762,15 @@ class RenderEditableTextLine extends RenderEditableBox { _paintSelection(PaintingContext context, Offset effectiveOffset) { assert(_selectedRects != null); final paint = Paint()..color = color; - for (final box in _selectedRects) { + for (final box in _selectedRects!) { context.canvas.drawRect(box.toRect().shift(effectiveOffset), paint); } } _paintCursor(PaintingContext context, Offset effectiveOffset) { final position = TextPosition( - offset: textSelection.extentOffset - line.getDocumentOffset(), - affinity: textSelection.base.affinity, + offset: textSelection!.extentOffset - line.getDocumentOffset(), + affinity: textSelection!.base.affinity, ); _cursorPainter.paint(context.canvas, effectiveOffset, position); } @@ -814,7 +803,7 @@ class _TextLineElement extends RenderObjectElement { } @override - mount(Element parent, dynamic newSlot) { + mount(Element? parent, dynamic newSlot) { super.mount(parent, newSlot); _mountChild(widget.leading, TextLineSlot.LEADING); _mountChild(widget.body, TextLineSlot.BODY); @@ -848,9 +837,9 @@ class _TextLineElement extends RenderObjectElement { throw UnimplementedError(); } - _mountChild(Widget widget, TextLineSlot slot) { - Element oldChild = _slotToChildren[slot]; - Element newChild = updateChild(oldChild, widget, slot); + _mountChild(Widget? widget, TextLineSlot slot) { + Element? oldChild = _slotToChildren[slot]; + Element? newChild = updateChild(oldChild, widget, slot); if (oldChild != null) { _slotToChildren.remove(slot); } @@ -859,22 +848,22 @@ class _TextLineElement extends RenderObjectElement { } } - _updateRenderObject(RenderObject child, TextLineSlot slot) { + _updateRenderObject(RenderObject? child, TextLineSlot slot) { switch (slot) { case TextLineSlot.LEADING: renderObject.setLeading(child as RenderBox); break; case TextLineSlot.BODY: - renderObject.setBody(child as RenderBox); + renderObject.setBody(child as RenderContentProxyBox); break; default: throw UnimplementedError(); } } - _updateChild(Widget widget, TextLineSlot slot) { - Element oldChild = _slotToChildren[slot]; - Element newChild = updateChild(oldChild, widget, slot); + _updateChild(Widget? widget, TextLineSlot slot) { + Element? oldChild = _slotToChildren[slot]; + Element? newChild = updateChild(oldChild, widget, slot); if (oldChild != null) { _slotToChildren.remove(slot); } diff --git a/lib/widgets/text_selection.dart b/lib/widgets/text_selection.dart index e74318ac..592b2eee 100644 --- a/lib/widgets/text_selection.dart +++ b/lib/widgets/text_selection.dart @@ -27,19 +27,19 @@ class EditorTextSelectionOverlay { TextEditingValue value; bool handlesVisible = false; final BuildContext context; - final Widget debugRequiredFor; - final LayerLink toolbarLayerLink; - final LayerLink startHandleLayerLink; - final LayerLink endHandleLayerLink; - final RenderEditor renderObject; - final TextSelectionControls selectionCtrls; - final TextSelectionDelegate selectionDelegate; - final DragStartBehavior dragStartBehavior; - final VoidCallback onSelectionHandleTapped; - final ClipboardStatusNotifier clipboardStatus; - AnimationController _toolbarController; - List _handles; - OverlayEntry toolbar; + final Widget? debugRequiredFor; + final LayerLink? toolbarLayerLink; + final LayerLink? startHandleLayerLink; + final LayerLink? endHandleLayerLink; + final RenderEditor? renderObject; + final TextSelectionControls? selectionCtrls; + final TextSelectionDelegate? selectionDelegate; + final DragStartBehavior? dragStartBehavior; + final VoidCallback? onSelectionHandleTapped; + final ClipboardStatusNotifier? clipboardStatus; + AnimationController? _toolbarController; + List? _handles; + OverlayEntry? toolbar; EditorTextSelectionOverlay( this.value, @@ -54,31 +54,24 @@ class EditorTextSelectionOverlay { this.selectionDelegate, this.dragStartBehavior, this.onSelectionHandleTapped, - this.clipboardStatus) - : assert(value != null), - assert(context != null), - assert(handlesVisible != null) { - OverlayState overlay = Overlay.of(context, rootOverlay: true); - assert( - overlay != null, - ); + this.clipboardStatus) { + OverlayState overlay = Overlay.of(context, rootOverlay: true)!; _toolbarController = AnimationController( duration: Duration(milliseconds: 150), vsync: overlay); } TextSelection get _selection => value.selection; - Animation get _toolbarOpacity => _toolbarController.view; + Animation get _toolbarOpacity => _toolbarController!.view; setHandlesVisible(bool visible) { - assert(visible != null); if (handlesVisible == visible) { return; } handlesVisible = visible; - if (SchedulerBinding.instance.schedulerPhase == + if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance.addPostFrameCallback(markNeedsBuild); + SchedulerBinding.instance!.addPostFrameCallback(markNeedsBuild); } else { markNeedsBuild(); } @@ -88,24 +81,24 @@ class EditorTextSelectionOverlay { if (_handles == null) { return; } - _handles[0].remove(); - _handles[1].remove(); + _handles![0].remove(); + _handles![1].remove(); _handles = null; } hideToolbar() { assert(toolbar != null); - _toolbarController.stop(); - toolbar.remove(); + _toolbarController!.stop(); + toolbar!.remove(); toolbar = null; } showToolbar() { assert(toolbar == null); toolbar = OverlayEntry(builder: _buildToolbar); - Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor) - .insert(toolbar); - _toolbarController.forward(from: 0.0); + Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)! + .insert(toolbar!); + _toolbarController!.forward(from: 0.0); } Widget _buildHandle( @@ -122,13 +115,13 @@ class EditorTextSelectionOverlay { _handleSelectionHandleChanged(newSelection, position); }, onSelectionHandleTapped: onSelectionHandleTapped, - startHandleLayerLink: startHandleLayerLink, - endHandleLayerLink: endHandleLayerLink, - renderObject: renderObject, + startHandleLayerLink: startHandleLayerLink!, + endHandleLayerLink: endHandleLayerLink!, + renderObject: renderObject!, selection: _selection, - selectionControls: selectionCtrls, + selectionControls: selectionCtrls!, position: position, - dragStartBehavior: dragStartBehavior, + dragStartBehavior: dragStartBehavior!, )); } @@ -137,9 +130,9 @@ class EditorTextSelectionOverlay { return; } value = newValue; - if (SchedulerBinding.instance.schedulerPhase == + if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance.addPostFrameCallback(markNeedsBuild); + SchedulerBinding.instance!.addPostFrameCallback(markNeedsBuild); } else { markNeedsBuild(); } @@ -158,9 +151,9 @@ class EditorTextSelectionOverlay { default: throw ('Invalid position'); } - selectionDelegate.textEditingValue = + selectionDelegate!.textEditingValue = value.copyWith(selection: newSelection, composing: TextRange.empty); - selectionDelegate.bringIntoView(textPosition); + selectionDelegate!.bringIntoView(textPosition); } Widget _buildToolbar(BuildContext context) { @@ -169,16 +162,16 @@ class EditorTextSelectionOverlay { } List endpoints = - renderObject.getEndpointsForSelection(_selection); + renderObject!.getEndpointsForSelection(_selection); Rect editingRegion = Rect.fromPoints( - renderObject.localToGlobal(Offset.zero), - renderObject.localToGlobal(renderObject.size.bottomRight(Offset.zero)), + renderObject!.localToGlobal(Offset.zero), + renderObject!.localToGlobal(renderObject!.size.bottomRight(Offset.zero)), ); - double baseLineHeight = renderObject.preferredLineHeight(_selection.base); + double baseLineHeight = renderObject!.preferredLineHeight(_selection.base); double extentLineHeight = - renderObject.preferredLineHeight(_selection.extent); + renderObject!.preferredLineHeight(_selection.extent); double smallestLineHeight = math.min(baseLineHeight, extentLineHeight); bool isMultiline = endpoints.last.point.dy - endpoints.first.point.dy > smallestLineHeight / 2; @@ -195,34 +188,34 @@ class EditorTextSelectionOverlay { return FadeTransition( opacity: _toolbarOpacity, child: CompositedTransformFollower( - link: toolbarLayerLink, + link: toolbarLayerLink!, showWhenUnlinked: false, offset: -editingRegion.topLeft, - child: selectionCtrls.buildToolbar( + child: selectionCtrls!.buildToolbar( context, editingRegion, baseLineHeight, midpoint, endpoints, - selectionDelegate, - clipboardStatus, + selectionDelegate!, + clipboardStatus!, Offset(0, 0)), ), ); } - markNeedsBuild([Duration duration]) { + markNeedsBuild([Duration? duration]) { if (_handles != null) { - _handles[0].markNeedsBuild(); - _handles[1].markNeedsBuild(); + _handles![0].markNeedsBuild(); + _handles![1].markNeedsBuild(); } toolbar?.markNeedsBuild(); } hide() { if (_handles != null) { - _handles[0].remove(); - _handles[1].remove(); + _handles![0].remove(); + _handles![1].remove(); _handles = null; } if (toolbar != null) { @@ -232,7 +225,7 @@ class EditorTextSelectionOverlay { dispose() { hide(); - _toolbarController.dispose(); + _toolbarController!.dispose(); } void showHandles() { @@ -246,22 +239,22 @@ class EditorTextSelectionOverlay { _buildHandle(context, _TextSelectionHandlePosition.END)), ]; - Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor) - .insertAll(_handles); + Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)! + .insertAll(_handles!); } } class _TextSelectionHandleOverlay extends StatefulWidget { const _TextSelectionHandleOverlay({ - Key key, - @required this.selection, - @required this.position, - @required this.startHandleLayerLink, - @required this.endHandleLayerLink, - @required this.renderObject, - @required this.onSelectionHandleChanged, - @required this.onSelectionHandleTapped, - @required this.selectionControls, + Key? key, + required this.selection, + required this.position, + required this.startHandleLayerLink, + required this.endHandleLayerLink, + required this.renderObject, + required this.onSelectionHandleChanged, + required this.onSelectionHandleTapped, + required this.selectionControls, this.dragStartBehavior = DragStartBehavior.start, }) : super(key: key); @@ -271,7 +264,7 @@ class _TextSelectionHandleOverlay extends StatefulWidget { final LayerLink endHandleLayerLink; final RenderEditor renderObject; final ValueChanged onSelectionHandleChanged; - final VoidCallback onSelectionHandleTapped; + final VoidCallback? onSelectionHandleTapped; final TextSelectionControls selectionControls; final DragStartBehavior dragStartBehavior; @@ -286,16 +279,15 @@ class _TextSelectionHandleOverlay extends StatefulWidget { case _TextSelectionHandlePosition.END: return renderObject.selectionEndInViewport; } - return null; } } class _TextSelectionHandleOverlayState extends State<_TextSelectionHandleOverlay> with SingleTickerProviderStateMixin { - AnimationController _controller; + AnimationController? _controller; - Animation get _opacity => _controller.view; + Animation get _opacity => _controller!.view; @override void initState() { @@ -310,9 +302,9 @@ class _TextSelectionHandleOverlayState _handleVisibilityChanged() { if (widget._visibility.value) { - _controller.forward(); + _controller!.forward(); } else { - _controller.reverse(); + _controller!.reverse(); } } @@ -327,7 +319,7 @@ class _TextSelectionHandleOverlayState @override void dispose() { widget._visibility.removeListener(_handleVisibilityChanged); - _controller.dispose(); + _controller!.dispose(); super.dispose(); } @@ -367,8 +359,9 @@ class _TextSelectionHandleOverlayState } _handleTap() { - if (widget.onSelectionHandleTapped != null) - widget.onSelectionHandleTapped(); + if (widget.onSelectionHandleTapped != null) { + widget.onSelectionHandleTapped!(); + } } @override @@ -465,20 +458,18 @@ class _TextSelectionHandleOverlayState ) { if (widget.selection.isCollapsed) return TextSelectionHandleType.collapsed; - assert(textDirection != null); switch (textDirection) { case TextDirection.ltr: return ltrType; case TextDirection.rtl: return rtlType; } - return null; } } class EditorTextSelectionGestureDetector extends StatefulWidget { const EditorTextSelectionGestureDetector({ - Key key, + Key? key, this.onTapDown, this.onForcePressStart, this.onForcePressEnd, @@ -492,35 +483,34 @@ class EditorTextSelectionGestureDetector extends StatefulWidget { this.onDragSelectionUpdate, this.onDragSelectionEnd, this.behavior, - @required this.child, - }) : assert(child != null), - super(key: key); + required this.child, + }) : super(key: key); - final GestureTapDownCallback onTapDown; + final GestureTapDownCallback? onTapDown; - final GestureForcePressStartCallback onForcePressStart; + final GestureForcePressStartCallback? onForcePressStart; - final GestureForcePressEndCallback onForcePressEnd; + final GestureForcePressEndCallback? onForcePressEnd; - final GestureTapUpCallback onSingleTapUp; + final GestureTapUpCallback? onSingleTapUp; - final GestureTapCancelCallback onSingleTapCancel; + final GestureTapCancelCallback? onSingleTapCancel; - final GestureLongPressStartCallback onSingleLongTapStart; + final GestureLongPressStartCallback? onSingleLongTapStart; - final GestureLongPressMoveUpdateCallback onSingleLongTapMoveUpdate; + final GestureLongPressMoveUpdateCallback? onSingleLongTapMoveUpdate; - final GestureLongPressEndCallback onSingleLongTapEnd; + final GestureLongPressEndCallback? onSingleLongTapEnd; - final GestureTapDownCallback onDoubleTapDown; + final GestureTapDownCallback? onDoubleTapDown; - final GestureDragStartCallback onDragSelectionStart; + final GestureDragStartCallback? onDragSelectionStart; - final DragSelectionUpdateCallback onDragSelectionUpdate; + final DragSelectionUpdateCallback? onDragSelectionUpdate; - final GestureDragEndCallback onDragSelectionEnd; + final GestureDragEndCallback? onDragSelectionEnd; - final HitTestBehavior behavior; + final HitTestBehavior? behavior; final Widget child; @@ -531,28 +521,28 @@ class EditorTextSelectionGestureDetector extends StatefulWidget { class _EditorTextSelectionGestureDetectorState extends State { - Timer _doubleTapTimer; - Offset _lastTapOffset; + Timer? _doubleTapTimer; + Offset? _lastTapOffset; bool _isDoubleTap = false; @override void dispose() { _doubleTapTimer?.cancel(); - _dragUpdateThrottleTimer?.cancel(); + _dragUpdateThrottleTimer!.cancel(); super.dispose(); } _handleTapDown(TapDownDetails details) { if (widget.onTapDown != null) { - widget.onTapDown(details); + widget.onTapDown!(details); } if (_doubleTapTimer != null && _isWithinDoubleTapTolerance(details.globalPosition)) { if (widget.onDoubleTapDown != null) { - widget.onDoubleTapDown(details); + widget.onDoubleTapDown!(details); } - _doubleTapTimer.cancel(); + _doubleTapTimer!.cancel(); _doubleTapTimeout(); _isDoubleTap = true; } @@ -561,7 +551,7 @@ class _EditorTextSelectionGestureDetectorState _handleTapUp(TapUpDetails details) { if (!_isDoubleTap) { if (widget.onSingleTapUp != null) { - widget.onSingleTapUp(details); + widget.onSingleTapUp!(details); } _lastTapOffset = details.globalPosition; _doubleTapTimer = Timer(kDoubleTapTimeout, _doubleTapTimeout); @@ -571,19 +561,19 @@ class _EditorTextSelectionGestureDetectorState _handleTapCancel() { if (widget.onSingleTapCancel != null) { - widget.onSingleTapCancel(); + widget.onSingleTapCancel!(); } } - DragStartDetails _lastDragStartDetails; - DragUpdateDetails _lastDragUpdateDetails; - Timer _dragUpdateThrottleTimer; + DragStartDetails? _lastDragStartDetails; + DragUpdateDetails? _lastDragUpdateDetails; + Timer? _dragUpdateThrottleTimer; _handleDragStart(DragStartDetails details) { assert(_lastDragStartDetails == null); _lastDragStartDetails = details; if (widget.onDragSelectionStart != null) { - widget.onDragSelectionStart(details); + widget.onDragSelectionStart!(details); } } @@ -597,8 +587,8 @@ class _EditorTextSelectionGestureDetectorState assert(_lastDragStartDetails != null); assert(_lastDragUpdateDetails != null); if (widget.onDragSelectionUpdate != null) { - widget.onDragSelectionUpdate( - _lastDragStartDetails, _lastDragUpdateDetails); + widget.onDragSelectionUpdate!( + _lastDragStartDetails!, _lastDragUpdateDetails!); } _dragUpdateThrottleTimer = null; _lastDragUpdateDetails = null; @@ -607,11 +597,11 @@ class _EditorTextSelectionGestureDetectorState _handleDragEnd(DragEndDetails details) { assert(_lastDragStartDetails != null); if (_dragUpdateThrottleTimer != null) { - _dragUpdateThrottleTimer.cancel(); + _dragUpdateThrottleTimer!.cancel(); _handleDragUpdateThrottled(); } if (widget.onDragSelectionEnd != null) { - widget.onDragSelectionEnd(details); + widget.onDragSelectionEnd!(details); } _dragUpdateThrottleTimer = null; _lastDragStartDetails = null; @@ -622,31 +612,31 @@ class _EditorTextSelectionGestureDetectorState _doubleTapTimer?.cancel(); _doubleTapTimer = null; if (widget.onForcePressStart != null) { - widget.onForcePressStart(details); + widget.onForcePressStart!(details); } } _forcePressEnded(ForcePressDetails details) { if (widget.onForcePressEnd != null) { - widget.onForcePressEnd(details); + widget.onForcePressEnd!(details); } } _handleLongPressStart(LongPressStartDetails details) { if (!_isDoubleTap && widget.onSingleLongTapStart != null) { - widget.onSingleLongTapStart(details); + widget.onSingleLongTapStart!(details); } } _handleLongPressMoveUpdate(LongPressMoveUpdateDetails details) { if (!_isDoubleTap && widget.onSingleLongTapMoveUpdate != null) { - widget.onSingleLongTapMoveUpdate(details); + widget.onSingleLongTapMoveUpdate!(details); } } _handleLongPressEnd(LongPressEndDetails details) { if (!_isDoubleTap && widget.onSingleLongTapEnd != null) { - widget.onSingleLongTapEnd(details); + widget.onSingleLongTapEnd!(details); } _isDoubleTap = false; } @@ -657,12 +647,11 @@ class _EditorTextSelectionGestureDetectorState } bool _isWithinDoubleTapTolerance(Offset secondTapOffset) { - assert(secondTapOffset != null); if (_lastTapOffset == null) { return false; } - return (secondTapOffset - _lastTapOffset).distance <= kDoubleTapSlop; + return (secondTapOffset - _lastTapOffset!).distance <= kDoubleTapSlop; } @override @@ -738,7 +727,7 @@ class _EditorTextSelectionGestureDetectorState class _TransparentTapGestureRecognizer extends TapGestureRecognizer { _TransparentTapGestureRecognizer({ - Object debugOwner, + Object? debugOwner, }) : super(debugOwner: debugOwner); @override diff --git a/lib/widgets/toolbar.dart b/lib/widgets/toolbar.dart index 74ee989b..0390fa6b 100644 --- a/lib/widgets/toolbar.dart +++ b/lib/widgets/toolbar.dart @@ -1,10 +1,12 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; +//import 'package:filesystem_picker/filesystem_picker.dart'; import 'package:filesystem_picker/filesystem_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +//import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_quill/models/documents/attribute.dart'; import 'package:flutter_quill/models/documents/nodes/embed.dart'; @@ -18,7 +20,7 @@ import 'controller.dart'; double iconSize = 18.0; double kToolbarHeight = iconSize * 2; -typedef OnImagePickCallback = Future Function(File file); +typedef OnImagePickCallback = Future Function(File? file); typedef ImagePickImpl = Future Function(ImageSource source); class InsertEmbedButton extends StatelessWidget { @@ -26,9 +28,9 @@ class InsertEmbedButton extends StatelessWidget { final IconData icon; const InsertEmbedButton({ - Key key, - @required this.controller, - @required this.icon, + Key? key, + required this.controller, + required this.icon, }) : super(key: key); @override @@ -54,11 +56,11 @@ class InsertEmbedButton extends StatelessWidget { class LinkStyleButton extends StatefulWidget { final QuillController controller; - final IconData icon; + final IconData? icon; const LinkStyleButton({ - Key key, - @required this.controller, + Key? key, + required this.controller, this.icon, }) : super(key: key); @@ -96,7 +98,8 @@ class _LinkStyleButtonState extends State { Widget build(BuildContext context) { final theme = Theme.of(context); final isEnabled = !widget.controller.selection.isCollapsed; - final pressedHandler = isEnabled ? () => _openLinkDialog(context) : null; + final VoidCallback? pressedHandler = + isEnabled ? () => _openLinkDialog(context) : null; return QuillIconButton( highlightElevation: 0, hoverElevation: 0, @@ -120,7 +123,7 @@ class _LinkStyleButtonState extends State { ).then(_linkSubmitted); } - void _linkSubmitted(String value) { + void _linkSubmitted(String? value) { if (value == null || value.isEmpty) { return; } @@ -129,7 +132,7 @@ class _LinkStyleButtonState extends State { } class _LinkDialog extends StatefulWidget { - const _LinkDialog({Key key}) : super(key: key); + const _LinkDialog({Key? key}) : super(key: key); @override _LinkDialogState createState() => _LinkDialogState(); @@ -171,7 +174,7 @@ typedef ToggleStyleButtonBuilder = Widget Function( Attribute attribute, IconData icon, bool isToggled, - VoidCallback onPressed, + VoidCallback? onPressed, ); class ToggleStyleButton extends StatefulWidget { @@ -184,23 +187,19 @@ class ToggleStyleButton extends StatefulWidget { final ToggleStyleButtonBuilder childBuilder; ToggleStyleButton({ - Key key, - @required this.attribute, - @required this.icon, - @required this.controller, + Key? key, + required this.attribute, + required this.icon, + required this.controller, this.childBuilder = defaultToggleStyleButtonBuilder, - }) : assert(attribute.value != null), - assert(icon != null), - assert(controller != null), - assert(childBuilder != null), - super(key: key); + }) : super(key: key); @override _ToggleStyleButtonState createState() => _ToggleStyleButtonState(); } class _ToggleStyleButtonState extends State { - bool _isToggled; + bool? _isToggled; Style get _selectionStyle => widget.controller.getSelectionStyle(); @@ -220,7 +219,7 @@ class _ToggleStyleButtonState extends State { bool _getIsToggled(Map attrs) { if (widget.attribute.key == Attribute.list.key) { - Attribute attribute = attrs[widget.attribute.key]; + Attribute? attribute = attrs[widget.attribute.key]; if (attribute == null) { return false; } @@ -252,11 +251,11 @@ class _ToggleStyleButtonState extends State { final isEnabled = !isInCodeBlock || widget.attribute.key == Attribute.codeBlock.key; return widget.childBuilder(context, widget.attribute, widget.icon, - _isToggled, isEnabled ? _toggleAttribute : null); + _isToggled!, isEnabled ? _toggleAttribute : null); } _toggleAttribute() { - widget.controller.formatSelection(_isToggled + widget.controller.formatSelection(_isToggled! ? Attribute.clone(widget.attribute, null) : widget.attribute); } @@ -272,22 +271,19 @@ class ToggleCheckListButton extends StatefulWidget { final Attribute attribute; ToggleCheckListButton({ - Key key, - @required this.icon, - @required this.controller, + Key? key, + required this.icon, + required this.controller, this.childBuilder = defaultToggleStyleButtonBuilder, - @required this.attribute, - }) : assert(icon != null), - assert(controller != null), - assert(childBuilder != null), - super(key: key); + required this.attribute, + }) : super(key: key); @override _ToggleCheckListButtonState createState() => _ToggleCheckListButtonState(); } class _ToggleCheckListButtonState extends State { - bool _isToggled; + bool? _isToggled; Style get _selectionStyle => widget.controller.getSelectionStyle(); @@ -307,7 +303,7 @@ class _ToggleCheckListButtonState extends State { bool _getIsToggled(Map attrs) { if (widget.attribute.key == Attribute.list.key) { - Attribute attribute = attrs[widget.attribute.key]; + Attribute? attribute = attrs[widget.attribute.key]; if (attribute == null) { return false; } @@ -340,11 +336,11 @@ class _ToggleCheckListButtonState extends State { final isEnabled = !isInCodeBlock || Attribute.list.key == Attribute.codeBlock.key; return widget.childBuilder(context, Attribute.unchecked, widget.icon, - _isToggled, isEnabled ? _toggleAttribute : null); + _isToggled!, isEnabled ? _toggleAttribute : null); } _toggleAttribute() { - widget.controller.formatSelection(_isToggled + widget.controller.formatSelection(_isToggled! ? Attribute.clone(Attribute.unchecked, null) : Attribute.unchecked); } @@ -355,7 +351,7 @@ Widget defaultToggleStyleButtonBuilder( Attribute attribute, IconData icon, bool isToggled, - VoidCallback onPressed, + VoidCallback? onPressed, ) { final theme = Theme.of(context); final isEnabled = onPressed != null; @@ -378,7 +374,7 @@ Widget defaultToggleStyleButtonBuilder( class SelectHeaderStyleButton extends StatefulWidget { final QuillController controller; - const SelectHeaderStyleButton({Key key, @required this.controller}) + const SelectHeaderStyleButton({Key? key, required this.controller}) : super(key: key); @override @@ -387,7 +383,7 @@ class SelectHeaderStyleButton extends StatefulWidget { } class _SelectHeaderStyleButtonState extends State { - Attribute _value; + Attribute? _value; Style get _selectionStyle => widget.controller.getSelectionStyle(); @@ -431,7 +427,7 @@ class _SelectHeaderStyleButtonState extends State { @override Widget build(BuildContext context) { - return _selectHeadingStyleButtonBuilder(context, _value, _selectAttribute); + return _selectHeadingStyleButtonBuilder(context, _value!, _selectAttribute); } } @@ -453,35 +449,35 @@ Widget _selectHeadingStyleButtonBuilder( fillColor: Theme.of(context).canvasColor, child: Text( !kIsWeb - ? _valueToText[value] + ? _valueToText[value]! : _valueToText[value.key == "header" ? Attribute.header : (value.key == "h1") ? Attribute.h1 : (value.key == "h2") ? Attribute.h2 - : Attribute.h3], + : Attribute.h3]!, style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600), ), initialValue: value, items: [ PopupMenuItem( - child: Text(_valueToText[Attribute.header], style: style), + child: Text(_valueToText[Attribute.header]!, style: style), value: Attribute.header, height: iconSize * 1.77, ), PopupMenuItem( - child: Text(_valueToText[Attribute.h1], style: style), + child: Text(_valueToText[Attribute.h1]!, style: style), value: Attribute.h1, height: iconSize * 1.77, ), PopupMenuItem( - child: Text(_valueToText[Attribute.h2], style: style), + child: Text(_valueToText[Attribute.h2]!, style: style), value: Attribute.h2, height: iconSize * 1.77, ), PopupMenuItem( - child: Text(_valueToText[Attribute.h3], style: style), + child: Text(_valueToText[Attribute.h3]!, style: style), value: Attribute.h3, height: iconSize * 1.77, ), @@ -495,43 +491,41 @@ class ImageButton extends StatefulWidget { final QuillController controller; - final OnImagePickCallback onImagePickCallback; + final OnImagePickCallback? onImagePickCallback; - final ImagePickImpl imagePickImpl; + final ImagePickImpl? imagePickImpl; final ImageSource imageSource; ImageButton( - {Key key, - @required this.icon, - @required this.controller, - @required this.imageSource, + {Key? key, + required this.icon, + required this.controller, + required this.imageSource, this.onImagePickCallback, this.imagePickImpl}) - : assert(icon != null), - assert(controller != null), - super(key: key); + : super(key: key); @override _ImageButtonState createState() => _ImageButtonState(); } class _ImageButtonState extends State { - List _paths; - String _extension; + List? _paths; + String? _extension; final _picker = ImagePicker(); FileType _pickingType = FileType.any; - Future _pickImage(ImageSource source) async { - final PickedFile pickedFile = await _picker.getImage(source: source); + Future _pickImage(ImageSource imageSource) async { + final PickedFile? pickedFile = await _picker.getImage(source: imageSource); if (pickedFile == null) return null; - final File file = File(pickedFile.path); + final File? file = File(pickedFile.path); if (file == null || widget.onImagePickCallback == null) return null; // We simply return the absolute path to selected file. try { - String url = await widget.onImagePickCallback(file); + String? url = await widget.onImagePickCallback!(file); print('Image uploaded and its url is $url'); return url; } catch (error) { @@ -540,13 +534,13 @@ class _ImageButtonState extends State { return null; } - Future _pickImageWeb() async { + Future _pickImageWeb() async { try { _paths = (await FilePicker.platform.pickFiles( type: _pickingType, allowMultiple: false, allowedExtensions: (_extension?.isNotEmpty ?? false) - ? _extension?.replaceAll(' ', '')?.split(',') + ? _extension?.replaceAll(' ', '').split(',') : null, )) ?.files; @@ -556,14 +550,15 @@ class _ImageButtonState extends State { print(ex); } var _fileName = - _paths != null ? _paths.map((e) => e.name).toString() : '...'; + _paths != null ? _paths!.map((e) => e.name).toString() : '...'; if (_paths != null) { File file = File(_fileName); - if (file == null || widget.onImagePickCallback == null) return null; + //The condition is never true because File constructor never gives null. + //if (file == null || widget.onImagePickCallback == null) return null; // We simply return the absolute path to selected file. try { - String url = await widget.onImagePickCallback(file); + String? url = await widget.onImagePickCallback!(file); print('Image uploaded and its url is $url'); return url; } catch (error) { @@ -576,7 +571,7 @@ class _ImageButtonState extends State { return null; } - Future _pickImageDesktop() async { + Future _pickImageDesktop() async { try { var filePath = await FilesystemPicker.open( context: context, @@ -587,7 +582,7 @@ class _ImageButtonState extends State { if (filePath == null || filePath.isEmpty) return null; final File file = File(filePath); - String url = await widget.onImagePickCallback(file); + String? url = await widget.onImagePickCallback!(file); print('Image uploaded and its url is $url'); return url; } catch (error) { @@ -610,9 +605,9 @@ class _ImageButtonState extends State { onPressed: () { final index = widget.controller.selection.baseOffset; final length = widget.controller.selection.extentOffset - index; - Future image; + Future image; if (widget.imagePickImpl != null) { - image = widget.imagePickImpl(widget.imageSource); + image = widget.imagePickImpl!(widget.imageSource); } else { if (kIsWeb) { image = _pickImageWeb(); @@ -644,24 +639,21 @@ class ColorButton extends StatefulWidget { final QuillController controller; ColorButton( - {Key key, - @required this.icon, - @required this.controller, - @required this.background}) - : assert(icon != null), - assert(controller != null), - assert(background != null), - super(key: key); + {Key? key, + required this.icon, + required this.controller, + required this.background}) + : super(key: key); @override _ColorButtonState createState() => _ColorButtonState(); } class _ColorButtonState extends State { - bool _isToggledColor; - bool _isToggledBackground; - bool _isWhite; - bool _isWhitebackground; + bool? _isToggledColor; + bool? _isToggledBackground; + bool? _isWhite; + bool? _isWhitebackground; Style get _selectionStyle => widget.controller.getSelectionStyle(); @@ -671,10 +663,10 @@ class _ColorButtonState extends State { _getIsToggledColor(widget.controller.getSelectionStyle().attributes); _isToggledBackground = _getIsToggledBackground( widget.controller.getSelectionStyle().attributes); - _isWhite = _isToggledColor && - _selectionStyle.attributes["color"].value == '#ffffff'; - _isWhitebackground = _isToggledBackground && - _selectionStyle.attributes["background"].value == '#ffffff'; + _isWhite = _isToggledColor! && + _selectionStyle.attributes["color"]!.value == '#ffffff'; + _isWhitebackground = _isToggledBackground! && + _selectionStyle.attributes["background"]!.value == '#ffffff'; }); } @@ -683,10 +675,10 @@ class _ColorButtonState extends State { super.initState(); _isToggledColor = _getIsToggledColor(_selectionStyle.attributes); _isToggledBackground = _getIsToggledBackground(_selectionStyle.attributes); - _isWhite = _isToggledColor && - _selectionStyle.attributes["color"].value == '#ffffff'; - _isWhitebackground = _isToggledBackground && - _selectionStyle.attributes["background"].value == '#ffffff'; + _isWhite = _isToggledColor! && + _selectionStyle.attributes["color"]!.value == '#ffffff'; + _isWhitebackground = _isToggledBackground! && + _selectionStyle.attributes["background"]!.value == '#ffffff'; widget.controller.addListener(_didChangeEditingValue); } @@ -707,10 +699,10 @@ class _ColorButtonState extends State { _isToggledColor = _getIsToggledColor(_selectionStyle.attributes); _isToggledBackground = _getIsToggledBackground(_selectionStyle.attributes); - _isWhite = _isToggledColor && - _selectionStyle.attributes["color"].value == '#ffffff'; - _isWhitebackground = _isToggledBackground && - _selectionStyle.attributes["background"].value == '#ffffff'; + _isWhite = _isToggledColor! && + _selectionStyle.attributes["color"]!.value == '#ffffff'; + _isWhitebackground = _isToggledBackground! && + _selectionStyle.attributes["background"]!.value == '#ffffff'; } } @@ -723,20 +715,20 @@ class _ColorButtonState extends State { @override Widget build(BuildContext context) { final theme = Theme.of(context); - Color iconColor = _isToggledColor && !widget.background && !_isWhite - ? stringToColor(_selectionStyle.attributes["color"].value) - : theme.iconTheme.color; + Color iconColor = _isToggledColor! && !widget.background && !_isWhite! + ? stringToColor(_selectionStyle.attributes["color"]!.value) + : theme.iconTheme.color!; Color iconColorBackground = - _isToggledBackground && widget.background && !_isWhitebackground - ? stringToColor(_selectionStyle.attributes["background"].value) - : theme.iconTheme.color; + _isToggledBackground! && widget.background && !_isWhitebackground! + ? stringToColor(_selectionStyle.attributes["background"]!.value) + : theme.iconTheme.color!; - Color fillColor = _isToggledColor && !widget.background && _isWhite + Color fillColor = _isToggledColor! && !widget.background && _isWhite! ? stringToColor('#ffffff') : theme.canvasColor; Color fillColorBackground = - _isToggledBackground && widget.background && _isWhitebackground + _isToggledBackground! && widget.background && _isWhitebackground! ? stringToColor('#ffffff') : theme.canvasColor; @@ -785,29 +777,26 @@ class HistoryButton extends StatefulWidget { final QuillController controller; HistoryButton( - {Key key, - @required this.icon, - @required this.controller, - @required this.undo}) - : assert(icon != null), - assert(controller != null), - assert(undo != null), - super(key: key); + {Key? key, + required this.icon, + required this.controller, + required this.undo}) + : super(key: key); @override _HistoryButtonState createState() => _HistoryButtonState(); } class _HistoryButtonState extends State { - Color _iconColor; - ThemeData theme; + Color? _iconColor; + ThemeData? theme; @override Widget build(BuildContext context) { theme = Theme.of(context); _setIconColor(); - final fillColor = theme.canvasColor; + final fillColor = theme!.canvasColor; widget.controller.changes.listen((event) async { _setIconColor(); }); @@ -827,14 +816,14 @@ class _HistoryButtonState extends State { if (widget.undo) { setState(() { _iconColor = widget.controller.hasUndo - ? theme.iconTheme.color - : theme.disabledColor; + ? theme!.iconTheme.color! + : theme!.disabledColor; }); } else { setState(() { _iconColor = widget.controller.hasRedo - ? theme.iconTheme.color - : theme.disabledColor; + ? theme!.iconTheme.color! + : theme!.disabledColor; }); } } @@ -860,14 +849,11 @@ class IndentButton extends StatefulWidget { final bool isIncrease; IndentButton( - {Key key, - @required this.icon, - @required this.controller, - @required this.isIncrease}) - : assert(icon != null), - assert(controller != null), - assert(isIncrease != null), - super(key: key); + {Key? key, + required this.icon, + required this.controller, + required this.isIncrease}) + : super(key: key); @override _IndentButtonState createState() => _IndentButtonState(); @@ -917,10 +903,8 @@ class ClearFormatButton extends StatefulWidget { final QuillController controller; - ClearFormatButton({Key key, @required this.icon, @required this.controller}) - : assert(icon != null), - assert(controller != null), - super(key: key); + ClearFormatButton({Key? key, required this.icon, required this.controller}) + : super(key: key); @override _ClearFormatButtonState createState() => _ClearFormatButtonState(); @@ -950,11 +934,11 @@ class _ClearFormatButtonState extends State { class QuillToolbar extends StatefulWidget implements PreferredSizeWidget { final List children; - const QuillToolbar({Key key, @required this.children}) : super(key: key); + const QuillToolbar({Key? key, required this.children}) : super(key: key); factory QuillToolbar.basic( - {Key key, - @required QuillController controller, + {Key? key, + required QuillController controller, double toolbarIconSize = 18.0, bool showBoldButton = true, bool showItalicButton = true, @@ -973,7 +957,7 @@ class QuillToolbar extends StatefulWidget implements PreferredSizeWidget { bool showLink = true, bool showHistory = true, bool showHorizontalRule = false, - OnImagePickCallback onImagePickCallback}) { + OnImagePickCallback? onImagePickCallback}) { iconSize = toolbarIconSize; return QuillToolbar(key: key, children: [ Visibility( @@ -1192,16 +1176,16 @@ class _QuillToolbarState extends State { } class QuillIconButton extends StatelessWidget { - final VoidCallback onPressed; - final Widget icon; + final VoidCallback? onPressed; + final Widget? icon; final double size; - final Color fillColor; + final Color? fillColor; final double hoverElevation; final double highlightElevation; const QuillIconButton({ - Key key, - @required this.onPressed, + Key? key, + required this.onPressed, this.icon, this.size = 40, this.fillColor, @@ -1230,24 +1214,24 @@ class QuillIconButton extends StatelessWidget { class QuillDropdownButton extends StatefulWidget { final double height; - final Color fillColor; + final Color? fillColor; final double hoverElevation; final double highlightElevation; final Widget child; final T initialValue; final List> items; - final ValueChanged onSelected; + final ValueChanged? onSelected; const QuillDropdownButton({ - Key key, + Key? key, this.height = 40, this.fillColor, this.hoverElevation = 1, this.highlightElevation = 1, - @required this.child, - @required this.initialValue, - @required this.items, - @required this.onSelected, + required this.child, + required this.initialValue, + required this.items, + required this.onSelected, }) : super(key: key); @override @@ -1276,7 +1260,8 @@ class _QuillDropdownButtonState extends State> { void _showMenu() { final popupMenuTheme = PopupMenuTheme.of(context); final button = context.findRenderObject() as RenderBox; - final overlay = Overlay.of(context).context.findRenderObject() as RenderBox; + final overlay = + Overlay.of(context)!.context.findRenderObject() as RenderBox; final position = RelativeRect.fromRect( Rect.fromPoints( button.localToGlobal(Offset.zero, ancestor: overlay), @@ -1296,14 +1281,14 @@ class _QuillDropdownButtonState extends State> { // widget.shape ?? popupMenuTheme.shape, color: popupMenuTheme.color, // widget.color ?? popupMenuTheme.color, // captureInheritedThemes: widget.captureInheritedThemes, - ).then((T newValue) { + ).then((T? newValue) { if (!mounted) return null; if (newValue == null) { // if (widget.onCanceled != null) widget.onCanceled(); return null; } if (widget.onSelected != null) { - widget.onSelected(newValue); + widget.onSelected!(newValue); } }); } diff --git a/pubspec.lock b/pubspec.lock index c582bed2..faffa143 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -56,7 +56,7 @@ packages: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.16.2" + version: "0.17.0" fake_async: dependency: transitive description: @@ -91,7 +91,7 @@ packages: name: filesystem_picker url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0-nullsafety.0" flutter: dependency: "direct main" description: flutter @@ -103,7 +103,7 @@ packages: name: flutter_colorpicker url: "https://pub.dartlang.org" source: hosted - version: "0.3.5" + version: "0.4.0-nullsafety.0" flutter_keyboard_visibility: dependency: "direct main" description: @@ -148,7 +148,7 @@ packages: name: html url: "https://pub.dartlang.org" source: hosted - version: "0.14.0+4" + version: "0.15.0" http: dependency: transitive description: @@ -169,7 +169,14 @@ packages: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.7.2+1" + version: "0.7.3" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" image_picker_platform_interface: dependency: transitive description: @@ -293,7 +300,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" stack_trace: dependency: transitive description: @@ -321,7 +328,7 @@ packages: name: string_validator url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.3.0" term_glyph: dependency: transitive description: @@ -356,21 +363,14 @@ packages: name: universal_html url: "https://pub.dartlang.org" source: hosted - version: "1.2.4" + version: "2.0.4" universal_io: dependency: transitive description: name: universal_io url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" - universal_ui: - dependency: "direct main" - description: - name: universal_ui - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.8" + version: "2.0.1" url_launcher: dependency: "direct main" description: @@ -426,7 +426,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.4" xdg_directories: dependency: transitive description: @@ -434,13 +434,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" - zone_local: - dependency: transitive - description: - name: zone_local - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.2" sdks: dart: ">=2.12.0 <3.0.0" - flutter: ">=1.22.0" + flutter: ">=1.24.0-10.2.pre" diff --git a/pubspec.yaml b/pubspec.yaml index b49566bc..80bc09db 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ homepage: https://bulletjournal.us/home/index.html repository: https://github.com/singerdmx/flutter-quill.git environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" dependencies: @@ -16,16 +16,16 @@ dependencies: collection: ^1.15.0 tuple: ^2.0.0 url_launcher: ^6.0.0 - flutter_colorpicker: ^0.3.5 + flutter_colorpicker: ^0.4.0-nullsafety.0 image_picker: ^0.7.2 photo_view: ^0.11.0 - universal_html: ^1.2.4 + universal_html: ^2.0.4 file_picker: ^3.0.0 - filesystem_picker: ^1.0.4 + filesystem_picker: ^2.0.0-nullsafety.0 path_provider: ^2.0.1 - string_validator: ^0.1.4 + string_validator: ^0.3.0 flutter_keyboard_visibility: ^5.0.0 - universal_ui: ^0.0.8 +# universal_ui: ^0.0.8