Skip to content

Commit 4da65d6

Browse files
waveverclaude
andcommitted
fix(dashboard): display runtime over 99:59:59 with auto-adaptive button width
- Show total hours in hh:mm:ss format (up to 99:59:59) - Switch to dd hh:mm:ss format only when hours exceed 99 - Cache text width per format to avoid redundant measurement every frame - Button width auto-adapts to text length without truncation Fixes #1824 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 672eacc commit 4da65d6

2 files changed

Lines changed: 43 additions & 37 deletions

File tree

lib/common/utils.dart

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,24 @@ class Utils {
7676
}
7777

7878
String getTimeDifference(DateTime dateTime) {
79-
var currentDateTime = DateTime.now();
80-
var difference = currentDateTime.difference(dateTime);
81-
var inHours = difference.inHours;
82-
var inMinutes = difference.inMinutes;
83-
var inSeconds = difference.inSeconds;
84-
85-
return '${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}';
79+
final difference = DateTime.now().difference(dateTime);
80+
return getTimeText(difference.inMilliseconds);
8681
}
8782

8883
String getTimeText(int? timeStamp) {
8984
if (timeStamp == null) {
9085
return '00:00:00';
9186
}
92-
final diff = timeStamp / 1000;
93-
final inHours = (diff / 3600).floor();
87+
final totalSeconds = (timeStamp / 1000).floor();
88+
final inHours = (totalSeconds / Duration.secondsPerHour).floor();
89+
final inMinutes = (totalSeconds / Duration.secondsPerMinute).floor() % 60;
90+
final inSeconds = totalSeconds % 60;
91+
9492
if (inHours > 99) {
95-
return '99:59:59';
93+
final inDays = (inHours / 24).floor();
94+
final remainHours = inHours % 24;
95+
return '${inDays}d ${getDateStringLast2(remainHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}';
9696
}
97-
final inMinutes = (diff / 60 % 60).floor();
98-
final inSeconds = (diff % 60).floor();
9997

10098
return '${getDateStringLast2(inHours)}:${getDateStringLast2(inMinutes)}:${getDateStringLast2(inSeconds)}';
10199
}

lib/views/dashboard/widgets/start_button.dart

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class _StartButtonState extends ConsumerState<StartButton>
1919
AnimationController? _controller;
2020
late Animation<double> _animation;
2121
bool isStart = false;
22+
double? _cachedShortWidth;
23+
double? _cachedLongWidth;
2224

2325
@override
2426
void initState() {
@@ -66,6 +68,17 @@ class _StartButtonState extends ConsumerState<StartButton>
6668
});
6769
}
6870

71+
double _measureTextWidth(String text, BuildContext context) {
72+
return globalState.measure
73+
.computeTextSize(
74+
Text(
75+
text,
76+
style: context.textTheme.titleMedium?.toSoftBold,
77+
),
78+
)
79+
.width;
80+
}
81+
6982
@override
7083
Widget build(BuildContext context) {
7184
final hasProfile = ref.watch(
@@ -83,17 +96,14 @@ class _StartButtonState extends ConsumerState<StartButton>
8396
),
8497
child: AnimatedBuilder(
8598
animation: _controller!.view,
86-
builder: (_, child) {
87-
final textWidth =
88-
globalState.measure
89-
.computeTextSize(
90-
Text(
91-
utils.getTimeDifference(DateTime.now()),
92-
style: context.textTheme.titleMedium?.toSoftBold,
93-
),
94-
)
95-
.width +
96-
16;
99+
builder: (_, __) {
100+
final runTime = ref.watch(runTimeProvider);
101+
final text = utils.getTimeText(runTime);
102+
final isLongFormat = text.contains('d ');
103+
final cachedWidth = isLongFormat
104+
? _cachedLongWidth ??= _measureTextWidth('00d 00:00:00', context)
105+
: _cachedShortWidth ??= _measureTextWidth('00:00:00', context);
106+
final textWidth = cachedWidth + 16;
97107
return FloatingActionButton(
98108
clipBehavior: Clip.antiAlias,
99109
materialTapTargetSize: MaterialTapTargetSize.padded,
@@ -113,24 +123,22 @@ class _StartButtonState extends ConsumerState<StartButton>
113123
progress: _animation,
114124
),
115125
),
116-
SizedBox(width: textWidth * _animation.value, child: child!),
126+
SizedBox(
127+
width: textWidth * _animation.value,
128+
child: Text(
129+
text,
130+
maxLines: 1,
131+
overflow: TextOverflow.visible,
132+
style: Theme.of(context).textTheme.titleMedium?.toSoftBold
133+
.copyWith(
134+
color: context.colorScheme.onPrimaryContainer,
135+
),
136+
),
137+
),
117138
],
118139
),
119140
);
120141
},
121-
child: Consumer(
122-
builder: (_, ref, _) {
123-
final runTime = ref.watch(runTimeProvider);
124-
final text = utils.getTimeText(runTime);
125-
return Text(
126-
text,
127-
maxLines: 1,
128-
overflow: TextOverflow.visible,
129-
style: Theme.of(context).textTheme.titleMedium?.toSoftBold
130-
.copyWith(color: context.colorScheme.onPrimaryContainer),
131-
);
132-
},
133-
),
134142
),
135143
);
136144
}

0 commit comments

Comments
 (0)