No se puede marcar “vista” sin revelar la palabra antes. Se puede volver a ver la palabra durante debate/votación/resultado. Notas online privadas por partida y jugador. Tests añadidos para notas scoped. Ajusté roomId en el payload de inicio para que las notas no se mezclen entre partidas.
97 lines
3.0 KiB
Dart
97 lines
3.0 KiB
Dart
import 'dart:convert';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Servicio para persistir las notas de los jugadores localmente.
|
|
class ServicioNotas {
|
|
static const _clavePrefix = 'notas_';
|
|
static const _clavePartidaPrefix = 'notas_partida_';
|
|
|
|
/// Guarda las notas de un jugador para una partida local/legacy.
|
|
static Future<void> guardarNotas(
|
|
String jugadorId,
|
|
Map<String, String> notas,
|
|
String notaLibre,
|
|
) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(
|
|
'$_clavePrefix$jugadorId',
|
|
json.encode(_serializar(notas, notaLibre)),
|
|
);
|
|
}
|
|
|
|
/// Carga las notas de un jugador en modo local/legacy.
|
|
static Future<Map<String, dynamic>> cargarNotas(String jugadorId) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return _decodificar(prefs.getString('$_clavePrefix$jugadorId'));
|
|
}
|
|
|
|
/// Guarda notas privadas scoped por partida y jugador autor.
|
|
///
|
|
/// Esto evita que una partida online contamine otra aunque se reutilicen
|
|
/// nombres o ids visibles de jugador.
|
|
static Future<void> guardarNotasPartida({
|
|
required String partidaId,
|
|
required String autorJugadorId,
|
|
required Map<String, String> notasPorJugador,
|
|
required String notaLibre,
|
|
}) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(
|
|
_claveNotasPartida(partidaId, autorJugadorId),
|
|
json.encode(_serializar(notasPorJugador, notaLibre)),
|
|
);
|
|
}
|
|
|
|
/// Carga notas privadas scoped por partida y jugador autor.
|
|
static Future<Map<String, dynamic>> cargarNotasPartida({
|
|
required String partidaId,
|
|
required String autorJugadorId,
|
|
}) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return _decodificar(
|
|
prefs.getString(_claveNotasPartida(partidaId, autorJugadorId)),
|
|
);
|
|
}
|
|
|
|
static String _claveNotasPartida(String partidaId, String autorJugadorId) {
|
|
return '$_clavePartidaPrefix${_normalizarClave(partidaId)}_${_normalizarClave(autorJugadorId)}';
|
|
}
|
|
|
|
static String _normalizarClave(String valor) {
|
|
return base64Url.encode(utf8.encode(valor));
|
|
}
|
|
|
|
static Map<String, Object> _serializar(
|
|
Map<String, String> notas,
|
|
String notaLibre,
|
|
) {
|
|
return {
|
|
'notas': notas,
|
|
'notaLibre': notaLibre,
|
|
};
|
|
}
|
|
|
|
static Map<String, dynamic> _decodificar(String? str) {
|
|
if (str == null) {
|
|
return {'notas': <String, String>{}, 'notaLibre': ''};
|
|
}
|
|
final datos = json.decode(str) as Map<String, dynamic>;
|
|
return {
|
|
'notas': Map<String, String>.from(datos['notas'] ?? {}),
|
|
'notaLibre': datos['notaLibre'] as String? ?? '',
|
|
};
|
|
}
|
|
|
|
/// Limpia todas las notas (al iniciar nueva partida local o reset manual).
|
|
static Future<void> limpiarNotas() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final claves = prefs
|
|
.getKeys()
|
|
.where((k) => k.startsWith(_clavePrefix))
|
|
.toList();
|
|
for (final clave in claves) {
|
|
await prefs.remove(clave);
|
|
}
|
|
}
|
|
}
|