퀘스트 완료 햅틱 · HOME 행성 반응 · Push·라이브 띠 중복 제어 · 알림함 위계 · Push 탭 화면 이동

This commit is contained in:
Sn-Kinos
2026-10-08 15:48:56 +09:00
parent 0b95454b28
commit 93150a0d5b
28 changed files with 619 additions and 52 deletions
@@ -19,8 +19,12 @@ class ZapFeedback extends StatefulWidget {
required this.target,
required this.radius,
this.fandomName,
this.quest = false,
});
/// 퀘스트 보상 확정의 행성 반응인가 — 결과 문구를 퀘스트 반영으로 바꾼다.
final bool quest;
/// 기여가 반영된 행성 이름 — 9/21 회신 6절 「N POP 이 [팬덤] 성장에 반영되었습니다」.
final String? fandomName;
@@ -114,6 +118,12 @@ class _ZapFeedbackState extends State<ZapFeedback>
child: Text(
widget.pending
? context.l10n.zapApplying
: widget.quest
? (widget.fandomName ?? '').isNotEmpty
? context.l10n.questReflected(
widget.fandomName!,
)
: context.l10n.zapDone
: result?.contributedPop == null
? context.l10n.zapDone
: (widget.fandomName ?? '').isNotEmpty
@@ -20,8 +20,30 @@ class ZapController extends ChangeNotifier {
({String fandomId, int count, String key})? _batch;
bool get needsRetry => _batch != null && !sending;
/// 지금 결과가 ZAP 이 아니라 퀘스트 보상 확정의 행성 반응인가([react]).
bool questReaction = false;
/// 퀘스트 보상 확정 뒤 행성 반응 — v1.5 4장 「성공 햅틱 → 보상/기여 에너지 이동 → Planet 반응 →
/// 실제 지급/성장 결과」의 에너지 이동 · 반응 두 단계. ZAP 과 같은 이동 · 흡수 연출을 쓰고 잔액은
/// 건드리지 않는다. 서버가 보상을 확정한 뒤에만 부른다(C-79).
Future<void> react() async {
if (_disposed || sending || pending > 0) return;
questReaction = true;
touchSerial++;
notifyListeners();
// 에너지가 행성에 닿은 뒤 흡수 — ZapFeedback 이동 시간(380ms)과 같다.
await Future<void>.delayed(const Duration(milliseconds: 380));
if (_disposed || !questReaction) return;
result = ZapResult(
txId: 'quest-${DateTime.now().microsecondsSinceEpoch}',
balanceAfter: -1,
);
notifyListeners();
}
void tap(String fandomId) {
if (_disposed || sending || _batch != null || fandomId.isEmpty) return;
questReaction = false;
if (pending == 0) fxHaptic(FxIntensity.small);
pending++;
touchSerial++;