이클립스 흐름 — 배너 진입 · 이벤트 버튼 · 오버레이 · 방어 진행 표시 · 흔들기 감지 통일

This commit is contained in:
Sn-Kinos
2026-10-05 19:05:21 +09:00
parent be623d2e46
commit 576dcfbdfd
27 changed files with 1369 additions and 369 deletions
+29 -4
View File
@@ -29,6 +29,8 @@ class EclipseState {
required this.defenseCount,
required this.defended,
this.qualifyShakes = 60,
this.startAt,
this.scheduled = false,
this.endsAt,
this.result,
this.mockNote,
@@ -60,7 +62,21 @@ class EclipseState {
/// 서버 확정 판정. 단말 타이머 만료는 failure가 아니다.
final EclipseResult? result;
bool get canDefend => result == null && !defended && endsAt != null && !isExpired(DateTime.now());
bool get canDefend => !scheduled && canShake(DateTime.now());
/// 흔들기를 받을 때인가 — 발생 시각이 지났고 아직 열려 있다. 서버가 회차를 `active` 로
/// 바꾸기 전(스케줄러 지연 수 초)의 흔들기는 모아 두었다가 [canDefend] 가 되면 보낸다.
bool canShake(DateTime now) =>
result == null && !defended && endsAt != null && hasStarted(now) && !isExpired(now);
/// 발생 시각. 사전 알림(`warnAt`)부터 문서가 있으므로 그 전에는 남은 시간을 센다.
/// 없으면 이미 시작한 회차로 본다.
final DateTime? startAt;
/// 서버 회차가 아직 `scheduled`(경보 단계)인가. 방어 호출은 `active` 에서만 받는다.
final bool scheduled;
bool hasStarted(DateTime now) => startAt == null || !startAt!.isAfter(now);
/// 방어 마감. 없으면 남은 시간을 띄우지 않는다.
final DateTime? endsAt;
@@ -172,7 +188,13 @@ enum LiveEventKind {
abstract interface class EclipseRepository {
/// 활성 이클립스. [fandomId] 를 주지 않으면 내 소속 팬덤을 본다.
/// 기본은 활성 회차만, includeResults는 방어 화면에서 마감 후 판정까지 받는다.
Stream<EclipseState?> watch({String? fandomId, bool includeResults = false});
/// includeScheduled는 사전 알림(`warnAt`)부터의 `scheduled` 회차도 받는다 — HOME 이클립스
/// 이벤트 버튼(`516:88125` 「발생 N분 전 노출」)과 이클립스 상세가 쓴다.
Stream<EclipseState?> watch({
String? fandomId,
bool includeResults = false,
bool includeScheduled = false,
});
/// 최근 티커 이벤트. 최신순.
Stream<List<LiveEvent>> liveEvents({String? fandomId, int limit = 20});
@@ -214,8 +236,11 @@ class SampleEclipseRepository implements EclipseRepository {
);
@override
Stream<EclipseState?> watch({String? fandomId, bool includeResults = false}) =>
Stream.value(_snapshot(fandomId: fandomId));
Stream<EclipseState?> watch({
String? fandomId,
bool includeResults = false,
bool includeScheduled = false,
}) => Stream.value(_snapshot(fandomId: fandomId));
@override
Stream<List<LiveEvent>> liveEvents({String? fandomId, int limit = 20}) {