Skip to content

Commit 461b0e3

Browse files
[Chat] - MessagePageScaffold: Prevent possibly negative layout constraints on bottom sheet.
1 parent 68d0ee3 commit 461b0e3

File tree

1 file changed

+46
-79
lines changed

1 file changed

+46
-79
lines changed

super_editor/lib/src/chat/message_page_scaffold.dart

Lines changed: 46 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ class MessagePageScaffold extends RenderObjectWidget {
6363
}
6464

6565
@override
66-
void updateRenderObject(
67-
BuildContext context, RenderMessagePageScaffold renderObject) {
66+
void updateRenderObject(BuildContext context, RenderMessagePageScaffold renderObject) {
6867
renderObject
6968
..bottomSheetMinimumTopGap = bottomSheetMinimumTopGap
7069
..bottomSheetMinimumHeight = bottomSheetMinimumHeight;
@@ -76,8 +75,7 @@ class MessagePageScaffold extends RenderObjectWidget {
7675
}
7776

7877
/// Builder that builds the content subtree within a [MessagePageScaffold].
79-
typedef MessagePageScaffoldContentBuilder = Widget Function(
80-
BuildContext context, double bottomSpacing);
78+
typedef MessagePageScaffoldContentBuilder = Widget Function(BuildContext context, double bottomSpacing);
8179

8280
/// Height sizing policy for a bottom sheet within a [MessagePageScaffold].
8381
enum BottomSheetMode {
@@ -104,8 +102,7 @@ enum BottomSheetMode {
104102
/// Controller for a [MessagePageScaffold].
105103
class MessagePageController with ChangeNotifier {
106104
MessagePageSheetHeightPolicy get sheetHeightPolicy => _sheetHeightPolicy;
107-
MessagePageSheetHeightPolicy _sheetHeightPolicy =
108-
MessagePageSheetHeightPolicy.minimumHeight;
105+
MessagePageSheetHeightPolicy _sheetHeightPolicy = MessagePageSheetHeightPolicy.minimumHeight;
109106
set sheetHeightPolicy(MessagePageSheetHeightPolicy policy) {
110107
if (policy == _sheetHeightPolicy) {
111108
return;
@@ -116,12 +113,12 @@ class MessagePageController with ChangeNotifier {
116113
}
117114

118115
bool get isPreview =>
119-
_collapsedMode == MessagePageSheetCollapsedMode.preview &&
116+
_collapsedMode == MessagePageSheetCollapsedMode.preview && //
120117
!isSliding &&
121118
!isDragging;
122119

123120
bool get isIntrinsic =>
124-
_collapsedMode == MessagePageSheetCollapsedMode.intrinsic &&
121+
_collapsedMode == MessagePageSheetCollapsedMode.intrinsic && //
125122
!isSliding &&
126123
!isDragging;
127124

@@ -137,12 +134,12 @@ class MessagePageController with ChangeNotifier {
137134
}
138135

139136
bool get isCollapsed =>
140-
_desiredSheetMode == MessagePageSheetMode.collapsed &&
137+
_desiredSheetMode == MessagePageSheetMode.collapsed && //
141138
!isSliding &&
142139
!isDragging;
143140

144141
bool get isExpanded =>
145-
_desiredSheetMode == MessagePageSheetMode.expanded &&
142+
_desiredSheetMode == MessagePageSheetMode.expanded && //
146143
!isSliding &&
147144
!isDragging;
148145

@@ -304,8 +301,7 @@ class MessagePageElement extends RenderObjectElement {
304301
MessagePageScaffold get widget => super.widget as MessagePageScaffold;
305302

306303
@override
307-
RenderMessagePageScaffold get renderObject =>
308-
super.renderObject as RenderMessagePageScaffold;
304+
RenderMessagePageScaffold get renderObject => super.renderObject as RenderMessagePageScaffold;
309305

310306
@override
311307
void mount(Element? parent, Object? newSlot) {
@@ -320,8 +316,7 @@ class MessagePageElement extends RenderObjectElement {
320316
_contentSlot,
321317
);
322318

323-
_bottomSheet =
324-
inflateWidget(widget.bottomSheetBuilder(this), _bottomSheetSlot);
319+
_bottomSheet = inflateWidget(widget.bottomSheetBuilder(this), _bottomSheetSlot);
325320
}
326321

327322
@override
@@ -368,13 +363,11 @@ class MessagePageElement extends RenderObjectElement {
368363
//
369364
// We don't rebuild our content widget because we only want content to
370365
// build during layout.
371-
updateChild(
372-
_bottomSheet, widget.bottomSheetBuilder(this), _bottomSheetSlot);
366+
updateChild(_bottomSheet, widget.bottomSheetBuilder(this), _bottomSheetSlot);
373367
}
374368

375369
void buildContent(double bottomSpacing) {
376-
messagePageElementLog
377-
.info('ContentLayersElement ($hashCode) - (re)building layers');
370+
messagePageElementLog.info('ContentLayersElement ($hashCode) - (re)building layers');
378371

379372
owner!.buildScope(this, () {
380373
if (_content == null) {
@@ -396,11 +389,8 @@ class MessagePageElement extends RenderObjectElement {
396389
void update(MessagePageScaffold newWidget) {
397390
super.update(newWidget);
398391

399-
_content =
400-
updateChild(_content, widget.contentBuilder(this, 0), _contentSlot) ??
401-
_content;
402-
_bottomSheet = updateChild(
403-
_bottomSheet, widget.bottomSheetBuilder(this), _bottomSheetSlot);
392+
_content = updateChild(_content, widget.contentBuilder(this, 0), _contentSlot) ?? _content;
393+
_bottomSheet = updateChild(_bottomSheet, widget.bottomSheetBuilder(this), _bottomSheetSlot);
404394
}
405395

406396
@override
@@ -619,8 +609,7 @@ class RenderMessagePageScaffold extends RenderBox {
619609
_currentDesiredGlobalTopY = _controller.desiredGlobalTopY;
620610

621611
final pageGlobalBottom = localToGlobal(Offset(0, size.height)).dy;
622-
_desiredDragHeight = pageGlobalBottom -
623-
max(_currentDesiredGlobalTopY!, _bottomSheetMinimumTopGap);
612+
_desiredDragHeight = pageGlobalBottom - max(_currentDesiredGlobalTopY!, _bottomSheetMinimumTopGap);
624613
_expandedHeight = size.height - _bottomSheetMinimumTopGap;
625614

626615
_velocityTracker.addPosition(
@@ -649,8 +638,7 @@ class RenderMessagePageScaffold extends RenderBox {
649638
_isExpandingOrCollapsing = true;
650639
_velocityStopwatch.stop();
651640

652-
final velocity =
653-
_velocityTracker.getVelocityEstimate()?.pixelsPerSecond.dy ?? 0;
641+
final velocity = _velocityTracker.getVelocityEstimate()?.pixelsPerSecond.dy ?? 0;
654642

655643
_startBottomSheetHeightSimulation(velocity: velocity);
656644
}
@@ -669,8 +657,7 @@ class RenderMessagePageScaffold extends RenderBox {
669657
? velocity < 0
670658
? MessagePageSheetMode.expanded
671659
: MessagePageSheetMode.collapsed
672-
: (_expandedHeight - _desiredDragHeight!).abs() <
673-
(_desiredDragHeight! - minimizedHeight).abs()
660+
: (_expandedHeight - _desiredDragHeight!).abs() < (_desiredDragHeight! - minimizedHeight).abs()
674661
? MessagePageSheetMode.expanded
675662
: MessagePageSheetMode.collapsed;
676663

@@ -698,10 +685,7 @@ class RenderMessagePageScaffold extends RenderBox {
698685

699686
final startHeight = _bottomSheet!.size.height;
700687
_simulationGoalMode = _controller.desiredSheetMode;
701-
_simulationGoalHeight =
702-
_simulationGoalMode! == MessagePageSheetMode.expanded
703-
? _expandedHeight
704-
: minimizedHeight;
688+
_simulationGoalHeight = _simulationGoalMode! == MessagePageSheetMode.expanded ? _expandedHeight : minimizedHeight;
705689

706690
messagePageLayoutLog.info('Creating expand/collapse simulation:');
707691
messagePageLayoutLog.info(
@@ -856,8 +840,7 @@ class RenderMessagePageScaffold extends RenderBox {
856840
childDiagnostics.add(_content!.toDiagnosticsNode(name: 'content'));
857841
}
858842
if (_bottomSheet != null) {
859-
childDiagnostics
860-
.add(_bottomSheet!.toDiagnosticsNode(name: 'message_editor'));
843+
childDiagnostics.add(_bottomSheet!.toDiagnosticsNode(name: 'message_editor'));
861844
}
862845

863846
return childDiagnostics;
@@ -907,8 +890,8 @@ class RenderMessagePageScaffold extends RenderBox {
907890
void performLayout() {
908891
messagePageLayoutLog.info('---------- LAYOUT -------------');
909892
messagePageLayoutLog.info('Laying out RenderChatScaffold');
910-
messagePageLayoutLog.info(
911-
'Sheet mode: ${_controller.desiredSheetMode}, collapsed mode: ${_controller.collapsedMode}');
893+
messagePageLayoutLog
894+
.info('Sheet mode: ${_controller.desiredSheetMode}, collapsed mode: ${_controller.collapsedMode}');
912895
if (_content == null) {
913896
size = Size.zero;
914897
_bottomSheetNeedsLayout = false;
@@ -927,9 +910,7 @@ class RenderMessagePageScaffold extends RenderBox {
927910
// sheet, bounded within its min/max height.
928911
_overrideSheetMode = BottomSheetMode.preview;
929912

930-
_previewHeight = _bottomSheet!
931-
.computeDryLayout(constraints.copyWith(minHeight: 0))
932-
.height;
913+
_previewHeight = _bottomSheet!.computeDryLayout(constraints.copyWith(minHeight: 0)).height;
933914

934915
_overrideSheetMode = null;
935916
messagePageLayoutLog.info(
@@ -982,7 +963,8 @@ class RenderMessagePageScaffold extends RenderBox {
982963

983964
_bottomSheet!.layout(
984965
bottomSheetConstraints.copyWith(
985-
minHeight: _animatedHeight - 1,
966+
minHeight: max(_animatedHeight - 1, 0),
967+
// ^ prevent a layout boundary
986968
maxHeight: _animatedHeight,
987969
),
988970
parentUsesSize: true,
@@ -992,13 +974,13 @@ class RenderMessagePageScaffold extends RenderBox {
992974
messagePageLayoutLog.info(
993975
' - drag height: $_desiredDragHeight, minimized height: $minimizedHeight',
994976
);
995-
final strictHeight =
996-
_desiredDragHeight!.clamp(minimizedHeight, _bottomSheetMaximumHeight);
977+
final strictHeight = _desiredDragHeight!.clamp(minimizedHeight, _bottomSheetMaximumHeight);
997978

998979
messagePageLayoutLog.info(' - bounded drag height: $strictHeight');
999980
_bottomSheet!.layout(
1000981
bottomSheetConstraints.copyWith(
1001-
minHeight: strictHeight - 1,
982+
minHeight: max(strictHeight - 1, 0),
983+
// ^ prevent layout boundary
1002984
maxHeight: strictHeight,
1003985
),
1004986
parentUsesSize: true,
@@ -1011,27 +993,24 @@ class RenderMessagePageScaffold extends RenderBox {
1011993

1012994
_bottomSheet!.layout(
1013995
bottomSheetConstraints.copyWith(
1014-
minHeight: _expandedHeight - 1,
996+
minHeight: max(_expandedHeight - 1, 0),
1015997
// ^ Prevent a layout boundary.
1016998
maxHeight: _expandedHeight,
1017999
),
10181000
parentUsesSize: true,
10191001
);
10201002
} else {
10211003
messagePageLayoutLog.info('>>>>>>>> Minimized');
1022-
messagePageLayoutLog.info(
1023-
'Running standard editor layout with constraints: $bottomSheetConstraints');
1004+
messagePageLayoutLog.info('Running standard editor layout with constraints: $bottomSheetConstraints');
10241005
_bottomSheet!.layout(
10251006
bottomSheetConstraints,
10261007
parentUsesSize: true,
10271008
);
10281009
}
10291010

1030-
(_bottomSheet!.parentData! as BoxParentData).offset =
1031-
Offset(0, size.height - _bottomSheet!.size.height);
1011+
(_bottomSheet!.parentData! as BoxParentData).offset = Offset(0, size.height - _bottomSheet!.size.height);
10321012
_bottomSheetNeedsLayout = false;
1033-
messagePageLayoutLog
1034-
.info('Bottom sheet height: ${_bottomSheet!.size.height}');
1013+
messagePageLayoutLog.info('Bottom sheet height: ${_bottomSheet!.size.height}');
10351014

10361015
// Now that we know the size of the message editor, build the content based
10371016
// on the bottom spacing needed to push above the editor.
@@ -1051,11 +1030,9 @@ class RenderMessagePageScaffold extends RenderBox {
10511030
}
10521031

10531032
double _calculateBoundedIntrinsicHeight(BoxConstraints constraints) {
1054-
messagePageLayoutLog.info(
1055-
'Running dry layout on bottom sheet content to find the intrinsic height...');
1033+
messagePageLayoutLog.info('Running dry layout on bottom sheet content to find the intrinsic height...');
10561034
messagePageLayoutLog.info(' - Bottom sheet constraints: $constraints');
1057-
messagePageLayoutLog
1058-
.info(' - Controller desired sheet mode: ${_controller.collapsedMode}');
1035+
messagePageLayoutLog.info(' - Controller desired sheet mode: ${_controller.collapsedMode}');
10591036
_overrideSheetMode = BottomSheetMode.intrinsic;
10601037
messagePageLayoutLog.info(' - Override sheet mode: $_overrideSheetMode');
10611038

@@ -1066,8 +1043,7 @@ class RenderMessagePageScaffold extends RenderBox {
10661043
.height;
10671044

10681045
_overrideSheetMode = null;
1069-
messagePageLayoutLog
1070-
.info(" - Child's self-chosen height is: $bottomSheetHeight");
1046+
messagePageLayoutLog.info(" - Child's self-chosen height is: $bottomSheetHeight");
10711047
messagePageLayoutLog.info(
10721048
" - Clamping child's height within [$_bottomSheetMinimumHeight, $_bottomSheetMaximumHeight]",
10731049
);
@@ -1146,8 +1122,7 @@ class RenderMessagePageScaffold extends RenderBox {
11461122
}
11471123
}
11481124

1149-
bool _isChatScaffoldSlot(Object slot) =>
1150-
slot == _contentSlot || slot == _bottomSheetSlot;
1125+
bool _isChatScaffoldSlot(Object slot) => slot == _contentSlot || slot == _bottomSheetSlot;
11511126

11521127
const _contentSlot = 'content';
11531128
const _bottomSheetSlot = 'bottom_sheet';
@@ -1235,8 +1210,7 @@ class RenderMessageEditorHeight extends RenderBox
12351210
messageEditorHeightLog.info(' - Constraints: $constraints');
12361211

12371212
final ancestorChatScaffold = _findAncestorMessagePageScaffold();
1238-
messageEditorHeightLog
1239-
.info(' - Ancestor chat scaffold: $ancestorChatScaffold');
1213+
messageEditorHeightLog.info(' - Ancestor chat scaffold: $ancestorChatScaffold');
12401214

12411215
final heightMode = ancestorChatScaffold?.bottomSheetMode;
12421216
if (heightMode == null) {
@@ -1253,17 +1227,15 @@ class RenderMessageEditorHeight extends RenderBox
12531227
switch (heightMode) {
12541228
case BottomSheetMode.preview:
12551229
// Preview mode imposes a specific height on the bottom sheet.
1256-
messageEditorHeightLog
1257-
.info(' - Desired bottom sheet preview height: $_previewHeight');
1230+
messageEditorHeightLog.info(' - Desired bottom sheet preview height: $_previewHeight');
12581231

12591232
// We want to be a specific height. Get as close as we can.
12601233
final constrainedHeight = constraints.constrainDimensions(
12611234
double.infinity,
12621235
_previewHeight,
12631236
);
12641237

1265-
messageEditorHeightLog.info(
1266-
' - Constrained bottom sheet preview height: $constrainedHeight');
1238+
messageEditorHeightLog.info(' - Constrained bottom sheet preview height: $constrainedHeight');
12671239
return constrainedHeight;
12681240
case BottomSheetMode.dragging:
12691241
case BottomSheetMode.settling:
@@ -1283,8 +1255,7 @@ class RenderMessageEditorHeight extends RenderBox
12831255
messageEditorHeightLog.info(' - Constraints: $constraints');
12841256

12851257
final ancestorChatScaffold = _findAncestorMessagePageScaffold();
1286-
messageEditorHeightLog
1287-
.info(' - Ancestor chat scaffold: $ancestorChatScaffold');
1258+
messageEditorHeightLog.info(' - Ancestor chat scaffold: $ancestorChatScaffold');
12881259

12891260
final heightMode = ancestorChatScaffold?.bottomSheetMode;
12901261
if (heightMode == null) {
@@ -1303,8 +1274,7 @@ class RenderMessageEditorHeight extends RenderBox
13031274
switch (heightMode) {
13041275
case BottomSheetMode.preview:
13051276
// Preview mode imposes a specific height on the bottom sheet.
1306-
messageEditorHeightLog
1307-
.info(' - Forcing bottom sheet to preview height: $_previewHeight');
1277+
messageEditorHeightLog.info(' - Forcing bottom sheet to preview height: $_previewHeight');
13081278

13091279
// We want to be a specific height. Get as close as we can.
13101280
size = constraints.constrainDimensions(
@@ -1316,7 +1286,8 @@ class RenderMessageEditorHeight extends RenderBox
13161286
);
13171287
child?.layout(
13181288
constraints.copyWith(
1319-
minHeight: size.height - 1,
1289+
minHeight: max(size.height - 1, 0),
1290+
// ^ prevent layout boundary
13201291
maxHeight: size.height,
13211292
),
13221293
parentUsesSize: true,
@@ -1331,11 +1302,9 @@ class RenderMessageEditorHeight extends RenderBox
13311302
case BottomSheetMode.expanded:
13321303
// Whether dragging, animating, or fully expanded, these conditions
13331304
// want to stipulate exactly how tall the bottom sheet should be.
1334-
messageEditorHeightLog
1335-
.info(' - Mode $heightMode - Filling available height');
1305+
messageEditorHeightLog.info(' - Mode $heightMode - Filling available height');
13361306
if (!constraints.hasBoundedHeight) {
1337-
messageEditorHeightLog
1338-
.info(' - No bounded height was provided. Deferring to child');
1307+
messageEditorHeightLog.info(' - No bounded height was provided. Deferring to child');
13391308
size = _doIntrinsicLayout(constraints);
13401309
messageEditorHeightLog.info(' - Our reported size: $size');
13411310
return;
@@ -1348,7 +1317,7 @@ class RenderMessageEditorHeight extends RenderBox
13481317
size = constraints.biggest;
13491318
child?.layout(
13501319
constraints.copyWith(
1351-
minHeight: size.height - 1,
1320+
minHeight: max(size.height - 1, 0),
13521321
// ^ Prevent a layout boundary.
13531322
maxHeight: size.height,
13541323
),
@@ -1369,8 +1338,7 @@ class RenderMessageEditorHeight extends RenderBox
13691338
BoxConstraints constraints, {
13701339
bool doDryLayout = false,
13711340
}) {
1372-
messageEditorHeightLog
1373-
.info(' - Measuring child intrinsic height. Constraints: $constraints');
1341+
messageEditorHeightLog.info(' - Measuring child intrinsic height. Constraints: $constraints');
13741342

13751343
final child = this.child;
13761344
if (child == null) {
@@ -1391,8 +1359,7 @@ class RenderMessageEditorHeight extends RenderBox
13911359
intrinsicSize = child.size;
13921360
}
13931361

1394-
messageEditorHeightLog
1395-
.info(' - Child intrinsic height: ${intrinsicSize.height}');
1362+
messageEditorHeightLog.info(' - Child intrinsic height: ${intrinsicSize.height}');
13961363
return constraints.constrain(intrinsicSize);
13971364
}
13981365

0 commit comments

Comments
 (0)