diff --git a/lib/utils/formatters.dart b/lib/utils/formatters.dart index d3baae62..0ed1383d 100644 --- a/lib/utils/formatters.dart +++ b/lib/utils/formatters.dart @@ -182,8 +182,9 @@ DurationLocale _getDurationLocale() { /// Formats the clock time at which media will finish playing, given the remaining duration. /// Returns a localized time string like "6:12 PM" or "18:12" depending on locale. -String formatFinishTime(Duration remaining) { - final finishTime = DateTime.now().add(remaining); +String formatFinishTime(Duration remaining, {double rate = 1.0}) { + final adjustedRemaining = remaining * (1.0 / rate); + final finishTime = DateTime.now().add(adjustedRemaining); final formatter = DateFormat.jm(LocaleSettings.currentLocale.languageCode); return formatter.format(finishTime); } diff --git a/lib/widgets/video_controls/desktop_video_controls.dart b/lib/widgets/video_controls/desktop_video_controls.dart index 298286c2..0888871c 100644 --- a/lib/widgets/video_controls/desktop_video_controls.dart +++ b/lib/widgets/video_controls/desktop_video_controls.dart @@ -544,16 +544,23 @@ class DesktopVideoControlsState extends State { stream: widget.player.streams.duration, initialData: widget.player.state.duration, builder: (context, durSnap) { - final position = posSnap.data ?? Duration.zero; - final duration = durSnap.data ?? Duration.zero; - final remaining = duration - position; - if (remaining.inSeconds <= 0) return const SizedBox.shrink(); - return Padding( - padding: const EdgeInsets.only(left: 8), - child: Text( - t.videoControls.endsAt(time: formatFinishTime(remaining)), - style: const TextStyle(color: Colors.white70, fontSize: 13), - ), + return StreamBuilder( + stream: widget.player.streams.rate, + initialData: widget.player.state.rate, + builder: (context, rateSnap) { + final position = posSnap.data ?? Duration.zero; + final duration = durSnap.data ?? Duration.zero; + final remaining = duration - position; + final rate = rateSnap.data ?? 1.0; + if (remaining.inSeconds <= 0) return const SizedBox.shrink(); + return Padding( + padding: const EdgeInsets.only(left: 8), + child: Text( + t.videoControls.endsAt(time: formatFinishTime(remaining, rate: rate)), + style: const TextStyle(color: Colors.white70, fontSize: 13), + ), + ); + }, ); }, ); diff --git a/lib/widgets/video_controls/widgets/video_timeline_bar.dart b/lib/widgets/video_controls/widgets/video_timeline_bar.dart index 28066c56..0269adcb 100644 --- a/lib/widgets/video_controls/widgets/video_timeline_bar.dart +++ b/lib/widgets/video_controls/widgets/video_timeline_bar.dart @@ -111,8 +111,15 @@ class VideoTimelineBar extends StatelessWidget { if (!showFinishTime || remaining.inSeconds >= 0) { return _buildTimestamp(remaining); } - final text = '${formatDurationTimestamp(remaining)} · ${formatFinishTime(remaining.abs())}'; - return Text(text, style: const TextStyle(color: Colors.white, fontSize: 14)); + return StreamBuilder( + stream: player.streams.rate, + initialData: player.state.rate, + builder: (context, rateSnap) { + final rate = rateSnap.data ?? 1.0; + final text = '${formatDurationTimestamp(remaining)} · ${formatFinishTime(remaining.abs(), rate: rate)}'; + return Text(text, style: const TextStyle(color: Colors.white, fontSize: 14)); + }, + ); } Widget _buildSlider(Duration position, Duration duration) {