앱 공통 계층 — 데이터 저장소 · 서버 시계 · 푸시 · 결제·광고 · 다국어 5종 · 행성 표현 · 공통 UI · 화면 자산
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import 'backend.dart';
|
||||
|
||||
/// 서버 시각 — 단말 시계와 서버 시계의 차이를 한 번 재어 앱 전체가 같이 쓴다.
|
||||
///
|
||||
/// 타임어택 창(`quests.activeFrom`~`activeTo`)은 서버 시각이다. 단말 시계로 세면 시계를
|
||||
/// 돌린 단말에서 마감이 늘어나 보인다. 판정은 서버가 다시 하므로 이것은 표시용이다.
|
||||
class ServerClock {
|
||||
ServerClock._();
|
||||
|
||||
/// 서버 − 단말. 재지 못했으면 0 이다(단말 시계 그대로).
|
||||
static Duration offset = Duration.zero;
|
||||
|
||||
static Future<void>? _synced;
|
||||
|
||||
static DateTime now() => DateTime.now().add(offset);
|
||||
|
||||
/// 세션당 한 번 `fnServerTime` 을 부른다. 실패하면 단말 시계로 두고 넘어간다.
|
||||
static Future<void> ensure(Backend backend) => _synced ??= _sync(backend);
|
||||
|
||||
static Future<void> _sync(Backend backend) async {
|
||||
try {
|
||||
final sent = DateTime.now();
|
||||
final reply = await backend.call('fnServerTime');
|
||||
final received = DateTime.now();
|
||||
final server = reply['now'];
|
||||
if (server is! num) return;
|
||||
// 왕복의 가운데를 서버가 답한 시각으로 본다.
|
||||
final middle = sent.add(received.difference(sent) ~/ 2);
|
||||
offset = DateTime.fromMillisecondsSinceEpoch(server.round()).difference(middle);
|
||||
} catch (_) {
|
||||
_synced = null; // 다음 기회에 다시 잰다.
|
||||
}
|
||||
}
|
||||
|
||||
/// 테스트가 회차마다 처음 상태로 돌린다.
|
||||
static void reset() {
|
||||
offset = Duration.zero;
|
||||
_synced = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user