tetraq/lib/services/storage_service.dart

203 lines
7.3 KiB
Dart
Raw Normal View History

2026-03-01 20:59:06 +01:00
// ===========================================================================
// FILE: lib/services/storage_service.dart
// ===========================================================================
2026-02-27 23:35:54 +01:00
import 'dart:convert';
2026-03-15 15:00:01 +01:00
import 'dart:io' show Platform, HttpClient;
2026-02-27 23:35:54 +01:00
import 'package:shared_preferences/shared_preferences.dart';
2026-03-01 20:59:06 +01:00
import 'package:cloud_firestore/cloud_firestore.dart';
2026-02-27 23:35:54 +01:00
import '../core/app_colors.dart';
2026-03-04 18:00:01 +01:00
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
2026-03-15 15:00:01 +01:00
import 'package:package_info_plus/package_info_plus.dart'; // <-- NUOVO IMPORT
2026-02-27 23:35:54 +01:00
class StorageService {
static final StorageService instance = StorageService._internal();
StorageService._internal();
late SharedPreferences _prefs;
2026-03-15 15:00:01 +01:00
int _sessionStart = 0;
2026-02-27 23:35:54 +01:00
Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
2026-03-13 22:00:00 +01:00
_checkDailyQuests();
2026-03-15 15:00:01 +01:00
_fetchLocationData();
_sessionStart = DateTime.now().millisecondsSinceEpoch;
2026-02-27 23:35:54 +01:00
}
2026-03-15 15:00:01 +01:00
// --- RECUPERO IP E CITTÀ IN BACKGROUND ---
Future<void> _fetchLocationData() async {
if (kIsWeb) return;
try {
final request = await HttpClient().getUrl(Uri.parse('http://ip-api.com/json/'));
final response = await request.close();
final responseBody = await response.transform(utf8.decoder).join();
final data = jsonDecode(responseBody);
await _prefs.setString('last_ip', data['query'] ?? 'Sconosciuto');
await _prefs.setString('last_city', data['city'] ?? 'Sconosciuta');
} catch (e) {
debugPrint("Errore recupero IP: $e");
}
}
String get lastIp => _prefs.getString('last_ip') ?? 'Sconosciuto';
String get lastCity => _prefs.getString('last_city') ?? 'Sconosciuta';
// ------------------------------------------------
2026-03-13 22:00:00 +01:00
int get savedThemeIndex => _prefs.getInt('theme') ?? AppThemeType.doodle.index;
2026-02-27 23:35:54 +01:00
Future<void> saveTheme(AppThemeType theme) async => await _prefs.setInt('theme', theme.index);
int get savedRadius => _prefs.getInt('radius') ?? 2;
Future<void> saveRadius(int radius) async => await _prefs.setInt('radius', radius);
bool get isMuted => _prefs.getBool('isMuted') ?? false;
Future<void> saveMuted(bool muted) async => await _prefs.setBool('isMuted', muted);
2026-03-01 20:59:06 +01:00
int get totalXP => _prefs.getInt('totalXP') ?? 0;
Future<void> addXP(int xp) async {
await _prefs.setInt('totalXP', totalXP + xp);
syncLeaderboard();
}
int get playerLevel => (totalXP / 100).floor() + 1;
2026-02-27 23:35:54 +01:00
int get wins => _prefs.getInt('wins') ?? 0;
2026-03-01 20:59:06 +01:00
Future<void> addWin() async {
await _prefs.setInt('wins', wins + 1);
syncLeaderboard();
}
2026-02-27 23:35:54 +01:00
int get losses => _prefs.getInt('losses') ?? 0;
Future<void> addLoss() async => await _prefs.setInt('losses', losses + 1);
int get cpuLevel => _prefs.getInt('cpuLevel') ?? 1;
Future<void> saveCpuLevel(int level) async => await _prefs.setInt('cpuLevel', level);
String get playerName => _prefs.getString('playerName') ?? '';
2026-03-01 20:59:06 +01:00
Future<void> savePlayerName(String name) async {
await _prefs.setString('playerName', name);
2026-03-13 22:00:00 +01:00
syncLeaderboard();
2026-03-01 20:59:06 +01:00
}
Future<void> syncLeaderboard() async {
if (playerName.isNotEmpty) {
try {
2026-03-04 18:00:01 +01:00
final user = FirebaseAuth.instance.currentUser;
if (user != null) {
2026-03-15 15:00:01 +01:00
// IDENTIFICA IL SISTEMA OPERATIVO E LA VERSIONE APP
String currentPlatform = "Sconosciuta";
String appVersion = "N/D";
if (!kIsWeb) {
if (Platform.isAndroid) currentPlatform = "Android";
else if (Platform.isIOS) currentPlatform = "iOS";
else if (Platform.isMacOS) currentPlatform = "macOS";
else if (Platform.isWindows) currentPlatform = "Windows";
try {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
appVersion = "${packageInfo.version}+${packageInfo.buildNumber}";
} catch(e) {
debugPrint("Errore lettura versione: $e");
}
}
// AGGIORNA IL TEMPO DI UTILIZZO
if (_sessionStart != 0) {
int now = DateTime.now().millisecondsSinceEpoch;
int sessionSeconds = (now - _sessionStart) ~/ 1000;
await _prefs.setInt('totalPlaytime', (_prefs.getInt('totalPlaytime') ?? 0) + sessionSeconds);
_sessionStart = now; // resetta per la prossima misurazione
}
int totalPlaytime = _prefs.getInt('totalPlaytime') ?? 0;
2026-03-04 18:00:01 +01:00
await FirebaseFirestore.instance.collection('leaderboard').doc(user.uid).set({
2026-03-13 22:00:00 +01:00
'name': playerName,
2026-03-04 18:00:01 +01:00
'xp': totalXP,
'level': playerLevel,
'wins': wins,
'lastActive': FieldValue.serverTimestamp(),
2026-03-15 15:00:01 +01:00
'platform': currentPlatform,
'ip': lastIp,
'city': lastCity,
'playtime': totalPlaytime,
'appVersion': appVersion, // <-- NUOVO: Salva la versione
2026-03-04 18:00:01 +01:00
}, SetOptions(merge: true));
}
2026-03-01 20:59:06 +01:00
} catch(e) {
2026-03-04 18:00:01 +01:00
debugPrint("Errore sinc. classifica: $e");
2026-03-01 20:59:06 +01:00
}
}
}
2026-03-15 15:00:01 +01:00
// --- GESTIONE PREFERITI (RUBRICA LOCALE) ---
2026-03-15 13:00:00 +01:00
List<Map<String, String>> get favorites {
List<String> favs = _prefs.getStringList('favorites') ?? [];
return favs.map((e) => Map<String, String>.from(jsonDecode(e))).toList();
}
Future<void> toggleFavorite(String uid, String name) async {
var favs = favorites;
if (favs.any((f) => f['uid'] == uid)) {
2026-03-15 15:00:01 +01:00
favs.removeWhere((f) => f['uid'] == uid);
2026-03-15 13:00:00 +01:00
} else {
2026-03-15 15:00:01 +01:00
favs.add({'uid': uid, 'name': name});
2026-03-15 13:00:00 +01:00
}
await _prefs.setStringList('favorites', favs.map((e) => jsonEncode(e)).toList());
}
bool isFavorite(String uid) {
return favorites.any((f) => f['uid'] == uid);
}
2026-03-01 20:59:06 +01:00
void _checkDailyQuests() {
String today = DateTime.now().toIso8601String().substring(0, 10);
String lastDate = _prefs.getString('quest_date') ?? '';
if (today != lastDate) {
_prefs.setString('quest_date', today);
_prefs.setInt('q1_type', 0);
_prefs.setInt('q1_prog', 0);
_prefs.setInt('q1_target', 3);
_prefs.setInt('q2_type', 1);
_prefs.setInt('q2_prog', 0);
_prefs.setInt('q2_target', 2);
_prefs.setInt('q3_type', 2);
_prefs.setInt('q3_prog', 0);
_prefs.setInt('q3_target', 2);
}
}
Future<void> updateQuestProgress(int type, int amount) async {
for(int i=1; i<=3; i++) {
if (_prefs.getInt('q${i}_type') == type) {
int prog = _prefs.getInt('q${i}_prog') ?? 0;
int target = _prefs.getInt('q${i}_target') ?? 1;
if (prog < target) {
_prefs.setInt('q${i}_prog', prog + amount);
}
}
}
}
2026-02-27 23:35:54 +01:00
List<Map<String, dynamic>> get matchHistory {
List<String> history = _prefs.getStringList('matchHistory') ?? [];
return history.map((e) => jsonDecode(e) as Map<String, dynamic>).toList();
}
Future<void> saveMatchToHistory({required String myName, required String opponent, required int myScore, required int oppScore, required bool isOnline}) async {
List<String> history = _prefs.getStringList('matchHistory') ?? [];
Map<String, dynamic> match = {
'date': DateTime.now().toIso8601String(),
2026-03-01 20:59:06 +01:00
'myName': myName, 'opponent': opponent, 'myScore': myScore, 'oppScore': oppScore, 'isOnline': isOnline,
2026-02-27 23:35:54 +01:00
};
history.insert(0, jsonEncode(match));
2026-03-01 20:59:06 +01:00
if (history.length > 50) history = history.sublist(0, 50);
2026-02-27 23:35:54 +01:00
await _prefs.setStringList('matchHistory', history);
}
}