From b5e0822d6ca7efd45add49634260740f4e98b9d3 Mon Sep 17 00:00:00 2001 From: Kieran Date: Fri, 16 May 2025 12:33:34 +0100 Subject: [PATCH] feat: live timer closes #23 --- lib/utils.dart | 8 ++++++ lib/widgets/live_timer.dart | 49 ++++++++++++++++++++++++++++++++++++ lib/widgets/stream_info.dart | 23 +++++++++++------ 3 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 lib/widgets/live_timer.dart diff --git a/lib/utils.dart b/lib/utils.dart index ea9f952..dbb9e39 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -374,6 +374,14 @@ Map topZapReceiver(Iterable zaps) { ); } +String formatSecondsToHHMMSS(int seconds) { + int hours = seconds ~/ 3600; + int minutes = (seconds % 3600) ~/ 60; + int remainingSeconds = seconds % 60; + + return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}'; +} + String bech32ToHex(String bech32) { final decoder = Bech32Decoder(); final data = decoder.convert(bech32, 10_000); diff --git a/lib/widgets/live_timer.dart b/lib/widgets/live_timer.dart new file mode 100644 index 0000000..df54195 --- /dev/null +++ b/lib/widgets/live_timer.dart @@ -0,0 +1,49 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:zap_stream_flutter/theme.dart'; +import 'package:zap_stream_flutter/utils.dart'; +import 'package:zap_stream_flutter/widgets/pill.dart'; + +class LiveTimerWidget extends StatefulWidget { + final DateTime started; + + const LiveTimerWidget({super.key, required this.started}); + + @override + createState() => _LiveTimerWidget(); +} + +class _LiveTimerWidget extends State { + late Timer _timer; + + @override + void initState() { + super.initState(); + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + // tick + }); + }); + } + + @override + void dispose() { + _timer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return PillWidget( + color: LAYER_2, + child: Text( + formatSecondsToHHMMSS( + ((DateTime.now().millisecondsSinceEpoch - + widget.started.millisecondsSinceEpoch) / + 1000) + .toInt(), + ), + ), + ); + } +} diff --git a/lib/widgets/stream_info.dart b/lib/widgets/stream_info.dart index 99c474d..49d15de 100644 --- a/lib/widgets/stream_info.dart +++ b/lib/widgets/stream_info.dart @@ -5,6 +5,7 @@ import 'package:zap_stream_flutter/theme.dart'; import 'package:zap_stream_flutter/utils.dart'; import 'package:zap_stream_flutter/widgets/button_follow.dart'; import 'package:zap_stream_flutter/widgets/game_info.dart'; +import 'package:zap_stream_flutter/widgets/live_timer.dart'; import 'package:zap_stream_flutter/widgets/nostr_text.dart'; import 'package:zap_stream_flutter/widgets/pill.dart'; import 'package:zap_stream_flutter/widgets/profile.dart'; @@ -39,14 +40,20 @@ class StreamInfoWidget extends StatelessWidget { style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), if (startedDate != null) - RichText( - text: TextSpan( - style: TextStyle(color: LAYER_5, fontSize: 14), - children: [ - TextSpan(text: "Started "), - TextSpan(text: DateFormat().format(startedDate)), - ], - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RichText( + text: TextSpan( + style: TextStyle(color: LAYER_5, fontSize: 14), + children: [ + TextSpan(text: "Started "), + TextSpan(text: DateFormat().format(startedDate)), + ], + ), + ), + LiveTimerWidget(started: startedDate), + ], ), if (stream.info.summary?.isNotEmpty ?? false) Text.rich(