mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-12 00:40:28 +00:00
Enable profiles switch UI
This commit is contained in:
@@ -18,6 +18,7 @@ import '../services/messaging_route_preferences.dart';
|
||||
import '../services/nearest_router_selector.dart';
|
||||
import '../services/packet_capture_storage_service.dart';
|
||||
import '../services/path_history_service.dart';
|
||||
import '../services/profiles_feature_service.dart';
|
||||
import '../services/route_hash_preferences.dart';
|
||||
import '../services/notification_service.dart';
|
||||
import '../models/contact.dart';
|
||||
@@ -253,6 +254,10 @@ class AppProvider with ChangeNotifier {
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
String _scopedKey(String baseKey) {
|
||||
return ProfileStorageScope.scopedKey(baseKey);
|
||||
}
|
||||
|
||||
void _startPacketCapturePersistence() {
|
||||
_packetCaptureFlushTimer?.cancel();
|
||||
_packetCaptureFlushTimer = Timer.periodic(const Duration(seconds: 2), (_) {
|
||||
@@ -516,7 +521,7 @@ class AppProvider with ChangeNotifier {
|
||||
Future<void> _loadMapEnabled() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isMapEnabled = prefs.getBool('map_enabled') ?? true;
|
||||
_isMapEnabled = prefs.getBool(_scopedKey('map_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading map enabled setting: $e');
|
||||
@@ -528,7 +533,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isMapEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('map_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('map_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving map enabled setting: $e');
|
||||
@@ -539,7 +544,8 @@ class AppProvider with ChangeNotifier {
|
||||
Future<void> _loadContactsEnabled() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isContactsEnabled = prefs.getBool('contacts_enabled') ?? true;
|
||||
_isContactsEnabled =
|
||||
prefs.getBool(_scopedKey('contacts_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading contacts enabled setting: $e');
|
||||
@@ -551,7 +557,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isContactsEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('contacts_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('contacts_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving contacts enabled setting: $e');
|
||||
@@ -562,7 +568,7 @@ class AppProvider with ChangeNotifier {
|
||||
Future<void> _loadSensorsEnabled() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isSensorsEnabled = prefs.getBool('sensors_enabled') ?? true;
|
||||
_isSensorsEnabled = prefs.getBool(_scopedKey('sensors_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading sensors enabled setting: $e');
|
||||
@@ -574,7 +580,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isSensorsEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('sensors_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('sensors_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving sensors enabled setting: $e');
|
||||
@@ -586,7 +592,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceSilenceTrimmingEnabled =
|
||||
prefs.getBool('voice_silence_trimming_enabled') ?? true;
|
||||
prefs.getBool(_scopedKey('voice_silence_trimming_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice silence trimming setting: $e');
|
||||
@@ -598,7 +604,10 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceSilenceTrimmingEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_silence_trimming_enabled', enabled);
|
||||
await prefs.setBool(
|
||||
_scopedKey('voice_silence_trimming_enabled'),
|
||||
enabled,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice silence trimming setting: $e');
|
||||
@@ -610,7 +619,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceBandPassFilterEnabled =
|
||||
prefs.getBool('voice_band_pass_filter_enabled') ?? true;
|
||||
prefs.getBool(_scopedKey('voice_band_pass_filter_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice band-pass filter setting: $e');
|
||||
@@ -622,7 +631,10 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceBandPassFilterEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_band_pass_filter_enabled', enabled);
|
||||
await prefs.setBool(
|
||||
_scopedKey('voice_band_pass_filter_enabled'),
|
||||
enabled,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice band-pass filter setting: $e');
|
||||
@@ -634,7 +646,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceCompressorEnabled =
|
||||
prefs.getBool('voice_compressor_enabled') ?? true;
|
||||
prefs.getBool(_scopedKey('voice_compressor_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice compressor setting: $e');
|
||||
@@ -646,7 +658,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceCompressorEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_compressor_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('voice_compressor_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice compressor setting: $e');
|
||||
@@ -657,7 +669,8 @@ class AppProvider with ChangeNotifier {
|
||||
Future<void> _loadVoiceLimiterEnabled() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceLimiterEnabled = prefs.getBool('voice_limiter_enabled') ?? true;
|
||||
_isVoiceLimiterEnabled =
|
||||
prefs.getBool(_scopedKey('voice_limiter_enabled')) ?? true;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice limiter setting: $e');
|
||||
@@ -669,7 +682,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceLimiterEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_limiter_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('voice_limiter_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice limiter setting: $e');
|
||||
@@ -680,7 +693,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceAutoGainEnabled =
|
||||
prefs.getBool('voice_auto_gain_enabled') ?? false;
|
||||
prefs.getBool(_scopedKey('voice_auto_gain_enabled')) ?? false;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice auto gain setting: $e');
|
||||
@@ -691,7 +704,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceAutoGainEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_auto_gain_enabled', enabled);
|
||||
await prefs.setBool(_scopedKey('voice_auto_gain_enabled'), enabled);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice auto gain setting: $e');
|
||||
@@ -702,7 +715,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceEchoCancellationEnabled =
|
||||
prefs.getBool('voice_echo_cancellation_enabled') ?? false;
|
||||
prefs.getBool(_scopedKey('voice_echo_cancellation_enabled')) ?? false;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice echo cancellation setting: $e');
|
||||
@@ -713,7 +726,10 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceEchoCancellationEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_echo_cancellation_enabled', enabled);
|
||||
await prefs.setBool(
|
||||
_scopedKey('voice_echo_cancellation_enabled'),
|
||||
enabled,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice echo cancellation setting: $e');
|
||||
@@ -724,7 +740,7 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_isVoiceNoiseSuppressionEnabled =
|
||||
prefs.getBool('voice_noise_suppression_enabled') ?? false;
|
||||
prefs.getBool(_scopedKey('voice_noise_suppression_enabled')) ?? false;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading voice noise suppression setting: $e');
|
||||
@@ -735,7 +751,10 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_isVoiceNoiseSuppressionEnabled = enabled;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('voice_noise_suppression_enabled', enabled);
|
||||
await prefs.setBool(
|
||||
_scopedKey('voice_noise_suppression_enabled'),
|
||||
enabled,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving voice noise suppression setting: $e');
|
||||
@@ -745,10 +764,11 @@ class AppProvider with ChangeNotifier {
|
||||
Future<void> _loadMessageFontScale() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_messageFontScale = (prefs.getDouble('message_font_scale') ?? 1.0).clamp(
|
||||
0.85,
|
||||
1.4,
|
||||
);
|
||||
_messageFontScale =
|
||||
(prefs.getDouble(_scopedKey('message_font_scale')) ?? 1.0).clamp(
|
||||
0.85,
|
||||
1.4,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error loading message font scale setting: $e');
|
||||
@@ -759,7 +779,10 @@ class AppProvider with ChangeNotifier {
|
||||
try {
|
||||
_messageFontScale = scale.clamp(0.85, 1.4);
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setDouble('message_font_scale', _messageFontScale);
|
||||
await prefs.setDouble(
|
||||
_scopedKey('message_font_scale'),
|
||||
_messageFontScale,
|
||||
);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error saving message font scale setting: $e');
|
||||
@@ -2600,6 +2623,24 @@ class AppProvider with ChangeNotifier {
|
||||
locationTrackingService.setFastLocationActiveUse(isActive);
|
||||
}
|
||||
|
||||
Future<void> reloadProfileScopedSettings() async {
|
||||
await Future.wait([
|
||||
_loadMapEnabled(),
|
||||
_loadContactsEnabled(),
|
||||
_loadSensorsEnabled(),
|
||||
_loadVoiceSilenceTrimmingEnabled(),
|
||||
_loadVoiceBandPassFilterEnabled(),
|
||||
_loadVoiceCompressorEnabled(),
|
||||
_loadVoiceLimiterEnabled(),
|
||||
_loadVoiceAutoGainEnabled(),
|
||||
_loadVoiceEchoCancellationEnabled(),
|
||||
_loadVoiceNoiseSuppressionEnabled(),
|
||||
_loadMessageFontScale(),
|
||||
_loadMessagingRouteSettings(),
|
||||
locationTrackingService.loadSettings(),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> _sendFastLocationUpdate(
|
||||
dynamic position, {
|
||||
required String reason,
|
||||
|
||||
@@ -1325,6 +1325,31 @@ class ConnectionProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setChannelSlot({
|
||||
required int channelIdx,
|
||||
required String channelName,
|
||||
required Uint8List secret,
|
||||
}) async {
|
||||
if (!_activeService.isConnected) {
|
||||
_error = 'Not connected to device';
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _activeService.setChannel(
|
||||
channelIdx: channelIdx,
|
||||
channelName: channelName,
|
||||
secret: secret,
|
||||
);
|
||||
await _activeService.getChannel(channelIdx);
|
||||
} catch (e) {
|
||||
_error = 'Failed to set channel: $e';
|
||||
notifyListeners();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate secret for hash channel using SHA256
|
||||
/// Same algorithm as Channel model for consistency
|
||||
/// Python equivalent: hashlib.sha256(channel_name.encode()).digest()[0:16]
|
||||
|
||||
@@ -134,6 +134,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
bool _persistRequested = false;
|
||||
bool _isPersistingPendingAdverts = false;
|
||||
bool _persistPendingAdvertsRequested = false;
|
||||
String? _storageNamespace;
|
||||
|
||||
// Add default public channel on initialization
|
||||
ContactsProvider() {
|
||||
@@ -141,19 +142,74 @@ class ContactsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
bool get isInitialized => _isInitialized;
|
||||
String? get storageNamespace => _storageNamespace;
|
||||
|
||||
/// Initialize and load persisted contacts at app startup
|
||||
/// This loads contacts without filtering, allowing offline viewing
|
||||
Future<void> initializeEarly() async {
|
||||
if (_isInitialized) return;
|
||||
|
||||
await _loadFromStorage();
|
||||
}
|
||||
|
||||
Future<void> reloadFromStorage({
|
||||
String? namespace,
|
||||
Uint8List? devicePublicKey,
|
||||
}) async {
|
||||
_storageNamespace = namespace;
|
||||
await _loadFromStorage(force: true, devicePublicKey: devicePublicKey);
|
||||
}
|
||||
|
||||
Future<void> persistNow() async {
|
||||
await _storageService.saveContacts(
|
||||
_contactsForStorage(),
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
await _storageService.saveContactGroups(
|
||||
_savedContactGroups,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
await _storageService.savePendingAdverts(
|
||||
_pendingAdverts.values.map(_pendingAdvertToJson).toList(),
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cloneCurrentStorageTo(String? namespace) async {
|
||||
await _storageService.saveContacts(
|
||||
_contactsForStorage(),
|
||||
namespace: namespace,
|
||||
);
|
||||
await _storageService.saveContactGroups(
|
||||
_savedContactGroups,
|
||||
namespace: namespace,
|
||||
);
|
||||
await _storageService.savePendingAdverts(
|
||||
_pendingAdverts.values.map(_pendingAdvertToJson).toList(),
|
||||
namespace: namespace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadFromStorage({
|
||||
bool force = false,
|
||||
Uint8List? devicePublicKey,
|
||||
}) async {
|
||||
if (_isInitialized && !force) return;
|
||||
|
||||
try {
|
||||
_resetInMemoryState();
|
||||
debugPrint(
|
||||
'📦 [ContactsProvider] Early loading persisted contacts (no filtering)...',
|
||||
);
|
||||
final storedContacts = await _storageService.loadContacts();
|
||||
final storedGroups = await _storageService.loadContactGroups();
|
||||
final storedPendingAdverts = await _storageService.loadPendingAdverts();
|
||||
final storedContacts = await _storageService.loadContacts(
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
final storedGroups = await _storageService.loadContactGroups(
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
final storedPendingAdverts = await _storageService.loadPendingAdverts(
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
|
||||
// Add stored contacts (excluding any with all-zeros public key)
|
||||
const publicChannelKey =
|
||||
@@ -170,7 +226,10 @@ class ContactsProvider with ChangeNotifier {
|
||||
_savedContactGroups
|
||||
..clear()
|
||||
..addAll(storedGroups);
|
||||
_restorePendingAdverts(storedPendingAdverts);
|
||||
_restorePendingAdverts(
|
||||
storedPendingAdverts,
|
||||
devicePublicKey: devicePublicKey,
|
||||
);
|
||||
debugPrint(
|
||||
'✅ [ContactsProvider] Early loaded ${storedContacts.length} persisted contacts and ${storedGroups.length} groups',
|
||||
);
|
||||
@@ -197,45 +256,9 @@ class ContactsProvider with ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
debugPrint('📦 [ContactsProvider] Loading persisted contacts...');
|
||||
final storedContacts = await _storageService.loadContacts(
|
||||
excludePublicKey: devicePublicKey,
|
||||
);
|
||||
final storedGroups = await _storageService.loadContactGroups();
|
||||
final storedPendingAdverts = await _storageService.loadPendingAdverts();
|
||||
|
||||
// Add stored contacts (excluding any with all-zeros public key)
|
||||
const publicChannelKey =
|
||||
'0000000000000000000000000000000000000000000000000000000000000000';
|
||||
for (final contact in storedContacts) {
|
||||
// Skip any contacts with all-zeros public key (shouldn't happen, but safety check)
|
||||
if (contact.publicKeyHex == publicChannelKey) {
|
||||
continue;
|
||||
}
|
||||
_contacts[contact.publicKeyHex] = contact;
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
_savedContactGroups
|
||||
..clear()
|
||||
..addAll(storedGroups);
|
||||
_restorePendingAdverts(
|
||||
storedPendingAdverts,
|
||||
devicePublicKey: devicePublicKey,
|
||||
);
|
||||
debugPrint(
|
||||
'✅ [ContactsProvider] Loaded ${storedContacts.length} persisted contacts and ${storedGroups.length} groups',
|
||||
);
|
||||
|
||||
// Ensure public channel exists after loading
|
||||
_ensurePublicChannelExists();
|
||||
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('❌ [ContactsProvider] Error initializing: $e');
|
||||
_isInitialized = true; // Mark as initialized even on error
|
||||
_ensurePublicChannelExists();
|
||||
await _loadFromStorage(force: true, devicePublicKey: devicePublicKey);
|
||||
if (devicePublicKey != null) {
|
||||
_removeSelfContact(devicePublicKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +310,10 @@ class ContactsProvider with ChangeNotifier {
|
||||
try {
|
||||
while (_persistRequested) {
|
||||
_persistRequested = false;
|
||||
await _storageService.saveContacts(_contactsForStorage());
|
||||
await _storageService.saveContacts(
|
||||
_contactsForStorage(),
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('❌ [ContactsProvider] Error persisting contacts: $e');
|
||||
@@ -305,6 +331,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
_persistPendingAdvertsRequested = false;
|
||||
await _storageService.savePendingAdverts(
|
||||
_pendingAdverts.values.map(_pendingAdvertToJson).toList(),
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -436,7 +463,10 @@ class ContactsProvider with ChangeNotifier {
|
||||
|
||||
Future<void> _persistSavedGroups() async {
|
||||
try {
|
||||
await _storageService.saveContactGroups(_savedContactGroups);
|
||||
await _storageService.saveContactGroups(
|
||||
_savedContactGroups,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('❌ [ContactsProvider] Error persisting contact groups: $e');
|
||||
}
|
||||
@@ -1442,11 +1472,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
|
||||
/// Get storage statistics
|
||||
Future<Map<String, dynamic>> getStorageStats() async {
|
||||
return await _storageService.getStorageStats();
|
||||
}
|
||||
|
||||
Future<void> persistNow() async {
|
||||
await _storageService.saveContacts(_contactsForStorage());
|
||||
return await _storageService.getStorageStats(namespace: _storageNamespace);
|
||||
}
|
||||
|
||||
Future<void> clearPendingAdverts() async {
|
||||
@@ -1454,7 +1480,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
return;
|
||||
}
|
||||
_pendingAdverts.clear();
|
||||
await _storageService.clearPendingAdverts();
|
||||
await _storageService.clearPendingAdverts(namespace: _storageNamespace);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -1517,6 +1543,12 @@ class ContactsProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
void _resetInMemoryState() {
|
||||
_contacts.clear();
|
||||
_savedContactGroups.clear();
|
||||
_pendingAdverts.clear();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _pendingAdvertToJson(PendingAdvert advert) {
|
||||
return {
|
||||
'publicKey': base64Encode(advert.publicKey),
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:latlong2/latlong.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../models/map_drawing.dart';
|
||||
import '../models/map_coordinate_space.dart';
|
||||
import '../services/profiles_feature_service.dart';
|
||||
import '../utils/drawing_message_parser.dart';
|
||||
|
||||
/// Drawing mode state
|
||||
@@ -85,6 +86,12 @@ class DrawingProvider with ChangeNotifier {
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
Future<void> reloadProfileScopedState() async {
|
||||
await _loadPreferences();
|
||||
await _loadDrawings();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setMapContext({
|
||||
required MapCoordinateSpace coordinateSpace,
|
||||
String? mapId,
|
||||
@@ -140,15 +147,19 @@ class DrawingProvider with ChangeNotifier {
|
||||
|
||||
Future<void> _loadPreferences() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_showReceivedDrawings = prefs.getBool(_showReceivedDrawingsKey) ?? true;
|
||||
_showSarMarkers = prefs.getBool(_showSarMarkersKey) ?? true;
|
||||
_showReceivedDrawings =
|
||||
prefs.getBool(_scopedKey(_showReceivedDrawingsKey)) ?? true;
|
||||
_showSarMarkers = prefs.getBool(_scopedKey(_showSarMarkersKey)) ?? true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _savePreferences() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(_showReceivedDrawingsKey, _showReceivedDrawings);
|
||||
await prefs.setBool(_showSarMarkersKey, _showSarMarkers);
|
||||
await prefs.setBool(
|
||||
_scopedKey(_showReceivedDrawingsKey),
|
||||
_showReceivedDrawings,
|
||||
);
|
||||
await prefs.setBool(_scopedKey(_showSarMarkersKey), _showSarMarkers);
|
||||
}
|
||||
|
||||
/// Start drawing a line
|
||||
@@ -365,7 +376,7 @@ class DrawingProvider with ChangeNotifier {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final jsonList = _drawings.map((d) => d.toJson()).toList();
|
||||
final jsonString = jsonEncode(jsonList);
|
||||
await prefs.setString(_storageKey, jsonString);
|
||||
await prefs.setString(_scopedKey(_storageKey), jsonString);
|
||||
} catch (e) {
|
||||
debugPrint('Error saving drawings: $e');
|
||||
}
|
||||
@@ -375,8 +386,11 @@ class DrawingProvider with ChangeNotifier {
|
||||
Future<void> _loadDrawings() async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final jsonString = prefs.getString(_storageKey);
|
||||
if (jsonString == null) return;
|
||||
final jsonString = prefs.getString(_scopedKey(_storageKey));
|
||||
if (jsonString == null || jsonString.isEmpty) {
|
||||
_drawings.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
final jsonList = jsonDecode(jsonString) as List<dynamic>;
|
||||
_drawings.clear();
|
||||
@@ -475,6 +489,24 @@ class DrawingProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> exportDrawingsJson() {
|
||||
return _drawings.map((drawing) => drawing.toJson()).toList();
|
||||
}
|
||||
|
||||
Future<void> replaceDrawingsFromJson(
|
||||
List<Map<String, dynamic>> jsonList,
|
||||
) async {
|
||||
_drawings
|
||||
..clear()
|
||||
..addAll(jsonList.map(MapDrawing.fromJson).whereType<MapDrawing>());
|
||||
await _saveDrawings();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String _scopedKey(String baseKey) {
|
||||
return ProfileStorageScope.scopedKey(baseKey);
|
||||
}
|
||||
|
||||
/// Get all unshared drawings (local drawings not yet sent)
|
||||
List<MapDrawing> getUnsharedDrawings() {
|
||||
return drawings.where((d) => !d.isShared && !d.isReceived).toList();
|
||||
|
||||
@@ -16,6 +16,7 @@ import '../models/location_trail.dart';
|
||||
import '../models/map_coordinate_space.dart';
|
||||
import '../models/map_drawing.dart';
|
||||
import '../models/sar_marker.dart';
|
||||
import '../services/profiles_feature_service.dart';
|
||||
import '../utils/custom_map_id.dart';
|
||||
|
||||
class MapProvider with ChangeNotifier {
|
||||
@@ -105,6 +106,10 @@ class MapProvider with ChangeNotifier {
|
||||
|
||||
LatLngBounds? get customMapBounds => _customMapConfig?.bounds;
|
||||
|
||||
Future<void> reloadProfileScopedState() async {
|
||||
await _loadInitialState();
|
||||
}
|
||||
|
||||
bool matchesActiveCustomMap(String? mapId) {
|
||||
return hasCustomMap &&
|
||||
normalizeCustomMapId(_customMapConfig!.mapId) ==
|
||||
@@ -522,27 +527,29 @@ class MapProvider with ChangeNotifier {
|
||||
Future<void> loadOverlayState() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_showCadastralOverlay =
|
||||
prefs.getBool('map_show_cadastral_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_cadastral_overlay')) ?? false;
|
||||
_showForestRoadsOverlay =
|
||||
prefs.getBool('map_show_forest_roads_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_forest_roads_overlay')) ?? false;
|
||||
_showHikingTrailsOverlay =
|
||||
prefs.getBool('map_show_hiking_trails_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_hiking_trails_overlay')) ?? false;
|
||||
_showMainRoadsOverlay =
|
||||
prefs.getBool('map_show_main_roads_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_main_roads_overlay')) ?? false;
|
||||
_showHouseNumbersOverlay =
|
||||
prefs.getBool('map_show_house_numbers_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_house_numbers_overlay')) ?? false;
|
||||
_showFireHazardZonesOverlay =
|
||||
prefs.getBool('map_show_fire_hazard_zones_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_fire_hazard_zones_overlay')) ??
|
||||
false;
|
||||
_showHistoricalFiresOverlay =
|
||||
prefs.getBool('map_show_historical_fires_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_historical_fires_overlay')) ?? false;
|
||||
_showFirebreaksOverlay =
|
||||
prefs.getBool('map_show_firebreaks_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_firebreaks_overlay')) ?? false;
|
||||
_showKrasFireZonesOverlay =
|
||||
prefs.getBool('map_show_kras_fire_zones_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_kras_fire_zones_overlay')) ?? false;
|
||||
_showPlaceNamesOverlay =
|
||||
prefs.getBool('map_show_place_names_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_place_names_overlay')) ?? false;
|
||||
_showMunicipalityBordersOverlay =
|
||||
prefs.getBool('map_show_municipality_borders_overlay') ?? false;
|
||||
prefs.getBool(_scopedKey('map_show_municipality_borders_overlay')) ??
|
||||
false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -557,36 +564,48 @@ class MapProvider with ChangeNotifier {
|
||||
|
||||
Future<void> _saveOverlayState() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('map_show_cadastral_overlay', _showCadastralOverlay);
|
||||
await prefs.setBool(
|
||||
'map_show_forest_roads_overlay',
|
||||
_scopedKey('map_show_cadastral_overlay'),
|
||||
_showCadastralOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
_scopedKey('map_show_forest_roads_overlay'),
|
||||
_showForestRoadsOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
'map_show_hiking_trails_overlay',
|
||||
_scopedKey('map_show_hiking_trails_overlay'),
|
||||
_showHikingTrailsOverlay,
|
||||
);
|
||||
await prefs.setBool('map_show_main_roads_overlay', _showMainRoadsOverlay);
|
||||
await prefs.setBool(
|
||||
'map_show_house_numbers_overlay',
|
||||
_scopedKey('map_show_main_roads_overlay'),
|
||||
_showMainRoadsOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
_scopedKey('map_show_house_numbers_overlay'),
|
||||
_showHouseNumbersOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
'map_show_fire_hazard_zones_overlay',
|
||||
_scopedKey('map_show_fire_hazard_zones_overlay'),
|
||||
_showFireHazardZonesOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
'map_show_historical_fires_overlay',
|
||||
_scopedKey('map_show_historical_fires_overlay'),
|
||||
_showHistoricalFiresOverlay,
|
||||
);
|
||||
await prefs.setBool('map_show_firebreaks_overlay', _showFirebreaksOverlay);
|
||||
await prefs.setBool(
|
||||
'map_show_kras_fire_zones_overlay',
|
||||
_scopedKey('map_show_firebreaks_overlay'),
|
||||
_showFirebreaksOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
_scopedKey('map_show_kras_fire_zones_overlay'),
|
||||
_showKrasFireZonesOverlay,
|
||||
);
|
||||
await prefs.setBool('map_show_place_names_overlay', _showPlaceNamesOverlay);
|
||||
await prefs.setBool(
|
||||
'map_show_municipality_borders_overlay',
|
||||
_scopedKey('map_show_place_names_overlay'),
|
||||
_showPlaceNamesOverlay,
|
||||
);
|
||||
await prefs.setBool(
|
||||
_scopedKey('map_show_municipality_borders_overlay'),
|
||||
_showMunicipalityBordersOverlay,
|
||||
);
|
||||
}
|
||||
@@ -600,13 +619,16 @@ class MapProvider with ChangeNotifier {
|
||||
Future<void> loadTrailSettings() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_showAllContactTrails =
|
||||
prefs.getBool('map_show_all_contact_trails') ?? true;
|
||||
prefs.getBool(_scopedKey('map_show_all_contact_trails')) ?? true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _saveTrailSettings() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('map_show_all_contact_trails', _showAllContactTrails);
|
||||
await prefs.setBool(
|
||||
_scopedKey('map_show_all_contact_trails'),
|
||||
_showAllContactTrails,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setHideRepeatersOnMap(bool hide) async {
|
||||
@@ -614,12 +636,13 @@ class MapProvider with ChangeNotifier {
|
||||
_hideRepeatersOnMap = hide;
|
||||
notifyListeners();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('map_hide_repeaters', _hideRepeatersOnMap);
|
||||
await prefs.setBool(_scopedKey('map_hide_repeaters'), _hideRepeatersOnMap);
|
||||
}
|
||||
|
||||
Future<void> loadRepeaterVisibilitySettings() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_hideRepeatersOnMap = prefs.getBool('map_hide_repeaters') ?? false;
|
||||
_hideRepeatersOnMap =
|
||||
prefs.getBool(_scopedKey('map_hide_repeaters')) ?? false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -661,7 +684,7 @@ class MapProvider with ChangeNotifier {
|
||||
|
||||
Future<void> _loadCustomMapState() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final configJson = prefs.getString(_customMapConfigKey);
|
||||
final configJson = prefs.getString(_scopedKey(_customMapConfigKey));
|
||||
if (configJson != null && configJson.isNotEmpty) {
|
||||
final decoded = jsonDecode(configJson);
|
||||
if (decoded is Map<String, dynamic>) {
|
||||
@@ -672,23 +695,26 @@ class MapProvider with ChangeNotifier {
|
||||
_customMapConfig = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_customMapConfig = null;
|
||||
}
|
||||
_isUsingCustomMap =
|
||||
(prefs.getBool(_customMapModeKey) ?? false) && _customMapConfig != null;
|
||||
(prefs.getBool(_scopedKey(_customMapModeKey)) ?? false) &&
|
||||
_customMapConfig != null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _saveCustomMapState() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
if (_customMapConfig == null) {
|
||||
await prefs.remove(_customMapConfigKey);
|
||||
await prefs.remove(_scopedKey(_customMapConfigKey));
|
||||
} else {
|
||||
await prefs.setString(
|
||||
_customMapConfigKey,
|
||||
_scopedKey(_customMapConfigKey),
|
||||
jsonEncode(_customMapConfig!.toJson()),
|
||||
);
|
||||
}
|
||||
await prefs.setBool(_customMapModeKey, _isUsingCustomMap);
|
||||
await prefs.setBool(_scopedKey(_customMapModeKey), _isUsingCustomMap);
|
||||
}
|
||||
|
||||
Future<(int, int)> _decodeImageSize(Uint8List bytes) async {
|
||||
@@ -711,4 +737,67 @@ class MapProvider with ChangeNotifier {
|
||||
await file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> exportWorkspaceJson() {
|
||||
return {
|
||||
'currentTrail': _currentTrail?.toJson(),
|
||||
'trailHistory': _trailHistory.map((trail) => trail.toJson()).toList(),
|
||||
'importedTrail': _importedTrail?.toJson(),
|
||||
'isTrailVisible': _isTrailVisible,
|
||||
'showCadastralOverlay': _showCadastralOverlay,
|
||||
'showForestRoadsOverlay': _showForestRoadsOverlay,
|
||||
'showHikingTrailsOverlay': _showHikingTrailsOverlay,
|
||||
'showMainRoadsOverlay': _showMainRoadsOverlay,
|
||||
'showHouseNumbersOverlay': _showHouseNumbersOverlay,
|
||||
'showFireHazardZonesOverlay': _showFireHazardZonesOverlay,
|
||||
'showHistoricalFiresOverlay': _showHistoricalFiresOverlay,
|
||||
'showFirebreaksOverlay': _showFirebreaksOverlay,
|
||||
'showKrasFireZonesOverlay': _showKrasFireZonesOverlay,
|
||||
'showPlaceNamesOverlay': _showPlaceNamesOverlay,
|
||||
'showMunicipalityBordersOverlay': _showMunicipalityBordersOverlay,
|
||||
'showAllContactTrails': _showAllContactTrails,
|
||||
'hideRepeatersOnMap': _hideRepeatersOnMap,
|
||||
};
|
||||
}
|
||||
|
||||
void applyWorkspaceJson(Map<String, dynamic> json) {
|
||||
_currentTrail = json['currentTrail'] is Map<String, dynamic>
|
||||
? LocationTrail.fromJson(json['currentTrail'] as Map<String, dynamic>)
|
||||
: null;
|
||||
_trailHistory
|
||||
..clear()
|
||||
..addAll(
|
||||
(json['trailHistory'] as List<dynamic>? ?? const [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(LocationTrail.fromJson),
|
||||
);
|
||||
_importedTrail = json['importedTrail'] is Map<String, dynamic>
|
||||
? LocationTrail.fromJson(json['importedTrail'] as Map<String, dynamic>)
|
||||
: null;
|
||||
_isTrailVisible = json['isTrailVisible'] as bool? ?? true;
|
||||
_showCadastralOverlay = json['showCadastralOverlay'] as bool? ?? false;
|
||||
_showForestRoadsOverlay = json['showForestRoadsOverlay'] as bool? ?? false;
|
||||
_showHikingTrailsOverlay =
|
||||
json['showHikingTrailsOverlay'] as bool? ?? false;
|
||||
_showMainRoadsOverlay = json['showMainRoadsOverlay'] as bool? ?? false;
|
||||
_showHouseNumbersOverlay =
|
||||
json['showHouseNumbersOverlay'] as bool? ?? false;
|
||||
_showFireHazardZonesOverlay =
|
||||
json['showFireHazardZonesOverlay'] as bool? ?? false;
|
||||
_showHistoricalFiresOverlay =
|
||||
json['showHistoricalFiresOverlay'] as bool? ?? false;
|
||||
_showFirebreaksOverlay = json['showFirebreaksOverlay'] as bool? ?? false;
|
||||
_showKrasFireZonesOverlay =
|
||||
json['showKrasFireZonesOverlay'] as bool? ?? false;
|
||||
_showPlaceNamesOverlay = json['showPlaceNamesOverlay'] as bool? ?? false;
|
||||
_showMunicipalityBordersOverlay =
|
||||
json['showMunicipalityBordersOverlay'] as bool? ?? false;
|
||||
_showAllContactTrails = json['showAllContactTrails'] as bool? ?? true;
|
||||
_hideRepeatersOnMap = json['hideRepeatersOnMap'] as bool? ?? false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String _scopedKey(String baseKey) {
|
||||
return ProfileStorageScope.scopedKey(baseKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
final Map<String, MessageReceptionDetails> _messageReceptionDetails = {};
|
||||
final Map<String, MessageTransferDetails> _messageTransferDetails = {};
|
||||
final Map<String, MessageRouteMetadata> _messageRouteMetadata = {};
|
||||
String? _storageNamespace;
|
||||
|
||||
// Track pending sent messages by expected ACK/TAG
|
||||
final Map<int, Message> _pendingSentMessages = {};
|
||||
@@ -149,6 +150,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
sarMarkers.where((m) => m.type == SarMarkerType.object).toList();
|
||||
|
||||
bool get isInitialized => _isInitialized;
|
||||
String? get storageNamespace => _storageNamespace;
|
||||
|
||||
String? get targetMessageId => _targetMessageId;
|
||||
|
||||
@@ -311,19 +313,64 @@ class MessagesProvider with ChangeNotifier {
|
||||
Future<void> initialize() async {
|
||||
if (_isInitialized) return;
|
||||
|
||||
await _loadFromStorage();
|
||||
}
|
||||
|
||||
Future<void> reloadFromStorage({String? namespace}) async {
|
||||
_storageNamespace = namespace;
|
||||
await _loadFromStorage(force: true);
|
||||
}
|
||||
|
||||
Future<void> persistNow() async {
|
||||
await _storageService.saveMessages(
|
||||
_messages,
|
||||
messageContactLocations: _messageContactLocations,
|
||||
messageReceptionDetails: _messageReceptionDetails,
|
||||
messageTransferDetails: _messageTransferDetails,
|
||||
messageRouteMetadata: _messageRouteMetadata,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
await _storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cloneCurrentStorageTo(String? namespace) async {
|
||||
await _storageService.saveMessages(
|
||||
_messages,
|
||||
messageContactLocations: _messageContactLocations,
|
||||
messageReceptionDetails: _messageReceptionDetails,
|
||||
messageTransferDetails: _messageTransferDetails,
|
||||
messageRouteMetadata: _messageRouteMetadata,
|
||||
namespace: namespace,
|
||||
);
|
||||
await _storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: namespace,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadFromStorage({bool force = false}) async {
|
||||
if (_isInitialized && !force) return;
|
||||
|
||||
try {
|
||||
_cancelAllTimers();
|
||||
_resetInMemoryState();
|
||||
debugPrint('📦 [MessagesProvider] Loading persisted messages...');
|
||||
final storedMessages = await _storageService.loadMessages();
|
||||
final storedMessages = await _storageService.loadMessages(
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
final storedContactLocations = await _storageService
|
||||
.loadMessageContactLocations();
|
||||
.loadMessageContactLocations(namespace: _storageNamespace);
|
||||
final storedReceptionDetails = await _storageService
|
||||
.loadMessageReceptionDetails();
|
||||
.loadMessageReceptionDetails(namespace: _storageNamespace);
|
||||
final storedTransferDetails = await _storageService
|
||||
.loadMessageTransferDetails();
|
||||
.loadMessageTransferDetails(namespace: _storageNamespace);
|
||||
final storedRouteMetadata = await _storageService
|
||||
.loadMessageRouteMetadata();
|
||||
.loadMessageRouteMetadata(namespace: _storageNamespace);
|
||||
final storedRemovedSarMarkerIds = await _storageService
|
||||
.loadRemovedSarMarkerIds();
|
||||
.loadRemovedSarMarkerIds(namespace: _storageNamespace);
|
||||
_messageContactLocations
|
||||
..clear()
|
||||
..addAll(storedContactLocations);
|
||||
@@ -1051,6 +1098,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
messageReceptionDetails: _messageReceptionDetails,
|
||||
messageTransferDetails: _messageTransferDetails,
|
||||
messageRouteMetadata: _messageRouteMetadata,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -1199,7 +1247,10 @@ class MessagesProvider with ChangeNotifier {
|
||||
Future<void> removeSarMarker(String id) async {
|
||||
_sarMarkers.remove(id);
|
||||
_removedSarMarkerIds.add(id);
|
||||
await _storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds);
|
||||
await _storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -1324,7 +1375,12 @@ class MessagesProvider with ChangeNotifier {
|
||||
debugPrint('🗑️ [MessagesProvider] Message $messageId deleted');
|
||||
|
||||
_persistMessages();
|
||||
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
||||
unawaited(
|
||||
_storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
),
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -1348,23 +1404,15 @@ class MessagesProvider with ChangeNotifier {
|
||||
/// Clear all messages
|
||||
void clearMessages() {
|
||||
_cancelAllTimers();
|
||||
_messages.clear();
|
||||
_sarMarkers.clear();
|
||||
_removedSarMarkerIds.clear();
|
||||
_messageContactLocations.clear();
|
||||
_messageReceptionDetails.clear();
|
||||
_messageTransferDetails.clear();
|
||||
_messageRouteMetadata.clear();
|
||||
_pendingSentMessages.clear();
|
||||
_messageContactMap.clear();
|
||||
_groupedMessageMapping.clear();
|
||||
_ackTagToRecipients.clear();
|
||||
_messageAckHistory.clear();
|
||||
_ackHistoryLookup.clear();
|
||||
_completedAckHistory.clear();
|
||||
_resetInMemoryState();
|
||||
_retryManager.clearAll();
|
||||
_persistMessages();
|
||||
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
||||
unawaited(
|
||||
_storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
),
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -1372,13 +1420,29 @@ class MessagesProvider with ChangeNotifier {
|
||||
Future<void> clearSarMarkers() async {
|
||||
_removedSarMarkerIds.addAll(_sarMarkers.keys);
|
||||
_sarMarkers.clear();
|
||||
await _storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds);
|
||||
await _storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Clear all data
|
||||
void clearAll() {
|
||||
_cancelAllTimers();
|
||||
_resetInMemoryState();
|
||||
_retryManager.clearAll();
|
||||
_persistMessages();
|
||||
unawaited(
|
||||
_storageService.saveRemovedSarMarkerIds(
|
||||
_removedSarMarkerIds,
|
||||
namespace: _storageNamespace,
|
||||
),
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _resetInMemoryState() {
|
||||
_messages.clear();
|
||||
_sarMarkers.clear();
|
||||
_removedSarMarkerIds.clear();
|
||||
@@ -1393,10 +1457,6 @@ class MessagesProvider with ChangeNotifier {
|
||||
_messageAckHistory.clear();
|
||||
_ackHistoryLookup.clear();
|
||||
_completedAckHistory.clear();
|
||||
_retryManager.clearAll();
|
||||
_persistMessages();
|
||||
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
int transferCountForSession({
|
||||
|
||||
Reference in New Issue
Block a user