refactor: all screens refactor

This commit is contained in:
2026-07-08 20:12:04 +03:30
parent 2496580e86
commit adc2d1fc47
16 changed files with 3546 additions and 3351 deletions
@@ -0,0 +1,76 @@
import 'dart:math' as math;
import '../../../../../core/service/app_sounds.dart';
import '../../../domain/entities/game_entities.dart';
/// ضربانِ قلبِ نوبتِ کاربر: در ثانیه‌های پایانیِ نوبتِ خودِ کاربر صدای ضربان پخش
/// می‌کند و با پایانِ نوبت بلافاصله قطع می‌شود. مستقل از چیدمانِ صحنه است.
///
/// زمان‌سنجِ نوبت دقیقاً هم‌زمان با «حلقه‌ی زمانِ نوبت» در HUD شروع می‌شود؛ آن حلقه
/// با تغییرِ امضای نوبت (نوبت|تعدادِ کارتِ زمین|فاز) ریست می‌شود و به انیمیشنِ بُر/
/// پخش کاری ندارد. اینجا هم شمارش به همان امضا بسته می‌شود و فقط «پخشِ صدا» در حینِ
/// انیمیشن/اینترو خاموش است تا صدا و تصویر یکی شوند.
class TurnHeartbeat {
double _elapsed = 0;
bool _beatPlayed = false;
double _accum = 0;
bool _wasMyTurn = false;
String _sig = '';
/// هر فریم صدا زده می‌شود. [busy] یعنی اینترو/بُر زدن/پخشِ کارت در جریان است
/// (شمارش ادامه دارد اما صدایی پخش نمی‌شود).
void update(
double dt,
GameState? s, {
required bool silent,
required bool busy,
}) {
final isMyTurn = s != null &&
((s.phase == 'playing' && s.turn == s.yourSeat) ||
(s.phase == 'choose_trump' && s.hakem == s.yourSeat));
if (!isMyTurn || silent) {
if (_wasMyTurn) {
AppSounds.stopHeartBeat(); // نوبت تمام شد ⇒ توقفِ فوریِ صدا
_wasMyTurn = false;
}
_sig = s == null ? '' : '${s.turn}|${s.trick.length}|${s.phase}';
return;
}
final sig = '${s.turn}|${s.trick.length}|${s.phase}';
if (!_wasMyTurn || sig != _sig) {
// شروعِ نوبتِ من (یا نوبتِ جدید) ⇒ شمارش از صفر، هم‌زمان با حلقه‌ی HUD.
_wasMyTurn = true;
_sig = sig;
_elapsed = 0;
_beatPlayed = false;
_accum = 0;
if (s.phase == 'playing' && !busy) AppSounds.turn();
}
_elapsed += dt;
if (busy) return;
final dur = (s.turnTimeoutMs > 0 ? s.turnTimeoutMs / 1000.0 : 30.0);
final remaining = dur - _elapsed;
final warn = math.min(7.0, dur * 0.4);
// در پنجره‌ی پایانیِ نوبت، ضربان با فاصله‌ی منظم تکرار می‌شود تا تا لحظه‌ی آخر
// شنیده شود (نه فقط یک ضربانِ زودهنگام که در سکوتِ پایانی گم می‌شود).
if (remaining > 0 && remaining <= warn) {
if (!_beatPlayed) {
_beatPlayed = true;
_accum = 0;
AppSounds.heartBeat();
} else {
_accum += dt;
if (_accum >= 0.95) {
_accum = 0;
AppSounds.heartBeat();
}
}
}
}
void stop() => AppSounds.stopHeartBeat();
}