사용자 화면 문구·표본 데이터 · 퀘스트 참여 흐름 · HOME 진입 구획 · 미니맵 · 공통 확인 창 배치 수정
This commit is contained in:
@@ -31,6 +31,7 @@ import 'widgets/item_sheet.dart';
|
||||
import 'widgets/inside_card.dart';
|
||||
import 'widgets/live_ticker.dart';
|
||||
import '../campaign/campaign_data.dart' show CampaignRepository;
|
||||
import '../campaign/campaign_create_screen.dart';
|
||||
import '../campaign/campaign_list_screen.dart';
|
||||
import '../notification/notification_screen.dart';
|
||||
import '../quest/quest_data.dart' show QuestRepository;
|
||||
@@ -150,19 +151,22 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
debugPrint('[HOME] load failed: ${snap.error}');
|
||||
return SafeArea(child: _LoadFailed(onRetry: _refresh));
|
||||
}
|
||||
return _HomeBody(
|
||||
data: snap.data!,
|
||||
galaxy: _galaxy,
|
||||
zap: _zap,
|
||||
repository: widget.repository,
|
||||
watchPlanet: widget.watchPlanet,
|
||||
planetRepository: widget.planetRepository,
|
||||
onRefresh: _refresh,
|
||||
onCreate: _createThenReload,
|
||||
questRepository: widget.questRepository,
|
||||
campaignRepository: widget.campaignRepository,
|
||||
eclipse: widget.eclipse,
|
||||
notifications: widget.notifications,
|
||||
return _StatusBarScrim(
|
||||
height: MediaQuery.paddingOf(context).top,
|
||||
child: _HomeBody(
|
||||
data: snap.data!,
|
||||
galaxy: _galaxy,
|
||||
zap: _zap,
|
||||
repository: widget.repository,
|
||||
watchPlanet: widget.watchPlanet,
|
||||
planetRepository: widget.planetRepository,
|
||||
onRefresh: _refresh,
|
||||
onCreate: _createThenReload,
|
||||
questRepository: widget.questRepository,
|
||||
campaignRepository: widget.campaignRepository,
|
||||
eclipse: widget.eclipse,
|
||||
notifications: widget.notifications,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -352,7 +356,7 @@ class _HomeBody extends StatelessWidget {
|
||||
zap == null
|
||||
? null
|
||||
: GalaxyMiniMap(
|
||||
size: 140,
|
||||
size: HomeHero.miniMapSize,
|
||||
data: galaxyState.data!,
|
||||
onOpen: () =>
|
||||
Navigator.of(context, rootNavigator: true).push(
|
||||
@@ -531,24 +535,39 @@ class _HomeBody extends StatelessWidget {
|
||||
const SizedBox(height: _sectionGap),
|
||||
],
|
||||
|
||||
if (data.campaign case final c?) ...[
|
||||
Padding(
|
||||
padding: _h,
|
||||
child: SectionHeader(
|
||||
title: 'HOT ARCHIVE',
|
||||
onMore: () => _openCampaigns(context, campaignRepository),
|
||||
),
|
||||
// HOT ARCHIVE 는 모금 중 캠페인이 없어도 둔다 — 기능명세서 v1.4 §2.114-6
|
||||
// (`2097:16415`) 「더보기 버튼 - HOT ARCHIVE 화면 이동」에 숨김 규칙이 없고,
|
||||
// 캠페인 목록·개설로 가는 길이 이 구획뿐이다(공통 기준 5항).
|
||||
Padding(
|
||||
padding: _h,
|
||||
child: SectionHeader(
|
||||
title: 'HOT ARCHIVE',
|
||||
onMore: () => _openCampaigns(context, campaignRepository),
|
||||
),
|
||||
const SizedBox(height: _headerGap),
|
||||
Padding(
|
||||
padding: _h,
|
||||
child: CampaignCard(
|
||||
),
|
||||
const SizedBox(height: _headerGap),
|
||||
Padding(
|
||||
padding: _h,
|
||||
child: switch (data.campaign) {
|
||||
final c? => CampaignCard(
|
||||
campaign: c,
|
||||
onTap: () => _openCampaigns(context, campaignRepository),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: _sectionGap),
|
||||
],
|
||||
// 0 건 — 「새 캠페인」(Figma `179:29123` 캠페인 개설)으로 바로 간다.
|
||||
null => Center(
|
||||
child: CampaignFab(
|
||||
label: context.l10n.campaignNew,
|
||||
onTap: () => Navigator.of(context, rootNavigator: true).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) =>
|
||||
CampaignCreateScreen(repository: campaignRepository),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
const SizedBox(height: _sectionGap),
|
||||
|
||||
Padding(
|
||||
padding: _h,
|
||||
@@ -575,6 +594,51 @@ class _HomeBody extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 상태 표시줄 가림막 — 히어로는 상태 표시줄 뒤까지 배경을 깔아야 해서 목록에
|
||||
/// SafeArea 를 주지 않는다. 대신 세로로 스크롤되면 상태 표시줄 자리를 화면 배경색으로
|
||||
/// 덮어, 아래 구획 머리글(TODAY'S QUEST 등)이 시계·배터리와 겹쳐 그려지지 않게 한다.
|
||||
class _StatusBarScrim extends StatefulWidget {
|
||||
const _StatusBarScrim({required this.height, required this.child});
|
||||
|
||||
final double height;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<_StatusBarScrim> createState() => _StatusBarScrimState();
|
||||
}
|
||||
|
||||
class _StatusBarScrimState extends State<_StatusBarScrim> {
|
||||
bool _scrolled = false;
|
||||
|
||||
bool _onScroll(ScrollNotification n) {
|
||||
// 퀘스트 카드의 가로 스크롤은 무시한다 — 바깥 세로 목록만 본다.
|
||||
if (n.depth != 0 || n.metrics.axis != Axis.vertical) return false;
|
||||
final scrolled = n.metrics.pixels > 0;
|
||||
if (scrolled != _scrolled) setState(() => _scrolled = scrolled);
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
NotificationListener<ScrollNotification>(
|
||||
onNotification: _onScroll,
|
||||
child: widget.child,
|
||||
),
|
||||
if (_scrolled)
|
||||
Positioned(
|
||||
key: const ValueKey('home-status-scrim'),
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: widget.height,
|
||||
child: const ColoredBox(color: AppColors.cosmicVoid),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 상단 활동 POP 잔액. 정책 설계서 §P-02 — 화면 표기는 「활동/지원」이다.
|
||||
class _PopBalance extends StatelessWidget {
|
||||
const _PopBalance({this.value});
|
||||
|
||||
Reference in New Issue
Block a user