이클립스 방어 횟수 즉시 표시·진동 · Music Shake 영상 재생 중 흔들기 판정 · 결과 공유
This commit is contained in:
@@ -4,6 +4,7 @@ import 'dart:math' as math;
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../core/data/backend.dart';
|
||||
import '../../core/theme/tokens.dart';
|
||||
@@ -56,6 +57,11 @@ class _EclipseDefendScreenState extends State<EclipseDefendScreen>
|
||||
/// 서버가 받아들인 내 누적 참여량.
|
||||
int _mine = 0;
|
||||
|
||||
/// 화면에 보이는 내 횟수 — 서버 확정값에 아직 보내지 않았거나 보내는 중인 흔들기를 더한다.
|
||||
/// 흔드는 동안 서버 왕복(약 0.7초 묶음)을 기다리면 숫자가 늦게 올라 「얼마나 잘 흔들고
|
||||
/// 있는지」 알 수 없었다. 확정값이 오면 그것으로 맞춰진다.
|
||||
int get _shown => _mine + _pending + (_sending ? (_batch?.shakes ?? 0) : 0);
|
||||
|
||||
/// 상한에 걸려 깎인 적이 있는가. 한 번 알리고 다시 알리지 않는다.
|
||||
bool _cappedNotified = false;
|
||||
|
||||
@@ -105,7 +111,15 @@ class _EclipseDefendScreenState extends State<EclipseDefendScreen>
|
||||
_current?.canShake(DateTime.now()) != true ||
|
||||
(_batch != null && !_sending))
|
||||
return;
|
||||
final qualify = _current?.qualifyShakes ?? 0;
|
||||
final before = _shown;
|
||||
setState(() => _pending += 1);
|
||||
// 화면을 보지 않고 흔들어도 알 수 있게 — 한 번 셀 때마다 짧게, 인정 기준을 넘는 순간 길게.
|
||||
if (qualify > 0 && before < qualify && _shown >= qualify) {
|
||||
HapticFeedback.heavyImpact();
|
||||
} else {
|
||||
HapticFeedback.selectionClick();
|
||||
}
|
||||
_scheduleFlush();
|
||||
}
|
||||
|
||||
@@ -256,7 +270,7 @@ class _EclipseDefendScreenState extends State<EclipseDefendScreen>
|
||||
title: context.l10n.eclipseSuccessTitle,
|
||||
success: true,
|
||||
extra: [
|
||||
if (_mine >= state.qualifyShakes) _Note(context.l10n.eclipseQualified),
|
||||
if (_shown >= state.qualifyShakes) _Note(context.l10n.eclipseQualified),
|
||||
if (_batch != null) _retryButton(),
|
||||
],
|
||||
);
|
||||
@@ -283,7 +297,7 @@ class _EclipseDefendScreenState extends State<EclipseDefendScreen>
|
||||
confirm: result != null,
|
||||
extra: [
|
||||
_Note(message),
|
||||
if (_mine >= state.qualifyShakes) _Note(context.l10n.eclipseQualified),
|
||||
if (_shown >= state.qualifyShakes) _Note(context.l10n.eclipseQualified),
|
||||
if (_batch != null) _retryButton(),
|
||||
],
|
||||
);
|
||||
@@ -424,16 +438,16 @@ class _EclipseDefendScreenState extends State<EclipseDefendScreen>
|
||||
_Meter(
|
||||
key: const ValueKey('eclipse-my-shakes'),
|
||||
label:
|
||||
'${context.l10n.eclipseMyShakes(formatPop(_mine), '${state.qualifyShakes}')}'
|
||||
'${context.l10n.eclipseMyShakes(formatPop(_shown), '${state.qualifyShakes}')}'
|
||||
'${_pending > 0
|
||||
? context.l10n.eclipsePendingSuffix('$_pending')
|
||||
: _sending
|
||||
? context.l10n.eclipseSendingSuffix
|
||||
: ''}'
|
||||
'${_mine >= state.qualifyShakes ? ' · ${context.l10n.eclipseQualified}' : ''}',
|
||||
'${_shown >= state.qualifyShakes ? ' · ${context.l10n.eclipseQualified}' : ''}',
|
||||
value: state.qualifyShakes <= 0
|
||||
? 0
|
||||
: (_mine / state.qualifyShakes).clamp(0.0, 1.0),
|
||||
: (_shown / state.qualifyShakes).clamp(0.0, 1.0),
|
||||
color: AppColors.cosmicAccent,
|
||||
),
|
||||
const SizedBox(height: AppSpace.s3),
|
||||
|
||||
Reference in New Issue
Block a user