import 'dart:async'; import 'package:flutter/widgets.dart'; import '../../../core/data/server_clock.dart'; /// 타임어택 남은 시간 — 초마다 다시 그린다. 마감은 서버 값(`quests.activeTo`)이라 /// 화면을 다시 열어도 처음부터 세지 않는다. 기준은 [ServerClock] 이다. 마감이 지나면 /// [builder] 가 null 을 받고 타이머를 멈춘다. /// /// 표시용이다. 참여 수락/거부는 서버 시각으로 다시 판정한다(`fn-quest-timeattack`). class TimeAttackCountdown extends StatefulWidget { const TimeAttackCountdown({ super.key, required this.endsAt, required this.builder, }); final DateTime endsAt; final Widget Function(BuildContext context, Duration? left) builder; @override State createState() => _TimeAttackCountdownState(); } class _TimeAttackCountdownState extends State { late final Timer _timer; @override void initState() { super.initState(); _timer = Timer.periodic(const Duration(seconds: 1), (_) => setState(() {})); } @override void dispose() { _timer.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final left = widget.endsAt.difference(ServerClock.now()); final closed = left.isNegative || left == Duration.zero; if (closed) _timer.cancel(); return widget.builder(context, closed ? null : left); } } /// `H:MM:SS`(1시간 이상) 또는 `MM:SS`. String formatLeft(Duration left) { String two(int n) => n.toString().padLeft(2, '0'); final h = left.inHours; final m = two(left.inMinutes % 60); final s = two(left.inSeconds % 60); return h > 0 ? '$h:$m:$s' : '$m:$s'; }