@@ -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,80 @@ 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 ) ||
1190
+ final renderEditor =
1191
+ _editorKey .currentContext? .findRenderObject () as RenderEditor ? ;
1192
+ if (renderEditor == null ||
1193
+ ! renderEditor .selection.isValid ||
1201
1194
! _scrollController.hasClients) {
1202
1195
return ;
1203
1196
}
1204
1197
1205
- final double lineHeight = renderEditable.preferredLineHeight;
1198
+ final lineHeight =
1199
+ renderEditor.preferredLineHeight (renderEditor.caretTextPosition);
1206
1200
1207
1201
// Enlarge the target rect by scrollPadding to ensure that caret is not
1208
1202
// 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 (
1218
1214
TextSelectionHandleType .collapsed,
1219
1215
lineHeight,
1220
1216
);
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
+ );
1224
1223
}
1225
1224
1226
- final EdgeInsets caretPadding =
1227
- widget.scrollPadding .copyWith (bottom: bottomSpacing);
1225
+ final caretPadding =
1226
+ widget.config.padding .copyWith (bottom: bottomSpacing);
1228
1227
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);
1232
1231
1233
- final Rect rectToReveal;
1234
- final TextSelection selection = textEditingValue.selection;
1232
+ Rect ? rectToReveal;
1233
+ final selection = textEditingValue.selection;
1235
1234
if (selection.isCollapsed) {
1236
1235
rectToReveal = targetOffset.rect;
1237
1236
} 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;
1250
1253
}
1251
1254
1252
1255
if (withAnimation) {
@@ -1255,15 +1258,14 @@ class QuillRawEditorState extends EditorState
1255
1258
duration: _caretAnimationDuration,
1256
1259
curve: _caretAnimationCurve,
1257
1260
);
1258
- renderEditable .showOnScreen (
1261
+ renderEditor .showOnScreen (
1259
1262
rect: caretPadding.inflateRect (rectToReveal),
1260
1263
duration: _caretAnimationDuration,
1261
1264
curve: _caretAnimationCurve,
1262
1265
);
1263
1266
} else {
1264
1267
_scrollController.jumpTo (targetOffset.offset);
1265
- renderEditable.showOnScreen (
1266
- rect: caretPadding.inflateRect (rectToReveal));
1268
+ renderEditor.showOnScreen (rect: caretPadding.inflateRect (rectToReveal));
1267
1269
}
1268
1270
}, debugLabel: 'EditableText.showCaret' );
1269
1271
}
0 commit comments