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.
- package/flutter_app/lib/main.dart +2 -0
- package/flutter_app/lib/main_app_shell.dart +210 -180
- package/flutter_app/lib/main_runtime.dart +30 -1
- package/flutter_app/lib/main_shared.dart +453 -179
- package/flutter_app/lib/main_theme.dart +79 -24
- package/flutter_app/lib/src/web_app_update_monitor.dart +17 -0
- package/flutter_app/lib/src/web_app_update_monitor_stub.dart +24 -0
- package/flutter_app/lib/src/web_app_update_monitor_web.dart +123 -0
- package/package.json +3 -3
- package/server/http/static.js +41 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +62678 -62325
|
@@ -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
|
|
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:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
207
|
+
_glassHighlight.withValues(alpha: 0.2),
|
|
50
208
|
Colors.transparent,
|
|
51
|
-
Colors.black.withValues(alpha: 0.
|
|
209
|
+
Colors.black.withValues(alpha: 0.06),
|
|
52
210
|
],
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
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
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
406
|
+
if (trailing != null) ...<Widget>[
|
|
407
|
+
const SizedBox(height: 18),
|
|
408
|
+
trailing!,
|
|
409
|
+
],
|
|
246
410
|
],
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
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
|
|
519
|
-
child:
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
|
562
|
-
child:
|
|
563
|
-
|
|
564
|
-
|
|
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
|
|
776
|
+
return _GlassSurface(
|
|
598
777
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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:
|
|
646
|
-
duration: const Duration(milliseconds:
|
|
823
|
+
child: AnimatedScale(
|
|
824
|
+
duration: const Duration(milliseconds: 220),
|
|
647
825
|
curve: Curves.easeOutCubic,
|
|
648
|
-
|
|
649
|
-
|
|
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
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
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
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
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
|
-
|
|
701
|
-
|
|
702
|
-
|
|
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:
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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
|
|
1188
|
-
width: double.infinity,
|
|
1383
|
+
return _GlassSurface(
|
|
1189
1384
|
padding: const EdgeInsets.all(12),
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
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,
|