@@ -6,7 +6,7 @@ import 'dart:ui' as ui hide TextStyle;
66import 'package:collection/collection.dart' ;
77import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb;
88import 'package:flutter/material.dart' ;
9- import 'package:flutter/rendering.dart' show RenderAbstractViewport ;
9+ import 'package:flutter/rendering.dart' show RenderEditable, RevealedOffset ;
1010import 'package:flutter/scheduler.dart' show SchedulerBinding;
1111import 'package:flutter/services.dart' ;
1212import 'package:flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork.dart'
@@ -94,7 +94,7 @@ class QuillRawEditorState extends EditorState
9494 bool get dirty => _dirty;
9595 bool _dirty = false ;
9696
97- // Completely copied from flutter:
97+ // Completely copied from flutter with some changes to fit flutter_quill :
9898 // https://github.com/flutter/flutter/blob/3.29.0/packages/flutter/lib/src/widgets/editable_text.dart#L3741
9999 // Finds the closest scroll offset to the current scroll offset that fully
100100 // reveals the given caret rect. If the given rect's main axis extent is too
@@ -110,44 +110,37 @@ class QuillRawEditorState extends EditorState
110110 return RevealedOffset (offset: _scrollController.offset, rect: rect);
111111 }
112112
113- final Size editableSize = renderEditable .size;
113+ final editableSize = renderEditor .size;
114114 final double additionalOffset;
115115 final Offset unitOffset;
116116
117- if (! _isMultiline) {
118- additionalOffset = rect.width >= editableSize.width
119- // Center `rect` if it's oversized.
120- ? editableSize.width / 2 - rect.center.dx
121- // Valid additional offsets range from (rect.right - size.width)
122- // to (rect.left). Pick the closest one if out of range.
123- : clampDouble (0.0 , rect.right - editableSize.width, rect.left);
124- unitOffset = const Offset (1 , 0 );
125- } else {
126- // The caret is vertically centered within the line. Expand the caret's
127- // height so that it spans the line because we're going to ensure that the
128- // entire expanded caret is scrolled into view.
129- final Rect expandedRect = Rect .fromCenter (
130- center: rect.center,
131- width: rect.width,
132- height: math.max (rect.height, renderEditable.preferredLineHeight),
133- );
117+ // The caret is vertically centered within the line. Expand the caret's
118+ // height so that it spans the line because we're going to ensure that the
119+ // entire expanded caret is scrolled into view.
120+ final expandedRect = Rect .fromCenter (
121+ center: rect.center,
122+ width: rect.width,
123+ height: math.max (
124+ rect.height,
125+ renderEditor.preferredLineHeight (renderEditor.caretTextPosition),
126+ ),
127+ );
134128
135- additionalOffset = expandedRect.height >= editableSize.height
136- ? editableSize.height / 2 - expandedRect.center.dy
137- : clampDouble (
138- 0.0 , expandedRect.bottom - editableSize.height, expandedRect.top);
139- unitOffset = const Offset (0 , 1 );
140- }
129+ additionalOffset = expandedRect.height >= editableSize.height
130+ ? editableSize.height / 2 - expandedRect.center.dy
131+ : ui.clampDouble (
132+ 0 , expandedRect.bottom - editableSize.height, expandedRect.top);
133+ unitOffset = const Offset (0 , 1 );
141134
142135 // No overscrolling when encountering tall fonts/scripts that extend past
143136 // the ascent.
144- final double targetOffset = clampDouble (
137+ final targetOffset = ui. clampDouble (
145138 additionalOffset + _scrollController.offset,
146139 _scrollController.position.minScrollExtent,
147140 _scrollController.position.maxScrollExtent,
148141 );
149142
150- final double offsetDelta = _scrollController.offset - targetOffset;
143+ final offsetDelta = _scrollController.offset - targetOffset;
151144 return RevealedOffset (
152145 rect: rect.shift (unitOffset * offsetDelta), offset: targetOffset);
153146 }
@@ -1183,70 +1176,80 @@ class QuillRawEditorState extends EditorState
11831176
11841177 bool _showCaretOnScreenScheduled = false ;
11851178
1186- // Completely copied from flutter:
1179+ // Completely copied from flutter with some changes to fit flutter_quill :
11871180 // https://github.com/flutter/flutter/blob/3.29.0/packages/flutter/lib/src/widgets/editable_text.dart#L4228
11881181 void _scheduleShowCaretOnScreen ({required bool withAnimation}) {
11891182 if (_showCaretOnScreenScheduled) {
11901183 return ;
11911184 }
11921185 _showCaretOnScreenScheduled = true ;
1193- SchedulerBinding .instance.addPostFrameCallback ((Duration _) {
1186+ SchedulerBinding .instance.addPostFrameCallback ((_) {
11941187 _showCaretOnScreenScheduled = false ;
11951188 // Since we are in a post frame callback, check currentContext in case
11961189 // RenderEditable has been disposed (in which case it will be null).
1197- final RenderEditable ? renderEditable =
1198- _editableKey .currentContext? .findRenderObject () as RenderEditable ? ;
1199- if (renderEditable == null ||
1200- ! (renderEditable .selection? .isValid ?? false ) ||
1190+ final renderEditor =
1191+ _editorKey .currentContext? .findRenderObject () as RenderEditor ? ;
1192+ if (renderEditor == null ||
1193+ ! renderEditor .selection.isValid ||
12011194 ! _scrollController.hasClients) {
12021195 return ;
12031196 }
12041197
1205- final double lineHeight = renderEditable.preferredLineHeight;
1198+ final lineHeight =
1199+ renderEditor.preferredLineHeight (renderEditor.caretTextPosition);
12061200
12071201 // Enlarge the target rect by scrollPadding to ensure that caret is not
12081202 // positioned directly at the edge after scrolling.
1209- double bottomSpacing = widget.scrollPadding.bottom;
1210- if (_selectionOverlay? .selectionControls != null ) {
1211- final double handleHeight = _selectionOverlay! .selectionControls!
1212- .getHandleSize (lineHeight)
1213- .height;
1214- final double interactiveHandleHeight =
1215- math.max (handleHeight, kMinInteractiveDimension);
1216- final Offset anchor =
1217- _selectionOverlay! .selectionControls! .getHandleAnchor (
1203+ var bottomSpacing = widget.config.padding.bottom;
1204+ if (_selectionOverlay? .selectionCtrls != null ) {
1205+ final handleHeight =
1206+ _selectionOverlay! .selectionCtrls.getHandleSize (lineHeight).height;
1207+
1208+ final double interactiveHandleHeight = math.max (
1209+ handleHeight,
1210+ kMinInteractiveDimension,
1211+ );
1212+
1213+ final anchor = _selectionOverlay! .selectionCtrls.getHandleAnchor (
12181214 TextSelectionHandleType .collapsed,
12191215 lineHeight,
12201216 );
1221- final double handleCenter = handleHeight / 2 - anchor.dy;
1222- bottomSpacing =
1223- math.max (handleCenter + interactiveHandleHeight / 2 , bottomSpacing);
1217+
1218+ final handleCenter = handleHeight / 2 - anchor.dy;
1219+ bottomSpacing = math.max (
1220+ handleCenter + interactiveHandleHeight / 2 ,
1221+ bottomSpacing,
1222+ );
12241223 }
12251224
1226- final EdgeInsets caretPadding =
1227- widget.scrollPadding .copyWith (bottom: bottomSpacing);
1225+ final caretPadding =
1226+ widget.config.padding .copyWith (bottom: bottomSpacing);
12281227
1229- final Rect caretRect =
1230- renderEditable .getLocalRectForCaret (renderEditable.selection ! .extent );
1231- final RevealedOffset targetOffset = _getOffsetToRevealCaret (caretRect);
1228+ final caretRect =
1229+ renderEditor .getLocalRectForCaret (renderEditor.caretTextPosition );
1230+ final targetOffset = _getOffsetToRevealCaret (caretRect);
12321231
1233- final Rect rectToReveal;
1234- final TextSelection selection = textEditingValue.selection;
1232+ Rect ? rectToReveal;
1233+ final selection = textEditingValue.selection;
12351234 if (selection.isCollapsed) {
12361235 rectToReveal = targetOffset.rect;
12371236 } else {
1238- final List <TextBox > selectionBoxes =
1239- renderEditable.getBoxesForSelection (selection);
1240- // selectionBoxes may be empty if, for example, the selection does not
1241- // encompass a full character, like if it only contained part of an
1242- // extended grapheme cluster.
1243- if (selectionBoxes.isEmpty) {
1244- rectToReveal = targetOffset.rect;
1245- } else {
1246- rectToReveal = selection.baseOffset < selection.extentOffset
1247- ? selectionBoxes.last.toRect ()
1248- : selectionBoxes.first.toRect ();
1249- }
1237+ // TODO: I'm not sure how to get getBoxesForSelection in flutter_quill or do we even has it?
1238+ // Currently just return targetOffset.rect.
1239+ //
1240+ // final List<TextBox> selectionBoxes =
1241+ // renderEditor.getBoxesForSelection(selection);
1242+ // // selectionBoxes may be empty if, for example, the selection does not
1243+ // // encompass a full character, like if it only contained part of an
1244+ // // extended grapheme cluster.
1245+ // if (selectionBoxes.isEmpty) {
1246+ // rectToReveal = targetOffset.rect;
1247+ // } else {
1248+ // rectToReveal = selection.baseOffset < selection.extentOffset
1249+ // ? selectionBoxes.last.toRect()
1250+ // : selectionBoxes.first.toRect();
1251+ // }
1252+ rectToReveal = targetOffset.rect;
12501253 }
12511254
12521255 if (withAnimation) {
@@ -1255,15 +1258,14 @@ class QuillRawEditorState extends EditorState
12551258 duration: _caretAnimationDuration,
12561259 curve: _caretAnimationCurve,
12571260 );
1258- renderEditable .showOnScreen (
1261+ renderEditor .showOnScreen (
12591262 rect: caretPadding.inflateRect (rectToReveal),
12601263 duration: _caretAnimationDuration,
12611264 curve: _caretAnimationCurve,
12621265 );
12631266 } else {
12641267 _scrollController.jumpTo (targetOffset.offset);
1265- renderEditable.showOnScreen (
1266- rect: caretPadding.inflateRect (rectToReveal));
1268+ renderEditor.showOnScreen (rect: caretPadding.inflateRect (rectToReveal));
12671269 }
12681270 }, debugLabel: 'EditableText.showCaret' );
12691271 }
0 commit comments