diff --git a/lib/flutter_quill.dart b/lib/flutter_quill.dart index c38ea4df..ec8a8163 100644 --- a/lib/flutter_quill.dart +++ b/lib/flutter_quill.dart @@ -6,9 +6,9 @@ export 'src/models/documents/nodes/embeddable.dart'; export 'src/models/documents/nodes/leaf.dart'; export 'src/models/documents/style.dart'; export 'src/models/quill_delta.dart'; +export 'src/models/themes/quill_custom_icon.dart'; export 'src/models/themes/quill_dialog_theme.dart'; export 'src/models/themes/quill_icon_theme.dart'; -export 'src/models/themes/quill_custom_icon.dart'; export 'src/widgets/controller.dart'; export 'src/widgets/default_styles.dart'; export 'src/widgets/editor.dart'; diff --git a/lib/src/widgets/raw_editor.dart b/lib/src/widgets/raw_editor.dart index 2ba0532c..8745ccde 100644 --- a/lib/src/widgets/raw_editor.dart +++ b/lib/src/widgets/raw_editor.dart @@ -896,6 +896,14 @@ class RawEditorState extends EditorState if (kIsWeb) { return false; } + + // selectionOverlay is aggressively released when selection is collapsed + // to remove unnecessary handles. Since a toolbar is requested here, + // attempt to create the selectionOverlay if it's not already created. + if (_selectionOverlay == null) { + _updateOrDisposeSelectionOverlayIfNeeded(); + } + if (_selectionOverlay == null || _selectionOverlay!.toolbar != null) { return false; } diff --git a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart index 8ea0f337..7363809a 100644 --- a/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart +++ b/lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart @@ -71,13 +71,18 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState @override void bringIntoView(TextPosition position) { - final localRect = renderEditor.getLocalRectForCaret(position); - final targetOffset = _getOffsetToRevealCaret(localRect, position); - - if (scrollController.hasClients) { - scrollController.jumpTo(targetOffset.offset); + // Ignore errors if position is invalid (i.e. paste on iOS when editor + // has no content and user pasted from toolbar) + try { + final localRect = renderEditor.getLocalRectForCaret(position); + final targetOffset = _getOffsetToRevealCaret(localRect, position); + + if (scrollController.hasClients) { + scrollController.jumpTo(targetOffset.offset); + } + renderEditor.showOnScreen(rect: targetOffset.rect); + } catch (_) { } - renderEditor.showOnScreen(rect: targetOffset.rect); } // Finds the closest scroll offset to the current scroll offset that fully diff --git a/lib/src/widgets/text_block.dart b/lib/src/widgets/text_block.dart index 26305179..cd0d2c36 100644 --- a/lib/src/widgets/text_block.dart +++ b/lib/src/widgets/text_block.dart @@ -272,6 +272,9 @@ class EditableTextBlock extends StatelessWidget { lineSpacing = defaultStyles!.code!.lineSpacing; } else if (attrs.containsKey(Attribute.align.key)) { lineSpacing = defaultStyles!.align!.lineSpacing; + } else { + // use paragraph linespacing as a default + lineSpacing = defaultStyles!.paragraph!.lineSpacing; } top = lineSpacing.item1; bottom = lineSpacing.item2; diff --git a/lib/src/widgets/toolbar.dart b/lib/src/widgets/toolbar.dart index 0951221d..a2e0aada 100644 --- a/lib/src/widgets/toolbar.dart +++ b/lib/src/widgets/toolbar.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import 'package:i18n_extension/i18n_widget.dart'; import '../models/documents/attribute.dart'; +import '../models/themes/quill_custom_icon.dart'; import '../models/themes/quill_dialog_theme.dart'; import '../models/themes/quill_icon_theme.dart'; -import '../models/themes/quill_custom_icon.dart'; import 'controller.dart'; import 'toolbar/arrow_indicated_button_list.dart'; import 'toolbar/camera_button.dart'; @@ -17,13 +17,13 @@ import 'toolbar/image_button.dart'; import 'toolbar/image_video_utils.dart'; import 'toolbar/indent_button.dart'; import 'toolbar/link_style_button.dart'; +import 'toolbar/quill_dropdown_button.dart'; +import 'toolbar/quill_icon_button.dart'; import 'toolbar/select_alignment_button.dart'; import 'toolbar/select_header_style_button.dart'; import 'toolbar/toggle_check_list_button.dart'; import 'toolbar/toggle_style_button.dart'; import 'toolbar/video_button.dart'; -import 'toolbar/quill_dropdown_button.dart'; -import 'toolbar/quill_icon_button.dart'; export 'toolbar/clear_format_button.dart'; export 'toolbar/color_button.dart'; diff --git a/lib/src/widgets/toolbar/quill_dropdown_button.dart b/lib/src/widgets/toolbar/quill_dropdown_button.dart index ecd582cf..0b4671b0 100644 --- a/lib/src/widgets/toolbar/quill_dropdown_button.dart +++ b/lib/src/widgets/toolbar/quill_dropdown_button.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import '../../models/themes/quill_icon_theme.dart'; -import '../../models/documents/style.dart'; + import '../../models/documents/attribute.dart'; +import '../../models/documents/style.dart'; +import '../../models/themes/quill_icon_theme.dart'; import '../controller.dart'; class QuillDropdownButton extends StatefulWidget { @@ -92,7 +93,7 @@ class _QuillDropdownButtonState extends State> { @override Widget build(BuildContext context) { return ConstrainedBox( - constraints: BoxConstraints.tightFor(height: (widget.iconSize * 1.81)), + constraints: BoxConstraints.tightFor(height: widget.iconSize * 1.81), child: RawMaterialButton( visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder( @@ -160,7 +161,7 @@ class _QuillDropdownButtonState extends State> { fontSize: widget.iconSize / 1.15, color: widget.iconTheme?.iconUnselectedColor ?? theme.iconTheme.color)), - SizedBox(width: 3), + const SizedBox(width: 3), Icon(Icons.arrow_drop_down, size: widget.iconSize / 1.15, color: widget.iconTheme?.iconUnselectedColor ??