이클립스 사전 경고 연출 · 브리핑 출처·게시시각 · PASSPORT 역사적 사건 Stamp

This commit is contained in:
Sn-Kinos
2026-10-08 15:43:12 +09:00
parent 62b9637db9
commit 586039da0a
26 changed files with 1223 additions and 1013 deletions
+8 -1
View File
@@ -377,7 +377,14 @@ enum PlanetHistoryKind {
/// PASSPORT Stamp — Eclipse 성공 참여(FX §5.2) · 진화 기념 Emblem(상세정의 22장) · 최초 100명 Badge(별첨 B).
eclipseSuccess,
emblemEvolution,
founderBadge,
founderBadge;
/// UX·FX v1.5 §7.2 「역사적 사건」 — Planet Evolution · Eclipse 성공 참여 · 주요 Badge 획득은
/// 일반 활동 로그와 구분되는 Stamp 로 보인다. Campaign 성공은 역사 응답에 종류가 없어 아직 빠진다.
bool get isHistoric => switch (this) {
evolution || eclipseSuccess || emblemEvolution || founderBadge => true,
_ => false,
};
}
class PlanetHistoryEntry {
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'planet_data.dart';
import '../../core/i18n/app_locale.dart';
import '../../core/ui/bottom_inset.dart';
@@ -86,47 +87,52 @@ class _PlanetHistoryScreenState extends State<PlanetHistoryScreen> {
),
const SizedBox(height: 16),
for (final item in _items)
ListTile(
contentPadding: EdgeInsets.zero,
leading: Icon(switch (item.kind) {
PlanetHistoryKind.evolution => Icons.auto_awesome,
PlanetHistoryKind.hibernation => Icons.bedtime_outlined,
PlanetHistoryKind.wakeUp => Icons.wb_sunny_outlined,
PlanetHistoryKind.zap => Icons.bolt,
PlanetHistoryKind.questReward => Icons.task_alt,
PlanetHistoryKind.companyAdBonus => Icons.play_circle_outline,
PlanetHistoryKind.funding => Icons.favorite_border,
PlanetHistoryKind.eclipseSuccess => Icons.shield_outlined,
PlanetHistoryKind.emblemEvolution => Icons.military_tech_outlined,
PlanetHistoryKind.founderBadge => Icons.workspace_premium_outlined,
}),
title: Text(switch (item.kind) {
PlanetHistoryKind.evolution => context.l10n.historyEvolution(
'${item.fromStage}',
'${item.toStage}',
_Stamp(
historic: item.kind.isHistoric,
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: Icon(switch (item.kind) {
PlanetHistoryKind.evolution => Icons.auto_awesome,
PlanetHistoryKind.hibernation => Icons.bedtime_outlined,
PlanetHistoryKind.wakeUp => Icons.wb_sunny_outlined,
PlanetHistoryKind.zap => Icons.bolt,
PlanetHistoryKind.questReward => Icons.task_alt,
PlanetHistoryKind.companyAdBonus => Icons.play_circle_outline,
PlanetHistoryKind.funding => Icons.favorite_border,
PlanetHistoryKind.eclipseSuccess => Icons.shield_outlined,
PlanetHistoryKind.emblemEvolution =>
Icons.military_tech_outlined,
PlanetHistoryKind.founderBadge =>
Icons.workspace_premium_outlined,
}),
title: Text(switch (item.kind) {
PlanetHistoryKind.evolution => context.l10n.historyEvolution(
'${item.fromStage}',
'${item.toStage}',
),
PlanetHistoryKind.hibernation =>
context.l10n.historyHibernation,
PlanetHistoryKind.wakeUp => context.l10n.historyWakeUp,
PlanetHistoryKind.zap => context.l10n.historyZap,
PlanetHistoryKind.questReward => context.l10n.historyQuest,
PlanetHistoryKind.companyAdBonus => context.l10n.historyAdBonus,
PlanetHistoryKind.funding => context.l10n.historyFunding,
PlanetHistoryKind.eclipseSuccess =>
context.l10n.historyEclipseSuccess,
PlanetHistoryKind.emblemEvolution =>
'${context.l10n.historyEmblemEvolution} · STAGE ${item.toStage ?? ''}',
PlanetHistoryKind.founderBadge =>
'${context.l10n.historyFounderBadge} · #${(item.memberNo ?? 0).toString().padLeft(3, '0')}',
}),
subtitle: Text(
[
MaterialLocalizations.of(context)
.formatMediumDate(item.occurredAt.toLocal()),
if (item.amount != null)
context.l10n.historyGrowthPop('${item.amount}'),
if (item.participationConfirmed) context.l10n.historyJoined,
].join('\n'),
),
PlanetHistoryKind.hibernation => context.l10n.historyHibernation,
PlanetHistoryKind.wakeUp => context.l10n.historyWakeUp,
PlanetHistoryKind.zap => context.l10n.historyZap,
PlanetHistoryKind.questReward => context.l10n.historyQuest,
PlanetHistoryKind.companyAdBonus => context.l10n.historyAdBonus,
PlanetHistoryKind.funding => context.l10n.historyFunding,
PlanetHistoryKind.eclipseSuccess =>
context.l10n.historyEclipseSuccess,
PlanetHistoryKind.emblemEvolution =>
'${context.l10n.historyEmblemEvolution} · STAGE ${item.toStage ?? ''}',
PlanetHistoryKind.founderBadge =>
'${context.l10n.historyFounderBadge} · #${(item.memberNo ?? 0).toString().padLeft(3, '0')}',
}),
subtitle: Text(
[
MaterialLocalizations.of(
context,
).formatMediumDate(item.occurredAt.toLocal()),
if (item.amount != null)
context.l10n.historyGrowthPop('${item.amount}'),
if (item.participationConfirmed) context.l10n.historyJoined,
].join('\n'),
),
),
if (_loading) const Center(child: CircularProgressIndicator()),
@@ -145,3 +151,36 @@ class _PlanetHistoryScreenState extends State<PlanetHistoryScreen> {
),
);
}
/// 「역사적 사건」(UX·FX v1.5 §7.2)은 테두리 Stamp 와 표지로 일반 활동 줄과 가른다.
/// 앱 Figma 에 PASSPORT 기록 화면이 없어 화면 테마 색만 쓴다.
class _Stamp extends StatelessWidget {
const _Stamp({required this.historic, required this.child});
final bool historic;
final Widget child;
@override
Widget build(BuildContext context) {
if (!historic) return child;
final scheme = Theme.of(context).colorScheme;
return Container(
margin: const EdgeInsets.symmetric(vertical: 4),
padding: const EdgeInsets.fromLTRB(12, 8, 12, 0),
decoration: BoxDecoration(
border: Border.all(color: scheme.primary),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.l10n.historyHistoric,
style: Theme.of(context).textTheme.labelSmall
?.copyWith(color: scheme.primary),
),
child,
],
),
);
}
}