QUEST · CAMPAIGN 화면 — 퀘스트 참여·생성·인증 · 캠페인 목록·상세·후원·랭킹
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
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<TimeAttackCountdown> createState() => _TimeAttackCountdownState();
|
||||
}
|
||||
|
||||
class _TimeAttackCountdownState extends State<TimeAttackCountdown> {
|
||||
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';
|
||||
}
|
||||
Reference in New Issue
Block a user