Files
fanuzu/app/lib/features/eclipse/widgets/eclipse_event_button.dart
T

116 lines
4.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import '../../../core/i18n/app_locale.dart';
import '../../../core/theme/tokens.dart';
import '../../../core/ui/live_stream.dart';
import '../eclipse_data.dart';
import '../eclipse_defend_screen.dart';
/// HOME 이클립스 이벤트 버튼 — 사본 「홈」(`373:443167`)의 `Group 563`.
///
/// 명세 `516:88125` *데이터: 이클립스 발생 잔여 시간 · 규칙: 성운(행성) 아래 중앙 정렬,
/// 어드민에서 설정된 이클립스 이벤트 발생 시간의 N분 전 노출 · 동작: 클릭 시 이클립스 상세로
/// 이동*. N분은 서버 회차의 `warnAt`(원장 C-22 발생 3분 전)이다 — 회차 문서가 그때부터
/// `scheduled` 로 있으므로 그 문서가 보이는 동안 띄운다. 발생 뒤 방어 창(60초) 동안은
/// 남은 초로 바뀌고, 결과가 나거나 창이 닫히면 접는다.
///
/// 모양: 위를 가리키는 꼭지 + 검정 80% 알약(229×46 · r 끝까지) · 42dot Medium 12 흰색 두 줄.
class EclipseEventButton extends StatelessWidget {
const EclipseEventButton({
super.key,
required this.repository,
required this.fandomId,
});
final EclipseRepository repository;
final String fandomId;
@override
Widget build(BuildContext context) => LiveStreamBuilder<EclipseState?>(
key: ValueKey('eclipse-button-$fandomId'),
create: () => repository.watch(fandomId: fandomId, includeScheduled: true),
builder: (context, state) {
if (state == null) return const SizedBox.shrink();
return EclipseTicker(
builder: (context, now) {
if (state.result != null || state.defended || state.isExpired(now)) {
return const SizedBox.shrink();
}
final text = state.hasStarted(now)
? context.l10n.eclipseButtonActive(
'${((state.remaining(now)?.inMilliseconds ?? 0) / 1000).ceil()}',
)
: context.l10n.eclipseButtonSoon(
eclipseLeftLabel(state.startAt!.difference(now)),
);
return Semantics(
button: true,
liveRegion: true,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute<void>(
// 명세 `516:88164` 「닫기 — 하단 move out」 — 아래에서 올라오는 전체 화면.
fullscreenDialog: true,
builder: (_) => EclipseDefendScreen(
repository: repository,
fandomId: state.fandomId,
),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CustomPaint(
size: const Size(16, 7),
painter: _Tip(),
),
Container(
constraints: const BoxConstraints(minWidth: 229, minHeight: 46),
padding: const EdgeInsets.symmetric(
horizontal: AppSpace.s4,
vertical: 6,
),
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xCC000000),
borderRadius: BorderRadius.circular(AppRadius.full),
),
child: Text(
text,
textAlign: TextAlign.center,
style: const TextStyle(
fontFamily: AppFonts.body,
fontSize: 12,
fontWeight: FontWeight.w500,
height: 17 / 12,
color: AppColors.onCosmic,
),
),
),
],
),
),
);
},
);
},
);
}
/// 말풍선 꼭지 — 행성을 가리킨다.
class _Tip extends CustomPainter {
@override
void paint(Canvas canvas, Size size) => canvas.drawPath(
Path()
..moveTo(size.width / 2, 0)
..lineTo(size.width, size.height)
..lineTo(0, size.height)
..close(),
Paint()..color = const Color(0xCC000000),
);
@override
bool shouldRepaint(_Tip old) => false;
}