mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Log contact data without revealing
This commit is contained in:
@@ -31,17 +31,22 @@ class MeshMapNode {
|
||||
}
|
||||
|
||||
class MeshMapNodesService {
|
||||
static const String _nodesEndpoint = 'https://api.meshcore.nz/api/v1/map/nodes';
|
||||
static const String _nodesEndpoint =
|
||||
'https://api.meshcore.nz/api/v1/map/nodes';
|
||||
static const Duration _cacheTtl = Duration(minutes: 2);
|
||||
static const Duration traceCacheTtl = Duration(minutes: 10);
|
||||
static List<MeshMapNode>? _cachedNodes;
|
||||
static DateTime? _cachedAt;
|
||||
|
||||
static Future<List<MeshMapNode>> fetchNodes({bool forceRefresh = false}) async {
|
||||
static Future<List<MeshMapNode>> fetchNodes({
|
||||
bool forceRefresh = false,
|
||||
Duration cacheTtl = _cacheTtl,
|
||||
}) async {
|
||||
final now = DateTime.now();
|
||||
if (!forceRefresh &&
|
||||
_cachedNodes != null &&
|
||||
_cachedAt != null &&
|
||||
now.difference(_cachedAt!) < _cacheTtl) {
|
||||
now.difference(_cachedAt!) < cacheTtl) {
|
||||
return _cachedNodes!;
|
||||
}
|
||||
|
||||
@@ -58,7 +63,9 @@ class MeshMapNodesService {
|
||||
final nodes = nodesRaw
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(MeshMapNode.fromJson)
|
||||
.where((n) => n.publicKey.isNotEmpty && n.latitude != 0 && n.longitude != 0)
|
||||
.where(
|
||||
(n) => n.publicKey.isNotEmpty && n.latitude != 0 && n.longitude != 0,
|
||||
)
|
||||
.toList();
|
||||
|
||||
_cachedNodes = nodes;
|
||||
|
||||
@@ -2,15 +2,21 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/message.dart';
|
||||
import '../models/message_contact_location.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
/// Service for persisting messages to local storage
|
||||
class MessageStorageService {
|
||||
static const String _messagesKey = 'stored_messages';
|
||||
static const String _messageContactLocationsKey =
|
||||
'stored_message_contact_locations';
|
||||
static const int _maxStoredMessages = 1000; // Store up to 1000 messages
|
||||
|
||||
/// Save messages to persistent storage
|
||||
Future<void> saveMessages(List<Message> messages) async {
|
||||
Future<void> saveMessages(
|
||||
List<Message> messages, {
|
||||
Map<String, MessageContactLocation> messageContactLocations = const {},
|
||||
}) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
@@ -24,6 +30,19 @@ class MessageStorageService {
|
||||
|
||||
final jsonString = jsonEncode(limitedList);
|
||||
await prefs.setString(_messagesKey, jsonString);
|
||||
final retainedMessageIds = limitedList
|
||||
.map((entry) => entry['id'] as String)
|
||||
.toSet();
|
||||
final locationJson = <String, dynamic>{};
|
||||
for (final entry in messageContactLocations.entries) {
|
||||
if (retainedMessageIds.contains(entry.key)) {
|
||||
locationJson[entry.key] = entry.value.toJson();
|
||||
}
|
||||
}
|
||||
await prefs.setString(
|
||||
_messageContactLocationsKey,
|
||||
jsonEncode(locationJson),
|
||||
);
|
||||
|
||||
debugPrint(
|
||||
'✅ [MessageStorage] Saved ${limitedList.length} messages to storage',
|
||||
@@ -33,6 +52,36 @@ class MessageStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, MessageContactLocation>> loadMessageContactLocations()
|
||||
async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final jsonString = prefs.getString(_messageContactLocationsKey);
|
||||
if (jsonString == null || jsonString.isEmpty) {
|
||||
return const {};
|
||||
}
|
||||
|
||||
final decoded = jsonDecode(jsonString);
|
||||
if (decoded is! Map<String, dynamic>) {
|
||||
return const {};
|
||||
}
|
||||
|
||||
final result = <String, MessageContactLocation>{};
|
||||
for (final entry in decoded.entries) {
|
||||
final value = entry.value;
|
||||
if (value is! Map<String, dynamic>) continue;
|
||||
final snapshot = MessageContactLocation.fromJson(value);
|
||||
if (snapshot != null) {
|
||||
result[entry.key] = snapshot;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
debugPrint('❌ [MessageStorage] Error loading contact locations: $e');
|
||||
return const {};
|
||||
}
|
||||
}
|
||||
|
||||
/// Load messages from persistent storage
|
||||
Future<List<Message>> loadMessages() async {
|
||||
try {
|
||||
@@ -66,6 +115,7 @@ class MessageStorageService {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(_messagesKey);
|
||||
await prefs.remove(_messageContactLocationsKey);
|
||||
debugPrint('✅ [MessageStorage] Cleared all stored messages');
|
||||
} catch (e) {
|
||||
debugPrint('❌ [MessageStorage] Error clearing messages: $e');
|
||||
|
||||
Reference in New Issue
Block a user