@@ -9,7 +9,7 @@ import 'icons.dart';
9
9
import 'text.dart' ;
10
10
import 'theme.dart' ;
11
11
12
- class SwipableMessageRow extends StatefulWidget {
12
+ class SwipableMessageRow extends StatelessWidget {
13
13
const SwipableMessageRow ({
14
14
super .key,
15
15
required this .children,
@@ -20,19 +20,69 @@ class SwipableMessageRow extends StatefulWidget {
20
20
final Message message;
21
21
22
22
@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
+ }
24
46
}
25
47
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
+
27
77
@override
28
78
void initState () {
29
79
super .initState ();
30
80
_controller = AnimationController (
31
81
// The duration is only used when `_controller.reverse()` is called,
32
82
// i.e.: when the drag is released and the marker gets collapsed.
33
83
duration: const Duration (milliseconds: 200 ),
34
- lowerBound: _EditStateMarker .widthCollapsed,
35
- upperBound: _EditStateMarker .widthExpanded,
84
+ lowerBound: _RowWithEditStateMarker .widthCollapsed,
85
+ upperBound: _RowWithEditStateMarker .widthExpanded,
36
86
vsync: this )
37
87
..addListener (() => setState ((){}));
38
88
}
@@ -53,68 +103,6 @@ class _SwipableMessageRowState extends State<SwipableMessageRow> with TickerProv
53
103
_controller.reverse ();
54
104
}
55
105
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
-
118
106
@override
119
107
Widget build (BuildContext context) {
120
108
final designVariables = DesignVariables .of (context);
@@ -124,9 +112,9 @@ class _EditStateMarker extends StatelessWidget {
124
112
final double iconSize;
125
113
final String markerText;
126
114
127
- switch (_editState) {
115
+ switch (widget. _editState) {
128
116
case MessageEditState .none:
129
- return const SizedBox (width: widthCollapsed);
117
+ return const SizedBox (width: _RowWithEditStateMarker . widthCollapsed);
130
118
case MessageEditState .edited:
131
119
icon = ZulipIcons .edited;
132
120
iconSize = 14 ;
@@ -139,7 +127,7 @@ class _EditStateMarker extends StatelessWidget {
139
127
break ;
140
128
}
141
129
142
- var marker = Row (
130
+ final markerContent = Row (
143
131
mainAxisAlignment: MainAxisAlignment .end,
144
132
mainAxisSize: MainAxisSize .min,
145
133
children: [
@@ -167,8 +155,9 @@ class _EditStateMarker extends StatelessWidget {
167
155
],
168
156
);
169
157
170
- return ConstrainedBox (
171
- constraints: BoxConstraints (maxWidth: _animation.value),
158
+
159
+ final markerBox = ConstrainedBox (
160
+ constraints: BoxConstraints (maxWidth: _controller.value),
172
161
child: Container (
173
162
margin: EdgeInsetsDirectional .only (
174
163
start: lerpDouble (5 , 13 , _animationProgress)! , end: 3 ),
@@ -182,8 +171,20 @@ class _EditStateMarker extends StatelessWidget {
182
171
child: Padding (
183
172
padding: EdgeInsetsDirectional .symmetric (
184
173
horizontal: lerpDouble (0 , 3 , _animationProgress)! ),
185
- child: marker ),
174
+ child: markerContent ),
186
175
),
187
176
);
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
+ );
188
189
}
189
190
}
0 commit comments