@@ -6,7 +6,7 @@ import 'dart:ui' as ui hide TextStyle;
6
6
import 'package:collection/collection.dart' ;
7
7
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb;
8
8
import 'package:flutter/material.dart' ;
9
- import 'package:flutter/rendering.dart' show RenderAbstractViewport ;
9
+ import 'package:flutter/rendering.dart' show RevealedOffset ;
10
10
import 'package:flutter/scheduler.dart' show SchedulerBinding;
11
11
import 'package:flutter/services.dart' ;
12
12
import 'package:flutter_keyboard_visibility_temp_fork/flutter_keyboard_visibility_temp_fork.dart'
@@ -94,7 +94,7 @@ class QuillRawEditorState extends EditorState
94
94
bool get dirty => _dirty;
95
95
bool _dirty = false ;
96
96
97
- // Completely copied from flutter:
97
+ // Completely copied from flutter with some changes to fit flutter_quill :
98
98
// https://github.com/flutter/flutter/blob/3.29.0/packages/flutter/lib/src/widgets/editable_text.dart#L3741
99
99
// Finds the closest scroll offset to the current scroll offset that fully
100
100
// reveals the given caret rect. If the given rect's main axis extent is too
@@ -110,44 +110,37 @@ class QuillRawEditorState extends EditorState
110
110
return RevealedOffset (offset: _scrollController.offset, rect: rect);
111
111
}
112
112
113
- final Size editableSize = renderEditable .size;
113
+ final editableSize = renderEditor .size;
114
114
final double additionalOffset;
115
115
final Offset unitOffset;
116
116
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
+ );
134
128
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 );
141
134
142
135
// No overscrolling when encountering tall fonts/scripts that extend past
143
136
// the ascent.
144
- final double targetOffset = clampDouble (
137
+ final targetOffset = ui. clampDouble (
145
138
additionalOffset + _scrollController.offset,
146
139
_scrollController.position.minScrollExtent,
147
140
_scrollController.position.maxScrollExtent,
148
141
);
149
142
150
- final double offsetDelta = _scrollController.offset - targetOffset;
143
+ final offsetDelta = _scrollController.offset - targetOffset;
151
144
return RevealedOffset (
152
145
rect: rect.shift (unitOffset * offsetDelta), offset: targetOffset);
153
146
}
@@ -1183,70 +1176,76 @@ class QuillRawEditorState extends EditorState
1183
1176
1184
1177
bool _showCaretOnScreenScheduled = false ;
1185
1178
1186
- // Completely copied from flutter:
1179
+ // Completely copied from flutter with some changes to fit flutter_quill :
1187
1180
// https://github.com/flutter/flutter/blob/3.29.0/packages/flutter/lib/src/widgets/editable_text.dart#L4228
1188
1181
void _scheduleShowCaretOnScreen ({required bool withAnimation}) {
1189
1182
if (_showCaretOnScreenScheduled) {
1190
1183
return ;
1191
1184
}
1192
1185
_showCaretOnScreenScheduled = true ;
1193
- SchedulerBinding .instance.addPostFrameCallback ((Duration _) {
1186
+ SchedulerBinding .instance.addPostFrameCallback ((_) {
1194
1187
_showCaretOnScreenScheduled = false ;
1195
1188
// Since we are in a post frame callback, check currentContext in case
1196
1189
// 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 ) ||
1201
- ! _scrollController.hasClients) {
1190
+ if (! renderEditor.selection.isValid || ! _scrollController.hasClients) {
1202
1191
return ;
1203
1192
}
1204
1193
1205
- final double lineHeight = renderEditable.preferredLineHeight;
1194
+ final lineHeight =
1195
+ renderEditor.preferredLineHeight (renderEditor.caretTextPosition);
1206
1196
1207
1197
// Enlarge the target rect by scrollPadding to ensure that caret is not
1208
1198
// 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 (
1199
+ var bottomSpacing = widget.config.padding.bottom;
1200
+ if (_selectionOverlay? .selectionCtrls != null ) {
1201
+ final handleHeight =
1202
+ _selectionOverlay! .selectionCtrls.getHandleSize (lineHeight).height;
1203
+
1204
+ final double interactiveHandleHeight = math.max (
1205
+ handleHeight,
1206
+ kMinInteractiveDimension,
1207
+ );
1208
+
1209
+ final anchor = _selectionOverlay! .selectionCtrls.getHandleAnchor (
1218
1210
TextSelectionHandleType .collapsed,
1219
1211
lineHeight,
1220
1212
);
1221
- final double handleCenter = handleHeight / 2 - anchor.dy;
1222
- bottomSpacing =
1223
- math.max (handleCenter + interactiveHandleHeight / 2 , bottomSpacing);
1213
+
1214
+ final handleCenter = handleHeight / 2 - anchor.dy;
1215
+ bottomSpacing = math.max (
1216
+ handleCenter + interactiveHandleHeight / 2 ,
1217
+ bottomSpacing,
1218
+ );
1224
1219
}
1225
1220
1226
- final EdgeInsets caretPadding =
1227
- widget.scrollPadding .copyWith (bottom: bottomSpacing);
1221
+ final caretPadding =
1222
+ widget.config.padding .copyWith (bottom: bottomSpacing);
1228
1223
1229
- final Rect caretRect =
1230
- renderEditable .getLocalRectForCaret (renderEditable.selection ! .extent );
1231
- final RevealedOffset targetOffset = _getOffsetToRevealCaret (caretRect);
1224
+ final caretRect =
1225
+ renderEditor .getLocalRectForCaret (renderEditor.caretTextPosition );
1226
+ final targetOffset = _getOffsetToRevealCaret (caretRect);
1232
1227
1233
- final Rect rectToReveal;
1234
- final TextSelection selection = textEditingValue.selection;
1228
+ Rect ? rectToReveal;
1229
+ final selection = textEditingValue.selection;
1235
1230
if (selection.isCollapsed) {
1236
1231
rectToReveal = targetOffset.rect;
1237
1232
} 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
- }
1233
+ // TODO: I'm not sure how to get getBoxesForSelection in flutter_quill or do we even has it?
1234
+ // Currently just return targetOffset.rect.
1235
+ //
1236
+ // final List<TextBox> selectionBoxes =
1237
+ // renderEditor.getBoxesForSelection(selection);
1238
+ // // selectionBoxes may be empty if, for example, the selection does not
1239
+ // // encompass a full character, like if it only contained part of an
1240
+ // // extended grapheme cluster.
1241
+ // if (selectionBoxes.isEmpty) {
1242
+ // rectToReveal = targetOffset.rect;
1243
+ // } else {
1244
+ // rectToReveal = selection.baseOffset < selection.extentOffset
1245
+ // ? selectionBoxes.last.toRect()
1246
+ // : selectionBoxes.first.toRect();
1247
+ // }
1248
+ rectToReveal = targetOffset.rect;
1250
1249
}
1251
1250
1252
1251
if (withAnimation) {
@@ -1255,15 +1254,14 @@ class QuillRawEditorState extends EditorState
1255
1254
duration: _caretAnimationDuration,
1256
1255
curve: _caretAnimationCurve,
1257
1256
);
1258
- renderEditable .showOnScreen (
1257
+ renderEditor .showOnScreen (
1259
1258
rect: caretPadding.inflateRect (rectToReveal),
1260
1259
duration: _caretAnimationDuration,
1261
1260
curve: _caretAnimationCurve,
1262
1261
);
1263
1262
} else {
1264
1263
_scrollController.jumpTo (targetOffset.offset);
1265
- renderEditable.showOnScreen (
1266
- rect: caretPadding.inflateRect (rectToReveal));
1264
+ renderEditor.showOnScreen (rect: caretPadding.inflateRect (rectToReveal));
1267
1265
}
1268
1266
}, debugLabel: 'EditableText.showCaret' );
1269
1267
}
0 commit comments