GIVE 연타에 행성이 흔들리고 우하단에 [+1] · 10회 이상이면 [+10]과 자전 1.5배, 전송 중 연타는 다음 묶음으로 쌓임
This commit is contained in:
@@ -20,6 +20,16 @@ class ZapController extends ChangeNotifier {
|
||||
({String fandomId, int count, String key})? _batch;
|
||||
bool get needsRetry => _batch != null && !sending;
|
||||
|
||||
/// 아직 확정되지 않은 연타 — 보내는 중인 묶음 + 다음 묶음. 표시 잔액은 이만큼 미리 뺀다.
|
||||
int get queued => pending + (sending ? _batch?.count ?? 0 : 0);
|
||||
|
||||
/// 이어서 누른 횟수 — Figma `2024:20758` 「0.5초간 [+1] 표시(연속 가능)」: [+1] 이 떠 있는
|
||||
/// [streakWindow] 안에 다시 누르면 이어지고, 넘기면 1 부터 다시 센다.
|
||||
int streak = 0;
|
||||
Timer? _streakTimer;
|
||||
String? _pendingFandom;
|
||||
static const streakWindow = Duration(milliseconds: 500);
|
||||
|
||||
/// 지금 결과가 ZAP 이 아니라 퀘스트 보상 확정의 행성 반응인가([react]).
|
||||
bool questReaction = false;
|
||||
|
||||
@@ -41,14 +51,25 @@ class ZapController extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// 보내는 중에도 받는다 — 다음 묶음으로 쌓였다가 앞 묶음이 확정되면 보낸다. 실패한 묶음이
|
||||
/// 있으면([needsRetry]) 같은 키로 다시 확인하기 전까지 받지 않는다.
|
||||
void tap(String fandomId) {
|
||||
if (_disposed || sending || _batch != null || fandomId.isEmpty) return;
|
||||
if (_disposed || needsRetry || fandomId.isEmpty) return;
|
||||
// 쌓인 연타는 한 행성 몫이다. 다른 행성 탭은 쌓인 묶음이 나간 뒤에 받는다.
|
||||
if (pending > 0 && fandomId != _pendingFandom) return;
|
||||
_pendingFandom = fandomId;
|
||||
questReaction = false;
|
||||
if (pending == 0) fxHaptic(FxIntensity.small);
|
||||
streak = _streakTimer?.isActive == true ? streak + 1 : 1;
|
||||
_streakTimer?.cancel();
|
||||
_streakTimer = Timer(streakWindow, () {});
|
||||
pending++;
|
||||
touchSerial++;
|
||||
notifyListeners();
|
||||
_burst ??= Timer(const Duration(milliseconds: 450), () => _flush(fandomId));
|
||||
_burst ??= Timer(const Duration(milliseconds: 450), () {
|
||||
_burst = null;
|
||||
_flush(_pendingFandom!);
|
||||
});
|
||||
}
|
||||
|
||||
void retry() {
|
||||
@@ -56,6 +77,7 @@ class ZapController extends ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<void> _flush(String fandomId) async {
|
||||
// 보내는 중이면 확정 뒤(finally)에 이어 보낸다.
|
||||
if (_disposed || sending) return;
|
||||
final batch =
|
||||
_batch ??
|
||||
@@ -84,6 +106,10 @@ class ZapController extends ChangeNotifier {
|
||||
_batch = null;
|
||||
} catch (error) {
|
||||
if (_disposed) return;
|
||||
// 실패하면 뒤에 쌓인 연타는 보내지 않는다 — 실패 묶음을 같은 키로 다시 확인하는 것이 먼저다.
|
||||
pending = 0;
|
||||
_burst?.cancel();
|
||||
_burst = null;
|
||||
onFailure(switch (error) {
|
||||
BackendException(code: 'E-POP-01') => appL10n.zapFailNoPop,
|
||||
BackendException(code: 'E-POP-02') => appL10n.zapFailLedger,
|
||||
@@ -94,6 +120,7 @@ class ZapController extends ChangeNotifier {
|
||||
if (!_disposed) {
|
||||
sending = false;
|
||||
notifyListeners();
|
||||
if (_batch == null && pending > 0 && _burst == null) _flush(_pendingFandom!);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,6 +129,7 @@ class ZapController extends ChangeNotifier {
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
_burst?.cancel();
|
||||
_streakTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user