neoagent 2.3.1-beta.54 → 2.3.1-beta.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,54 +11,216 @@ EdgeInsets _pagePadding(BuildContext context) {
11
11
  return const EdgeInsets.fromLTRB(20, 20, 20, 28);
12
12
  }
13
13
 
14
- class _AmbientBackdrop extends StatelessWidget {
14
+ class _AmbientBackdrop extends StatefulWidget {
15
15
  const _AmbientBackdrop({required this.child});
16
16
 
17
17
  final Widget child;
18
18
 
19
+ @override
20
+ State<_AmbientBackdrop> createState() => _AmbientBackdropState();
21
+ }
22
+
23
+ class _AmbientBackdropState extends State<_AmbientBackdrop>
24
+ with SingleTickerProviderStateMixin {
25
+ late final AnimationController _controller;
26
+
27
+ @override
28
+ void initState() {
29
+ super.initState();
30
+ _controller = AnimationController(
31
+ vsync: this,
32
+ duration: const Duration(seconds: 24),
33
+ )..repeat(reverse: true);
34
+ }
35
+
36
+ @override
37
+ void dispose() {
38
+ _controller.dispose();
39
+ super.dispose();
40
+ }
41
+
19
42
  @override
20
43
  Widget build(BuildContext context) {
21
44
  return DecoratedBox(
22
45
  decoration: BoxDecoration(gradient: _appBackgroundGradient),
23
- child: Stack(
24
- children: <Widget>[
25
- Positioned(
26
- top: -120,
27
- left: -90,
28
- child: _BlurOrb(size: 340, color: _accent.withValues(alpha: 0.9)),
29
- ),
30
- Positioned(
31
- top: 90,
32
- right: -120,
33
- child: _BlurOrb(
34
- size: 280,
35
- color: _accentAlt.withValues(alpha: 0.85),
36
- ),
37
- ),
38
- Positioned(
39
- bottom: -140,
40
- left: 100,
41
- child: _BlurOrb(size: 360, color: _accent.withValues(alpha: 0.45)),
42
- ),
43
- Positioned.fill(
44
- child: IgnorePointer(
46
+ child: AnimatedBuilder(
47
+ animation: _controller,
48
+ builder: (context, _) {
49
+ final t = Curves.easeInOut.transform(_controller.value);
50
+ return Stack(
51
+ children: <Widget>[
52
+ Positioned(
53
+ top: -120 + (t * 22),
54
+ left: -90 + (t * 18),
55
+ child: _BlurOrb(
56
+ size: 340,
57
+ color: _accent.withValues(alpha: 0.9),
58
+ ),
59
+ ),
60
+ Positioned(
61
+ top: 90 - (t * 26),
62
+ right: -120 + (t * 22),
63
+ child: _BlurOrb(
64
+ size: 280,
65
+ color: _accentAlt.withValues(alpha: 0.85),
66
+ ),
67
+ ),
68
+ Positioned(
69
+ bottom: -140 + (t * 16),
70
+ left: 100 - (t * 24),
71
+ child: _BlurOrb(
72
+ size: 360,
73
+ color: _accent.withValues(alpha: 0.45),
74
+ ),
75
+ ),
76
+ Positioned.fill(
77
+ child: IgnorePointer(
78
+ child: DecoratedBox(
79
+ decoration: BoxDecoration(
80
+ gradient: LinearGradient(
81
+ colors: <Color>[
82
+ Colors.white.withValues(alpha: 0.05),
83
+ Colors.transparent,
84
+ Colors.black.withValues(alpha: 0.12),
85
+ ],
86
+ stops: const <double>[0, 0.32, 1],
87
+ begin: Alignment.topCenter,
88
+ end: Alignment.bottomCenter,
89
+ ),
90
+ ),
91
+ ),
92
+ ),
93
+ ),
94
+ Positioned.fill(
95
+ child: IgnorePointer(
96
+ child: DecoratedBox(
97
+ decoration: BoxDecoration(
98
+ gradient: RadialGradient(
99
+ center: Alignment(0.75 - (t * 0.15), -0.9 + (t * 0.1)),
100
+ radius: 0.95,
101
+ colors: <Color>[
102
+ _glassHighlight.withValues(alpha: 0.14),
103
+ Colors.transparent,
104
+ ],
105
+ ),
106
+ ),
107
+ ),
108
+ ),
109
+ ),
110
+ widget.child,
111
+ ],
112
+ );
113
+ },
114
+ ),
115
+ );
116
+ }
117
+ }
118
+
119
+ class _EntranceMotion extends StatefulWidget {
120
+ const _EntranceMotion({required this.child});
121
+
122
+ final Widget child;
123
+
124
+ @override
125
+ State<_EntranceMotion> createState() => _EntranceMotionState();
126
+ }
127
+
128
+ class _EntranceMotionState extends State<_EntranceMotion> {
129
+ bool _visible = false;
130
+
131
+ @override
132
+ void initState() {
133
+ super.initState();
134
+ WidgetsBinding.instance.addPostFrameCallback((_) {
135
+ if (mounted) {
136
+ setState(() {
137
+ _visible = true;
138
+ });
139
+ }
140
+ });
141
+ }
142
+
143
+ @override
144
+ Widget build(BuildContext context) {
145
+ return AnimatedSlide(
146
+ duration: const Duration(milliseconds: 700),
147
+ curve: Curves.easeOutCubic,
148
+ offset: _visible ? Offset.zero : const Offset(0, 0.035),
149
+ child: AnimatedOpacity(
150
+ duration: const Duration(milliseconds: 700),
151
+ curve: Curves.easeOutCubic,
152
+ opacity: _visible ? 1 : 0,
153
+ child: widget.child,
154
+ ),
155
+ );
156
+ }
157
+ }
158
+
159
+ class _GlassSurface extends StatelessWidget {
160
+ const _GlassSurface({
161
+ required this.child,
162
+ this.width,
163
+ this.padding,
164
+ this.borderRadius = const BorderRadius.all(Radius.circular(24)),
165
+ this.blurSigma = 22,
166
+ this.fillColor,
167
+ this.borderColor,
168
+ this.overlayGradient,
169
+ this.boxShadow,
170
+ });
171
+
172
+ final Widget child;
173
+ final double? width;
174
+ final EdgeInsetsGeometry? padding;
175
+ final BorderRadius borderRadius;
176
+ final double blurSigma;
177
+ final Color? fillColor;
178
+ final Color? borderColor;
179
+ final Gradient? overlayGradient;
180
+ final List<BoxShadow>? boxShadow;
181
+
182
+ @override
183
+ Widget build(BuildContext context) {
184
+ return SizedBox(
185
+ width: width,
186
+ child: DecoratedBox(
187
+ decoration: BoxDecoration(
188
+ borderRadius: borderRadius,
189
+ boxShadow: boxShadow,
190
+ ),
191
+ child: ClipRRect(
192
+ borderRadius: borderRadius,
193
+ child: BackdropFilter(
194
+ filter: ImageFilter.blur(sigmaX: blurSigma, sigmaY: blurSigma),
195
+ child: DecoratedBox(
196
+ decoration: BoxDecoration(
197
+ color: fillColor ?? _glassFill,
198
+ gradient: overlayGradient ?? _liquidMetalGradient,
199
+ borderRadius: borderRadius,
200
+ border: Border.all(color: borderColor ?? _glassBorder),
201
+ ),
45
202
  child: DecoratedBox(
46
203
  decoration: BoxDecoration(
204
+ borderRadius: borderRadius,
47
205
  gradient: LinearGradient(
48
206
  colors: <Color>[
49
- Colors.white.withValues(alpha: 0.02),
207
+ _glassHighlight.withValues(alpha: 0.2),
50
208
  Colors.transparent,
51
- Colors.black.withValues(alpha: 0.08),
209
+ Colors.black.withValues(alpha: 0.06),
52
210
  ],
53
- begin: Alignment.topCenter,
54
- end: Alignment.bottomCenter,
211
+ stops: const <double>[0, 0.22, 1],
212
+ begin: Alignment.topLeft,
213
+ end: Alignment.bottomRight,
55
214
  ),
56
215
  ),
216
+ child: Padding(
217
+ padding: padding ?? EdgeInsets.zero,
218
+ child: child,
219
+ ),
57
220
  ),
58
221
  ),
59
222
  ),
60
- child,
61
- ],
223
+ ),
62
224
  ),
63
225
  );
64
226
  }
@@ -223,53 +385,58 @@ class _PageTitle extends StatelessWidget {
223
385
  @override
224
386
  Widget build(BuildContext context) {
225
387
  final compact = MediaQuery.sizeOf(context).width < 760;
226
- return Padding(
227
- padding: const EdgeInsets.only(bottom: 24),
228
- child: compact
229
- ? Column(
230
- crossAxisAlignment: CrossAxisAlignment.start,
231
- children: <Widget>[
232
- Text('CONTROL SURFACE', style: _sectionEyebrowStyle()),
233
- const SizedBox(height: 8),
234
- Text(title, style: _displayTitleStyle(30)),
235
- const SizedBox(height: 10),
236
- ConstrainedBox(
237
- constraints: const BoxConstraints(maxWidth: 720),
238
- child: Text(
239
- subtitle,
240
- style: TextStyle(color: _textSecondary, height: 1.5),
388
+ return _EntranceMotion(
389
+ child: Padding(
390
+ padding: const EdgeInsets.only(bottom: 24),
391
+ child: compact
392
+ ? Column(
393
+ crossAxisAlignment: CrossAxisAlignment.start,
394
+ children: <Widget>[
395
+ Text('CONTROL SURFACE', style: _sectionEyebrowStyle()),
396
+ const SizedBox(height: 8),
397
+ Text(title, style: _displayTitleStyle(30)),
398
+ const SizedBox(height: 10),
399
+ ConstrainedBox(
400
+ constraints: const BoxConstraints(maxWidth: 720),
401
+ child: Text(
402
+ subtitle,
403
+ style: TextStyle(color: _textSecondary, height: 1.5),
404
+ ),
241
405
  ),
242
- ),
243
- if (trailing != null) ...<Widget>[
244
- const SizedBox(height: 18),
245
- trailing!,
406
+ if (trailing != null) ...<Widget>[
407
+ const SizedBox(height: 18),
408
+ trailing!,
409
+ ],
246
410
  ],
247
- ],
248
- )
249
- : Row(
250
- crossAxisAlignment: CrossAxisAlignment.start,
251
- children: <Widget>[
252
- Expanded(
253
- child: Column(
254
- crossAxisAlignment: CrossAxisAlignment.start,
255
- children: <Widget>[
256
- Text('CONTROL SURFACE', style: _sectionEyebrowStyle()),
257
- const SizedBox(height: 8),
258
- Text(title, style: _displayTitleStyle(32)),
259
- const SizedBox(height: 10),
260
- ConstrainedBox(
261
- constraints: const BoxConstraints(maxWidth: 760),
262
- child: Text(
263
- subtitle,
264
- style: TextStyle(color: _textSecondary, height: 1.5),
411
+ )
412
+ : Row(
413
+ crossAxisAlignment: CrossAxisAlignment.start,
414
+ children: <Widget>[
415
+ Expanded(
416
+ child: Column(
417
+ crossAxisAlignment: CrossAxisAlignment.start,
418
+ children: <Widget>[
419
+ Text('CONTROL SURFACE', style: _sectionEyebrowStyle()),
420
+ const SizedBox(height: 8),
421
+ Text(title, style: _displayTitleStyle(32)),
422
+ const SizedBox(height: 10),
423
+ ConstrainedBox(
424
+ constraints: const BoxConstraints(maxWidth: 760),
425
+ child: Text(
426
+ subtitle,
427
+ style: TextStyle(
428
+ color: _textSecondary,
429
+ height: 1.5,
430
+ ),
431
+ ),
265
432
  ),
266
- ),
267
- ],
433
+ ],
434
+ ),
268
435
  ),
269
- ),
270
- if (trailing != null) trailing!,
271
- ],
272
- ),
436
+ if (trailing != null) trailing!,
437
+ ],
438
+ ),
439
+ ),
273
440
  );
274
441
  }
275
442
  }
@@ -515,35 +682,45 @@ class _OverviewCard extends StatelessWidget {
515
682
 
516
683
  @override
517
684
  Widget build(BuildContext context) {
518
- return Card(
519
- child: Padding(
520
- padding: const EdgeInsets.all(22),
521
- child: Column(
522
- crossAxisAlignment: CrossAxisAlignment.start,
523
- children: <Widget>[
524
- Container(
525
- width: 34,
526
- height: 4,
527
- decoration: BoxDecoration(
528
- color: _accent,
529
- borderRadius: BorderRadius.circular(999),
685
+ return _EntranceMotion(
686
+ child: Card(
687
+ child: Padding(
688
+ padding: const EdgeInsets.all(22),
689
+ child: Column(
690
+ crossAxisAlignment: CrossAxisAlignment.start,
691
+ children: <Widget>[
692
+ Container(
693
+ width: 34,
694
+ height: 4,
695
+ decoration: BoxDecoration(
696
+ gradient: LinearGradient(
697
+ colors: <Color>[
698
+ _accentHover,
699
+ _accentAlt.withValues(alpha: 0.9),
700
+ ],
701
+ ),
702
+ borderRadius: BorderRadius.circular(999),
703
+ ),
530
704
  ),
531
- ),
532
- const SizedBox(height: 16),
533
- Text(
534
- title.toUpperCase(),
535
- style: TextStyle(
536
- color: _textSecondary,
537
- fontSize: 11,
538
- fontWeight: FontWeight.w700,
539
- letterSpacing: 1.2,
705
+ const SizedBox(height: 16),
706
+ Text(
707
+ title.toUpperCase(),
708
+ style: TextStyle(
709
+ color: _textSecondary,
710
+ fontSize: 11,
711
+ fontWeight: FontWeight.w700,
712
+ letterSpacing: 1.2,
713
+ ),
540
714
  ),
541
- ),
542
- const SizedBox(height: 10),
543
- Text(value, style: _displayTitleStyle(28)),
544
- const SizedBox(height: 12),
545
- Text(helper, style: TextStyle(color: _textSecondary, height: 1.45)),
546
- ],
715
+ const SizedBox(height: 10),
716
+ Text(value, style: _displayTitleStyle(28)),
717
+ const SizedBox(height: 12),
718
+ Text(
719
+ helper,
720
+ style: TextStyle(color: _textSecondary, height: 1.45),
721
+ ),
722
+ ],
723
+ ),
547
724
  ),
548
725
  ),
549
726
  );
@@ -558,10 +735,12 @@ class _EmptyCard extends StatelessWidget {
558
735
 
559
736
  @override
560
737
  Widget build(BuildContext context) {
561
- return Card(
562
- child: Padding(
563
- padding: const EdgeInsets.all(34),
564
- child: _EmptyState(title: title, subtitle: subtitle),
738
+ return _EntranceMotion(
739
+ child: Card(
740
+ child: Padding(
741
+ padding: const EdgeInsets.all(34),
742
+ child: _EmptyState(title: title, subtitle: subtitle),
743
+ ),
565
744
  ),
566
745
  );
567
746
  }
@@ -594,13 +773,12 @@ class _DotStatus extends StatelessWidget {
594
773
 
595
774
  @override
596
775
  Widget build(BuildContext context) {
597
- return Container(
776
+ return _GlassSurface(
598
777
  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
599
- decoration: BoxDecoration(
600
- color: _bgSecondary,
601
- borderRadius: BorderRadius.circular(999),
602
- border: Border.all(color: _border),
603
- ),
778
+ borderRadius: BorderRadius.circular(999),
779
+ blurSigma: 16,
780
+ fillColor: _bgSecondary.withValues(alpha: 0.28),
781
+ borderColor: _glassBorder.withValues(alpha: 0.8),
604
782
  child: Row(
605
783
  mainAxisSize: MainAxisSize.min,
606
784
  children: <Widget>[
@@ -642,66 +820,79 @@ class _SidebarButton extends StatelessWidget {
642
820
  Widget build(BuildContext context) {
643
821
  return Padding(
644
822
  padding: const EdgeInsets.only(bottom: 6),
645
- child: AnimatedContainer(
646
- duration: const Duration(milliseconds: 180),
823
+ child: AnimatedScale(
824
+ duration: const Duration(milliseconds: 220),
647
825
  curve: Curves.easeOutCubic,
648
- decoration: BoxDecoration(
649
- gradient: active
650
- ? LinearGradient(
651
- colors: <Color>[
652
- _accentMuted,
653
- _accentMuted.withValues(alpha: 0.06),
654
- ],
655
- )
656
- : null,
826
+ scale: active ? 1.01 : 1,
827
+ child: _GlassSurface(
657
828
  borderRadius: BorderRadius.circular(18),
658
- border: Border.all(
659
- color: active
660
- ? _accent.withValues(alpha: 0.35)
661
- : Colors.transparent,
662
- ),
663
- ),
664
- child: Material(
665
- color: Colors.transparent,
666
- child: InkWell(
667
- borderRadius: BorderRadius.circular(18),
668
- onTap: onTap,
669
- child: Container(
670
- width: double.infinity,
671
- padding: EdgeInsets.fromLTRB(12 + indent, 12, 12, 12),
672
- child: Row(
673
- children: <Widget>[
674
- if (active)
675
- Container(
676
- width: 6,
677
- height: 26,
678
- margin: const EdgeInsets.only(right: 10),
679
- decoration: BoxDecoration(
680
- color: _accent,
681
- borderRadius: BorderRadius.circular(999),
829
+ blurSigma: 18,
830
+ fillColor: active
831
+ ? _accentMuted.withValues(alpha: 0.32)
832
+ : _bgCard.withValues(alpha: 0.2),
833
+ borderColor: active
834
+ ? _accent.withValues(alpha: 0.32)
835
+ : Colors.white.withValues(alpha: 0.03),
836
+ boxShadow: active
837
+ ? <BoxShadow>[
838
+ BoxShadow(
839
+ color: _accent.withValues(alpha: 0.12),
840
+ blurRadius: 22,
841
+ offset: const Offset(0, 8),
842
+ ),
843
+ ]
844
+ : null,
845
+ child: Material(
846
+ color: Colors.transparent,
847
+ child: InkWell(
848
+ borderRadius: BorderRadius.circular(18),
849
+ onTap: onTap,
850
+ child: Container(
851
+ width: double.infinity,
852
+ padding: EdgeInsets.fromLTRB(12 + indent, 12, 12, 12),
853
+ child: Row(
854
+ children: <Widget>[
855
+ if (active)
856
+ Container(
857
+ width: 6,
858
+ height: 26,
859
+ margin: const EdgeInsets.only(right: 10),
860
+ decoration: BoxDecoration(
861
+ gradient: LinearGradient(
862
+ colors: <Color>[
863
+ _accentHover,
864
+ _accentAlt.withValues(alpha: 0.9),
865
+ ],
866
+ begin: Alignment.topCenter,
867
+ end: Alignment.bottomCenter,
868
+ ),
869
+ borderRadius: BorderRadius.circular(999),
870
+ ),
682
871
  ),
872
+ Icon(
873
+ icon,
874
+ size: iconSize,
875
+ color: active ? _accentHover : _textSecondary,
683
876
  ),
684
- Icon(
685
- icon,
686
- size: iconSize,
687
- color: active ? _accentHover : _textSecondary,
688
- ),
689
- const SizedBox(width: 10),
690
- Expanded(
691
- child: Text(
692
- label,
693
- style: TextStyle(
694
- fontSize: fontSize,
695
- fontWeight: active ? FontWeight.w700 : FontWeight.w600,
696
- color: active ? _textPrimary : _textSecondary,
877
+ const SizedBox(width: 10),
878
+ Expanded(
879
+ child: Text(
880
+ label,
881
+ style: TextStyle(
882
+ fontSize: fontSize,
883
+ fontWeight: active
884
+ ? FontWeight.w700
885
+ : FontWeight.w600,
886
+ color: active ? _textPrimary : _textSecondary,
887
+ ),
697
888
  ),
698
889
  ),
699
- ),
700
- if (trailing != null) ...<Widget>[
701
- const SizedBox(width: 8),
702
- trailing!,
890
+ if (trailing != null) ...<Widget>[
891
+ const SizedBox(width: 8),
892
+ trailing!,
893
+ ],
703
894
  ],
704
- ],
895
+ ),
705
896
  ),
706
897
  ),
707
898
  ),
@@ -726,16 +917,21 @@ class _SidebarIconButton extends StatelessWidget {
726
917
  Widget build(BuildContext context) {
727
918
  return Tooltip(
728
919
  message: tooltip,
729
- child: Material(
730
- color: _bgCard.withValues(alpha: 0.8),
731
- shape: CircleBorder(side: BorderSide(color: _borderLight)),
732
- child: InkWell(
733
- customBorder: CircleBorder(),
734
- onTap: onTap,
735
- child: SizedBox(
736
- width: 38,
737
- height: 38,
738
- child: Icon(icon, size: 17, color: _textSecondary),
920
+ child: _GlassSurface(
921
+ borderRadius: BorderRadius.circular(999),
922
+ blurSigma: 18,
923
+ fillColor: _bgCard.withValues(alpha: 0.3),
924
+ child: Material(
925
+ color: Colors.transparent,
926
+ shape: const CircleBorder(),
927
+ child: InkWell(
928
+ customBorder: const CircleBorder(),
929
+ onTap: onTap,
930
+ child: SizedBox(
931
+ width: 38,
932
+ height: 38,
933
+ child: Icon(icon, size: 17, color: _textSecondary),
934
+ ),
739
935
  ),
740
936
  ),
741
937
  ),
@@ -1184,14 +1380,11 @@ class _MessageRunCardShell extends StatelessWidget {
1184
1380
 
1185
1381
  @override
1186
1382
  Widget build(BuildContext context) {
1187
- return Container(
1188
- width: double.infinity,
1383
+ return _GlassSurface(
1189
1384
  padding: const EdgeInsets.all(12),
1190
- decoration: BoxDecoration(
1191
- color: _bgPrimary,
1192
- borderRadius: BorderRadius.circular(14),
1193
- border: Border.all(color: _border),
1194
- ),
1385
+ borderRadius: BorderRadius.circular(14),
1386
+ blurSigma: 18,
1387
+ fillColor: _bgPrimary.withValues(alpha: 0.34),
1195
1388
  child: child,
1196
1389
  );
1197
1390
  }
@@ -1551,6 +1744,87 @@ class _GlobalNetworkBanner extends StatelessWidget {
1551
1744
  }
1552
1745
  }
1553
1746
 
1747
+ class _GlobalWebUpdateBanner extends StatelessWidget {
1748
+ const _GlobalWebUpdateBanner({required this.monitor});
1749
+
1750
+ final WebAppUpdateMonitor monitor;
1751
+
1752
+ @override
1753
+ Widget build(BuildContext context) {
1754
+ return LayoutBuilder(
1755
+ builder: (context, constraints) {
1756
+ final compact = constraints.maxWidth < 560;
1757
+ final content = Text(
1758
+ 'A newer web build is available on the server. Reload to fetch the latest bundle.',
1759
+ style: TextStyle(color: _textPrimary, height: 1.35),
1760
+ );
1761
+ return Material(
1762
+ color: Colors.transparent,
1763
+ child: Container(
1764
+ width: double.infinity,
1765
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
1766
+ decoration: BoxDecoration(
1767
+ color: _accent.withValues(alpha: 0.12),
1768
+ borderRadius: BorderRadius.circular(18),
1769
+ border: Border.all(color: _accent.withValues(alpha: 0.3)),
1770
+ boxShadow: <BoxShadow>[
1771
+ BoxShadow(
1772
+ color: Colors.black.withValues(alpha: 0.12),
1773
+ blurRadius: 18,
1774
+ offset: const Offset(0, 10),
1775
+ ),
1776
+ ],
1777
+ ),
1778
+ child: compact
1779
+ ? Column(
1780
+ crossAxisAlignment: CrossAxisAlignment.start,
1781
+ children: <Widget>[
1782
+ Row(
1783
+ crossAxisAlignment: CrossAxisAlignment.start,
1784
+ children: <Widget>[
1785
+ Icon(
1786
+ Icons.system_update_alt,
1787
+ color: _accent,
1788
+ size: 18,
1789
+ ),
1790
+ const SizedBox(width: 10),
1791
+ Expanded(child: content),
1792
+ ],
1793
+ ),
1794
+ const SizedBox(height: 10),
1795
+ FilledButton(
1796
+ onPressed: monitor.isReloading
1797
+ ? null
1798
+ : monitor.reloadToLatest,
1799
+ child: Text(
1800
+ monitor.isReloading ? 'Reloading...' : 'Reload now',
1801
+ ),
1802
+ ),
1803
+ ],
1804
+ )
1805
+ : Row(
1806
+ children: <Widget>[
1807
+ Icon(Icons.system_update_alt, color: _accent, size: 18),
1808
+ const SizedBox(width: 10),
1809
+ Expanded(child: content),
1810
+ const SizedBox(width: 12),
1811
+ FilledButton(
1812
+ onPressed: monitor.isReloading
1813
+ ? null
1814
+ : monitor.reloadToLatest,
1815
+ child: Text(
1816
+ monitor.isReloading ? 'Reloading...' : 'Reload now',
1817
+ ),
1818
+ ),
1819
+ ],
1820
+ ),
1821
+ ),
1822
+ );
1823
+ },
1824
+ );
1825
+ }
1826
+ }
1827
+
1554
1828
  class _DesktopCloseDecision {
1555
1829
  const _DesktopCloseDecision({
1556
1830
  required this.keepRunning,