aves_mio22/lib/remote/remote_state_store.dart
2026-04-18 20:05:02 +02:00

124 lines
3.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:uuid/uuid.dart';
class RemoteStateStore {
static const _storage = FlutterSecureStorage(
aOptions: AndroidOptions(
encryptedSharedPreferences: true,
resetOnError: true,
),
);
static const _kWsSessionId = 'ws_session_id';
static const _kProcessedRing = 'ws_processed_events_ring';
static const _kLastSyncIso = 'remote_last_sync_iso';
// ✅ NEW: last seen timestamp (ms) come sync.js: ws_last_seen
static const _kWsLastSeenMs = 'ws_last_seen_ms';
// ---------------------------
// WS session id
// ---------------------------
Future<String> getOrCreateSessionId() async {
var id = await _storage.read(key: _kWsSessionId);
if (id == null || id.isEmpty) {
id = const Uuid().v4();
await _storage.write(key: _kWsSessionId, value: id);
}
return id;
}
Future<void> clearSessionId() => _storage.delete(key: _kWsSessionId);
/// ✅ Alias “sync.js-like”: reset session id (usato quando sessione dormiente > 2 min)
Future<void> resetSessionId() => clearSessionId();
// ---------------------------
// Last sync ISO
// ---------------------------
Future<String?> getLastSyncIso() => _storage.read(key: _kLastSyncIso);
Future<void> setLastSyncIso(String iso) =>
_storage.write(key: _kLastSyncIso, value: iso);
// ---------------------------
// WS last seen (ms)
// ---------------------------
/// Ritorna lultimo timestamp (ms) in cui abbiamo ricevuto un messaggio WS.
Future<int> getWsLastSeenMs() async {
final raw = await _storage.read(key: _kWsLastSeenMs);
if (raw == null || raw.isEmpty) return 0;
final v = int.tryParse(raw);
return v ?? 0;
}
/// Salva lultimo timestamp (ms) in cui abbiamo ricevuto un messaggio WS.
Future<void> setWsLastSeenMs(int ms) async {
await _storage.write(key: _kWsLastSeenMs, value: ms.toString());
}
Future<void> clearWsLastSeenMs() => _storage.delete(key: _kWsLastSeenMs);
// ---------------------------
// Processed events ring
// ---------------------------
Future<List<String>> loadProcessedRing({int maxSize = 2000}) async {
final raw = await _storage.read(key: _kProcessedRing);
if (raw == null || raw.isEmpty) return <String>[];
try {
final v = jsonDecode(raw);
if (v is List) {
final list = v.whereType<String>().toList();
return list.length > maxSize ? list.sublist(list.length - maxSize) : list;
}
} catch (_) {}
return <String>[];
}
Future<void> saveProcessedRing(List<String> ring, {int maxSize = 2000}) async {
final trimmed = ring.length > maxSize ? ring.sublist(ring.length - maxSize) : ring;
await _storage.write(key: _kProcessedRing, value: jsonEncode(trimmed));
}
}
class EventRingDeduper {
EventRingDeduper(this.store, {this.maxSize = 2000});
final RemoteStateStore store;
final int maxSize;
final List<String> _ring = [];
final Set<String> _set = {};
Future<void> init() async {
final saved = await store.loadProcessedRing(maxSize: maxSize);
_ring
..clear()
..addAll(saved);
_set
..clear()
..addAll(saved);
}
bool has(String? id) => id != null && id.isNotEmpty && _set.contains(id);
Future<void> mark(String? id) async {
if (id == null || id.isEmpty) return;
if (_set.contains(id)) return;
_ring.add(id);
_set.add(id);
while (_ring.length > maxSize) {
final old = _ring.removeAt(0);
_set.remove(old);
}
await store.saveProcessedRing(_ring, maxSize: maxSize);
}
}