|
|
|
|
@ -16,6 +16,7 @@ import '../models/message.dart';
|
|
|
|
|
import '../models/path_selection.dart';
|
|
|
|
|
import '../models/translation_support.dart';
|
|
|
|
|
import '../helpers/reaction_helper.dart';
|
|
|
|
|
import '../helpers/cyr2lat.dart';
|
|
|
|
|
import '../helpers/smaz.dart';
|
|
|
|
|
import '../services/app_debug_log_service.dart';
|
|
|
|
|
import '../services/ble_debug_log_service.dart';
|
|
|
|
|
@ -283,9 +284,11 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
final UnreadStore _unreadStore = UnreadStore();
|
|
|
|
|
List<Channel> _cachedChannels = [];
|
|
|
|
|
final Map<int, bool> _channelSmazEnabled = {};
|
|
|
|
|
final Map<int, bool> _channelCyr2LatEnabled = {};
|
|
|
|
|
bool _lastSentWasCliCommand =
|
|
|
|
|
false; // Track if last sent message was a CLI command
|
|
|
|
|
final Map<String, bool> _contactSmazEnabled = {};
|
|
|
|
|
final Map<String, bool> _contactCyr2LatEnabled = {};
|
|
|
|
|
final Set<String> _knownContactKeys = {};
|
|
|
|
|
final Map<String, int> _contactUnreadCount = {};
|
|
|
|
|
final Map<String, RepeaterBatterySnapshot> _repeaterBatterySnapshots = {};
|
|
|
|
|
@ -607,6 +610,18 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
_ensureContactSmazSettingLoaded(contactKeyHex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isChannelCyr2LatEnabled(int channelIndex) {
|
|
|
|
|
return _channelCyr2LatEnabled[channelIndex] ?? false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isContactCyr2LatEnabled(String contactKeyHex) {
|
|
|
|
|
return _contactCyr2LatEnabled[contactKeyHex] ?? false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ensureContactCyr2LatSettingLoaded(String contactKeyHex) {
|
|
|
|
|
_ensureContactCyr2LatSettingLoaded(contactKeyHex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> loadUnreadState() async {
|
|
|
|
|
_contactUnreadCount
|
|
|
|
|
..clear()
|
|
|
|
|
@ -682,6 +697,10 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
|
|
|
|
|
Future<void> setChannelSmazEnabled(int channelIndex, bool enabled) async {
|
|
|
|
|
_channelSmazEnabled[channelIndex] = enabled;
|
|
|
|
|
if (enabled) {
|
|
|
|
|
_channelCyr2LatEnabled[channelIndex] = false;
|
|
|
|
|
await _channelSettingsStore.saveCyr2LatEnabled(channelIndex, false);
|
|
|
|
|
}
|
|
|
|
|
await _channelSettingsStore.saveSmazEnabled(channelIndex, enabled);
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
@ -692,6 +711,25 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> setChannelCyr2LatEnabled(int channelIndex, bool enabled) async {
|
|
|
|
|
_channelCyr2LatEnabled[channelIndex] = enabled;
|
|
|
|
|
if (enabled) {
|
|
|
|
|
_channelSmazEnabled[channelIndex] = false;
|
|
|
|
|
await _channelSettingsStore.saveSmazEnabled(channelIndex, false);
|
|
|
|
|
}
|
|
|
|
|
await _channelSettingsStore.saveCyr2LatEnabled(channelIndex, enabled);
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> setContactCyr2LatEnabled(
|
|
|
|
|
String contactKeyHex,
|
|
|
|
|
bool enabled,
|
|
|
|
|
) async {
|
|
|
|
|
_contactCyr2LatEnabled[contactKeyHex] = enabled;
|
|
|
|
|
await _contactSettingsStore.saveCyr2LatEnabled(contactKeyHex, enabled);
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _loadChannelOrder() async {
|
|
|
|
|
_channelOrder = await _channelOrderStore.loadChannelOrder();
|
|
|
|
|
_applyChannelOrder();
|
|
|
|
|
@ -828,6 +866,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
..addAll(cached);
|
|
|
|
|
for (final contact in cached) {
|
|
|
|
|
_ensureContactSmazSettingLoaded(contact.publicKeyHex);
|
|
|
|
|
_ensureContactCyr2LatSettingLoaded(contact.publicKeyHex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -840,9 +879,12 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
|
|
|
|
|
Future<void> loadChannelSettings({int? maxChannels}) async {
|
|
|
|
|
_channelSmazEnabled.clear();
|
|
|
|
|
_channelCyr2LatEnabled.clear();
|
|
|
|
|
final channelCount = maxChannels ?? _maxChannels;
|
|
|
|
|
for (int i = 0; i < channelCount; i++) {
|
|
|
|
|
_channelSmazEnabled[i] = await _channelSettingsStore.loadSmazEnabled(i);
|
|
|
|
|
_channelCyr2LatEnabled[i] = await _channelSettingsStore
|
|
|
|
|
.loadCyr2LatEnabled(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -4432,6 +4474,15 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _ensureContactCyr2LatSettingLoaded(String contactKeyHex) {
|
|
|
|
|
if (_contactCyr2LatEnabled.containsKey(contactKeyHex)) return;
|
|
|
|
|
_contactSettingsStore.loadCyr2LatEnabled(contactKeyHex).then((enabled) {
|
|
|
|
|
if (_contactCyr2LatEnabled[contactKeyHex] == enabled) return;
|
|
|
|
|
_contactCyr2LatEnabled[contactKeyHex] = enabled;
|
|
|
|
|
notifyListeners();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Prepares contact outbound text by applying SMAZ encoding if enabled.
|
|
|
|
|
/// This should be used to transform text before computing ACK hashes.
|
|
|
|
|
String prepareContactOutboundText(Contact contact, String text) {
|
|
|
|
|
@ -4440,8 +4491,12 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
trimmed.startsWith('g:') ||
|
|
|
|
|
trimmed.startsWith('m:') ||
|
|
|
|
|
trimmed.startsWith('V1|');
|
|
|
|
|
if (!isStructuredPayload && isContactSmazEnabled(contact.publicKeyHex)) {
|
|
|
|
|
return Smaz.encodeIfSmaller(text);
|
|
|
|
|
if (!isStructuredPayload) {
|
|
|
|
|
if (isContactSmazEnabled(contact.publicKeyHex)) {
|
|
|
|
|
return Smaz.encodeIfSmaller(text);
|
|
|
|
|
} else if (isContactCyr2LatEnabled(contact.publicKeyHex)) {
|
|
|
|
|
return Cyr2Lat.encode(text);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
@ -4450,8 +4505,12 @@ class MeshCoreConnector extends ChangeNotifier {
|
|
|
|
|
final trimmed = text.trim();
|
|
|
|
|
final isStructuredPayload =
|
|
|
|
|
trimmed.startsWith('g:') || trimmed.startsWith('m:');
|
|
|
|
|
if (!isStructuredPayload && isChannelSmazEnabled(channelIndex)) {
|
|
|
|
|
return Smaz.encodeIfSmaller(text);
|
|
|
|
|
if (!isStructuredPayload) {
|
|
|
|
|
if (isChannelSmazEnabled(channelIndex)) {
|
|
|
|
|
return Smaz.encodeIfSmaller(text);
|
|
|
|
|
} else if (isChannelCyr2LatEnabled(channelIndex)) {
|
|
|
|
|
return Cyr2Lat.encode(text);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|