@@ -4,8 +4,10 @@ import '../models/terminal/models.dart';
4
4
import 'expandable_section.dart' ;
5
5
6
6
class SystemLogTile extends StatelessWidget {
7
- const SystemLogTile ({super .key, required this .entry});
7
+ const SystemLogTile (
8
+ {super .key, required this .entry, this .showTimestamp = false });
8
9
final TerminalEntry entry;
10
+ final bool showTimestamp;
9
11
@override
10
12
Widget build (BuildContext context) {
11
13
assert (entry.system != null , 'System tile requires SystemLogData' );
@@ -35,10 +37,17 @@ class SystemLogTile extends StatelessWidget {
35
37
child: Row (
36
38
crossAxisAlignment: CrossAxisAlignment .start,
37
39
children: [
38
- Padding (
39
- padding: const EdgeInsets .only (top: 2 , right: 8 ),
40
- child: Icon (icon, size: 18 , color: iconColor),
41
- ),
40
+ if (showTimestamp) ...[
41
+ Padding (
42
+ padding: const EdgeInsets .only (top: 2 , right: 8 ),
43
+ child: Text (_formatTs (entry.ts), style: subStyle),
44
+ ),
45
+ ] else ...[
46
+ Padding (
47
+ padding: const EdgeInsets .only (top: 2 , right: 8 ),
48
+ child: Icon (icon, size: 18 , color: iconColor),
49
+ ),
50
+ ],
42
51
Expanded (
43
52
child: Column (
44
53
crossAxisAlignment: CrossAxisAlignment .start,
@@ -58,8 +67,14 @@ class SystemLogTile extends StatelessWidget {
58
67
}
59
68
60
69
class JsLogTile extends StatelessWidget {
61
- const JsLogTile ({super .key, required this .entry});
70
+ const JsLogTile (
71
+ {super .key,
72
+ required this .entry,
73
+ this .showTimestamp = false ,
74
+ this .requestName});
62
75
final TerminalEntry entry;
76
+ final bool showTimestamp;
77
+ final String ? requestName;
63
78
@override
64
79
Widget build (BuildContext context) {
65
80
assert (entry.js != null , 'JS tile requires JsLogData' );
@@ -83,21 +98,37 @@ class JsLogTile extends StatelessWidget {
83
98
case TerminalLevel .debug:
84
99
break ;
85
100
}
101
+ final bodyParts = < String > [];
102
+ if (requestName != null && requestName! .isNotEmpty) {
103
+ bodyParts.add ('[$requestName ]' );
104
+ }
105
+ // Add JS level/context prefix to disambiguate
106
+ if (j.context != null && j.context! .isNotEmpty) {
107
+ bodyParts.add ('(${j .context })' );
108
+ }
109
+ bodyParts.addAll (j.args);
110
+ final bodyText = bodyParts.join (' ' );
86
111
return Container (
87
112
color: bg,
88
113
padding: const EdgeInsets .symmetric (horizontal: 12 , vertical: 10 ),
89
114
child: Row (
90
115
crossAxisAlignment: CrossAxisAlignment .start,
91
116
children: [
92
- if (icon != null ) ...[
117
+ if (showTimestamp) ...[
118
+ Padding (
119
+ padding: const EdgeInsets .only (top: 2 , right: 8 ),
120
+ child: Text (_formatTs (entry.ts),
121
+ style: Theme .of (context).textTheme.bodySmall),
122
+ ),
123
+ ] else if (icon != null ) ...[
93
124
Padding (
94
125
padding: const EdgeInsets .only (top: 2 , right: 8 ),
95
126
child: Icon (icon, size: 18 , color: iconColor),
96
127
),
97
128
],
98
129
Expanded (
99
130
child: SelectableText (
100
- j.args. join ( ' ' ) ,
131
+ bodyText ,
101
132
style: Theme .of (context).textTheme.bodyMedium,
102
133
),
103
134
),
@@ -108,8 +139,14 @@ class JsLogTile extends StatelessWidget {
108
139
}
109
140
110
141
class NetworkLogTile extends StatefulWidget {
111
- const NetworkLogTile ({super .key, required this .entry});
142
+ const NetworkLogTile (
143
+ {super .key,
144
+ required this .entry,
145
+ this .showTimestamp = false ,
146
+ this .requestName});
112
147
final TerminalEntry entry;
148
+ final bool showTimestamp;
149
+ final String ? requestName;
113
150
@override
114
151
State <NetworkLogTile > createState () => _NetworkLogTileState ();
115
152
}
@@ -123,6 +160,11 @@ class _NetworkLogTileState extends State<NetworkLogTile> {
123
160
final status = n.responseStatus != null ? '${n .responseStatus }' : null ;
124
161
final duration =
125
162
n.duration != null ? '${n .duration !.inMilliseconds } ms' : null ;
163
+ final title = [
164
+ if (widget.requestName != null && widget.requestName! .isNotEmpty)
165
+ '[${widget .requestName }]' ,
166
+ methodUrl,
167
+ ].join (' ' );
126
168
return Column (
127
169
children: [
128
170
InkWell (
@@ -131,9 +173,18 @@ class _NetworkLogTileState extends State<NetworkLogTile> {
131
173
padding: const EdgeInsets .symmetric (horizontal: 12 , vertical: 10 ),
132
174
child: Row (
133
175
children: [
176
+ if (widget.showTimestamp) ...[
177
+ Padding (
178
+ padding: const EdgeInsets .only (right: 8 ),
179
+ child: Text (
180
+ _formatTs (widget.entry.ts),
181
+ style: Theme .of (context).textTheme.bodySmall,
182
+ ),
183
+ ),
184
+ ],
134
185
Expanded (
135
186
child: Text (
136
- methodUrl ,
187
+ title ,
137
188
maxLines: 1 ,
138
189
overflow: TextOverflow .ellipsis,
139
190
style: Theme .of (context).textTheme.bodyMedium,
@@ -220,3 +271,11 @@ class NetworkDetails extends StatelessWidget {
220
271
return SelectableText (lines);
221
272
}
222
273
}
274
+
275
+ String _formatTs (DateTime ts) {
276
+ // Show only time (HH:mm:ss) for compactness
277
+ final h = ts.hour.toString ().padLeft (2 , '0' );
278
+ final m = ts.minute.toString ().padLeft (2 , '0' );
279
+ final s = ts.second.toString ().padLeft (2 , '0' );
280
+ return '$h :$m :$s ' ;
281
+ }
0 commit comments