118 lines
4.4 KiB
Dart
118 lines
4.4 KiB
Dart
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,
|
||
this.nebula = false,
|
||
});
|
||
|
||
final EclipseRepository repository;
|
||
final String fandomId;
|
||
|
||
/// 내 팬덤이 아직 성운인가 — 상세 · 방어 화면이 성운 그림을 그린다.
|
||
final bool nebula;
|
||
|
||
@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(
|
||
// 명세 `516:88164` 「닫기 — 하단 move out」 — 아래에서 올라오는 전체 화면.
|
||
eclipseDefendRoute(
|
||
repository: repository,
|
||
fandomId: state.fandomId,
|
||
nebula: nebula,
|
||
),
|
||
),
|
||
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;
|
||
}
|