Figma 설명 프레임 반영 — 로그인·온보딩·스플래시 · HOME · GALAXY · 퀘스트·이클립스·알림
This commit is contained in:
@@ -314,32 +314,42 @@ class _Contribution extends StatelessWidget {
|
||||
Widget build(BuildContext context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 성운·첫 사용자 상태의 「{닉네임} 님의」는 기여 여부와 무관한 인사 줄이다.
|
||||
if (growth.hasRecentContribution ||
|
||||
((!joined || growth.isNebula) &&
|
||||
growth.contributorName.trim().isNotEmpty)) ...[
|
||||
// 「{닉네임} 님의」는 로그인 사용자의 인사 줄이다(설명 프레임 `2097:16391`).
|
||||
if (growth.contributorName.trim().isNotEmpty) ...[
|
||||
Row(
|
||||
children: [
|
||||
// 프로필 사진 자산이 데이터에 없어 이니셜로 그린다.
|
||||
// 로그인 사용자의 프로필 사진(`2097:16391` 「프로필 - 이미지」). 없으면 이니셜.
|
||||
Container(
|
||||
width: 26,
|
||||
height: 26,
|
||||
alignment: Alignment.center,
|
||||
decoration: const BoxDecoration(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
// 사본 `Ellipse 3` #9BF8A8(프로필 사진이 없을 때의 바탕).
|
||||
color: Color(0xFF9BF8A8),
|
||||
boxShadow: [BoxShadow(color: Color(0xB3000000), blurRadius: 4)],
|
||||
),
|
||||
child: Text(
|
||||
growth.contributorName.characters.firstOrNull ?? '—',
|
||||
style: const TextStyle(
|
||||
fontFamily: AppFonts.body,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
color: const Color(0xFF9BF8A8),
|
||||
boxShadow: const [
|
||||
BoxShadow(color: Color(0xB3000000), blurRadius: 4),
|
||||
],
|
||||
image: growth.photoUrl == null
|
||||
? null
|
||||
: DecorationImage(
|
||||
image: NetworkImage(growth.photoUrl!),
|
||||
fit: BoxFit.cover,
|
||||
onError: (_, _) {},
|
||||
),
|
||||
),
|
||||
child: growth.photoUrl != null
|
||||
? null
|
||||
: Text(
|
||||
growth.contributorName.characters.firstOrNull ?? '—',
|
||||
style: const TextStyle(
|
||||
fontFamily: AppFonts.body,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 9),
|
||||
Text(
|
||||
@@ -686,8 +696,10 @@ class _Nebula extends StatelessWidget {
|
||||
Semantics(
|
||||
button: ready && onBirth != null,
|
||||
label: context.l10n.heroNebula,
|
||||
child: GestureDetector(
|
||||
onTap: ready ? onBirth : null,
|
||||
// Figma `2013:15377` 「성운 터치시 흔들림」 — 조건 전에도 흔들림 · 가벼운 햅틱으로 반응하고,
|
||||
// 탄생 조건을 채웠으면 흔들린 뒤 행성 생성으로 간다.
|
||||
child: _TapShake(
|
||||
onTap: ready && onBirth != null ? onBirth : () {},
|
||||
child: Image.asset(
|
||||
'assets/figma/nebula-home.png',
|
||||
width: 212,
|
||||
@@ -1018,6 +1030,9 @@ class HomeZap extends StatelessWidget {
|
||||
onItem: onItem,
|
||||
zapPop: data.zapPop,
|
||||
myPop: (zap.balance ?? data.myPop) - zap.pending * data.zapPop,
|
||||
// Figma `516:88102` Zap_버프(아이템 배수 · 지속시간)는 별첨 B B-22 「배수 기능 제거」 ·
|
||||
// 10/3 통합회신(C-124) 「사용 시 Drop Pool 발생 후 HERO TIME 발동」이 대체한다 —
|
||||
// 같은 팬덤의 아이템 사용으로 HERO TIME 이 열리면 ZAP 이 Drop POP 참여로 바뀐다.
|
||||
isHeroTime: hero,
|
||||
blockedReason: zap.sending
|
||||
? context.l10n.zapApplying
|
||||
|
||||
@@ -2,12 +2,10 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/i18n/app_locale.dart';
|
||||
import '../../../core/theme/tokens.dart';
|
||||
import '../../../core/ui/app_icons.dart';
|
||||
import '../../quest/widgets/quest_card_tile.dart'
|
||||
show QuestIconBox, questImageFor;
|
||||
import '../../quest/widgets/time_attack_countdown.dart';
|
||||
import '../home_data.dart';
|
||||
|
||||
/// 홈 「TODAY'S QUEST」 묶음 — Figma 「홈」 `2097:16428`: 343×270 · r12 안에 343×90 줄
|
||||
@@ -45,8 +43,9 @@ class QuestRows extends StatelessWidget {
|
||||
/// 오른쪽 chevron 24 #4F4F4F.
|
||||
///
|
||||
/// 보조 줄은 카테고리(사본 「오늘의 출석체크」 · 「커뮤니티」)다. 「홈」 프레임에는 보상 숫자 ·
|
||||
/// 진행 상태가 없어 그리지 않는다. 예외는 긴급 타임어택의 남은 시간 하나 — FR-QST-06
|
||||
/// 「홈 카운트다운」이 요구한다.
|
||||
/// 진행 상태가 없어 그리지 않는다. 타임어택 남은 시간도 그리지 않는다 — 설명 프레임
|
||||
/// `2097:16397` 데이터는 「어드민에서 등록된 퀘스트」뿐이고, FR-QST-06 · 원장 C-94 의 카운트다운
|
||||
/// 표시 위치는 퀘스트 목록 · 상세다.
|
||||
class QuestRow extends StatelessWidget {
|
||||
const QuestRow({
|
||||
super.key,
|
||||
@@ -65,7 +64,6 @@ class QuestRow extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final done = quest.state == QuestState.done;
|
||||
return Material(
|
||||
color: AppColors.cosmicSurfaceContainer,
|
||||
shape: divider
|
||||
@@ -100,20 +98,7 @@ class QuestRow extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
// 타임어택은 받기 전까지 남은 시간을 센다(FR-QST-06).
|
||||
if (quest.endsAt case final endsAt? when !done)
|
||||
TimeAttackCountdown(
|
||||
endsAt: endsAt,
|
||||
builder: (context, left) => _sub(
|
||||
left == null
|
||||
? context.l10n.questTimeAttackClosed
|
||||
: context.l10n.questTimeAttackLeft(
|
||||
formatLeft(left),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
_sub(quest.category ?? ''),
|
||||
_sub(quest.category ?? ''),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user