Skip to content

Commit 5c32798

Browse files
committed
Layout fix wip
Signed-off-by: Zixuan James Li <[email protected]>
1 parent 002f9d7 commit 5c32798

File tree

1 file changed

+74
-73
lines changed

1 file changed

+74
-73
lines changed

lib/widgets/swipable_message_row.dart

+74-73
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'icons.dart';
99
import 'text.dart';
1010
import 'theme.dart';
1111

12-
class SwipableMessageRow extends StatefulWidget {
12+
class SwipableMessageRow extends StatelessWidget {
1313
const SwipableMessageRow({
1414
super.key,
1515
required this.children,
@@ -20,19 +20,69 @@ class SwipableMessageRow extends StatefulWidget {
2020
final Message message;
2121

2222
@override
23-
State<StatefulWidget> createState() => _SwipableMessageRowState();
23+
Widget build(BuildContext context) {
24+
// print('regular build');
25+
return LayoutBuilder(
26+
builder: (context, constraints) {
27+
print('layout rebuild');
28+
return OverflowBox(
29+
fit: OverflowBoxFit.deferToChild,
30+
alignment: Alignment.topLeft,
31+
maxWidth: double.infinity,
32+
child: _RowWithEditStateMarker(
33+
editState: message.editState,
34+
child: Builder(builder: (context) {
35+
return SizedBox(
36+
width: constraints.maxWidth - 16,
37+
child: Row(
38+
crossAxisAlignment: CrossAxisAlignment.baseline,
39+
textBaseline: localizedTextBaseline(context),
40+
children: children));
41+
}))
42+
);
43+
}
44+
);
45+
}
2446
}
2547

26-
class _SwipableMessageRowState extends State<SwipableMessageRow> with TickerProviderStateMixin {
48+
class _RowWithEditStateMarker extends StatefulWidget {
49+
/// The minimum width of the marker.
50+
///
51+
/// This is when no drag has been performed on the message row
52+
/// where only the moved/edited icon, not the text, is visible.
53+
static const double widthCollapsed = 16;
54+
55+
/// The maximum width of the marker.
56+
///
57+
/// This is typically wider than the colored pill when the marker is fully
58+
/// expanded. At that point only the blank space to the right of the colored
59+
/// block will grow until the marker reaches this width.
60+
static const double widthExpanded = 100;
61+
62+
const _RowWithEditStateMarker({
63+
required MessageEditState editState,
64+
required this.child,
65+
}) : _editState = editState;
66+
67+
final MessageEditState _editState;
68+
final Widget child;
69+
70+
@override
71+
State<_RowWithEditStateMarker> createState() => _RowWithEditStateMarkerState();
72+
}
73+
74+
class _RowWithEditStateMarkerState extends State<_RowWithEditStateMarker> with TickerProviderStateMixin {
75+
double get _animationProgress => (_controller.value - _RowWithEditStateMarker.widthCollapsed) / _RowWithEditStateMarker.widthExpanded;
76+
2777
@override
2878
void initState() {
2979
super.initState();
3080
_controller = AnimationController(
3181
// The duration is only used when `_controller.reverse()` is called,
3282
// i.e.: when the drag is released and the marker gets collapsed.
3383
duration: const Duration(milliseconds: 200),
34-
lowerBound: _EditStateMarker.widthCollapsed,
35-
upperBound: _EditStateMarker.widthExpanded,
84+
lowerBound: _RowWithEditStateMarker.widthCollapsed,
85+
upperBound: _RowWithEditStateMarker.widthExpanded,
3686
vsync: this)
3787
..addListener(() => setState((){}));
3888
}
@@ -53,68 +103,6 @@ class _SwipableMessageRowState extends State<SwipableMessageRow> with TickerProv
53103
_controller.reverse();
54104
}
55105

56-
@override
57-
Widget build(BuildContext context) {
58-
final hasMarker = widget.message.editState != MessageEditState.none;
59-
60-
final content = LayoutBuilder(
61-
builder: (context, constraints) => OverflowBox(
62-
fit: OverflowBoxFit.deferToChild,
63-
alignment: Alignment.topLeft,
64-
maxWidth: double.infinity,
65-
child: Row(
66-
crossAxisAlignment: CrossAxisAlignment.baseline,
67-
textBaseline: localizedTextBaseline(context),
68-
children: [
69-
hasMarker
70-
? _EditStateMarker(
71-
editState: widget.message.editState,
72-
animation: _controller)
73-
: const SizedBox(width: 16),
74-
SizedBox(
75-
width: constraints.maxWidth - 16,
76-
child: Row(
77-
crossAxisAlignment: CrossAxisAlignment.baseline,
78-
textBaseline: localizedTextBaseline(context),
79-
children: widget.children),
80-
),
81-
])),
82-
);
83-
84-
if (!hasMarker) return content;
85-
86-
return GestureDetector(
87-
onHorizontalDragEnd: _handleDragEnd,
88-
onHorizontalDragUpdate: _handleDragUpdate,
89-
child: content,
90-
);
91-
}
92-
}
93-
94-
class _EditStateMarker extends StatelessWidget {
95-
/// The minimum width of the marker.
96-
///
97-
/// This is when no drag has been performed on the message row
98-
/// where only the moved/edited icon, not the text, is visible.
99-
static const double widthCollapsed = 16;
100-
101-
/// The maximum width of the marker.
102-
///
103-
/// This is typically wider than the colored pill when the marker is fully
104-
/// expanded. At that point only the blank space to the right of the colored
105-
/// block will grow until the marker reaches this width.
106-
static const double widthExpanded = 100;
107-
108-
const _EditStateMarker({
109-
required MessageEditState editState,
110-
required Animation<double> animation,
111-
}) : _editState = editState, _animation = animation;
112-
113-
final MessageEditState _editState;
114-
final Animation<double> _animation;
115-
116-
double get _animationProgress => (_animation.value - widthCollapsed) / widthExpanded;
117-
118106
@override
119107
Widget build(BuildContext context) {
120108
final designVariables = DesignVariables.of(context);
@@ -124,9 +112,9 @@ class _EditStateMarker extends StatelessWidget {
124112
final double iconSize;
125113
final String markerText;
126114

127-
switch (_editState) {
115+
switch (widget._editState) {
128116
case MessageEditState.none:
129-
return const SizedBox(width: widthCollapsed);
117+
return const SizedBox(width: _RowWithEditStateMarker.widthCollapsed);
130118
case MessageEditState.edited:
131119
icon = ZulipIcons.edited;
132120
iconSize = 14;
@@ -139,7 +127,7 @@ class _EditStateMarker extends StatelessWidget {
139127
break;
140128
}
141129

142-
var marker = Row(
130+
final markerContent = Row(
143131
mainAxisAlignment: MainAxisAlignment.end,
144132
mainAxisSize: MainAxisSize.min,
145133
children: [
@@ -167,8 +155,9 @@ class _EditStateMarker extends StatelessWidget {
167155
],
168156
);
169157

170-
return ConstrainedBox(
171-
constraints: BoxConstraints(maxWidth: _animation.value),
158+
159+
final markerBox = ConstrainedBox(
160+
constraints: BoxConstraints(maxWidth: _controller.value),
172161
child: Container(
173162
margin: EdgeInsetsDirectional.only(
174163
start: lerpDouble(5, 13, _animationProgress)!, end: 3),
@@ -182,8 +171,20 @@ class _EditStateMarker extends StatelessWidget {
182171
child: Padding(
183172
padding: EdgeInsetsDirectional.symmetric(
184173
horizontal: lerpDouble(0, 3, _animationProgress)!),
185-
child: marker),
174+
child: markerContent),
186175
),
187176
);
177+
178+
return GestureDetector(
179+
onHorizontalDragEnd: _handleDragEnd,
180+
onHorizontalDragUpdate: _handleDragUpdate,
181+
child: Row(
182+
crossAxisAlignment: CrossAxisAlignment.baseline,
183+
textBaseline: localizedTextBaseline(context),
184+
children: [
185+
widget._editState != MessageEditState.none ? markerBox : const SizedBox(width: 16),
186+
widget.child,
187+
]),
188+
);
188189
}
189190
}

0 commit comments

Comments
 (0)