commit
1ad5db27ca
@ -1,105 +0,0 @@
|
|||||||
import 'dart:typed_data';
|
|
||||||
import '../connector/meshcore_protocol.dart';
|
|
||||||
|
|
||||||
class DiscoveryContact {
|
|
||||||
final Uint8List rawPacket;
|
|
||||||
final Uint8List publicKey;
|
|
||||||
final String name;
|
|
||||||
final int type;
|
|
||||||
final int pathLength; // -1 = flood, 0+ = direct hops (from device)
|
|
||||||
final Uint8List path; // Path bytes from device
|
|
||||||
final double? latitude;
|
|
||||||
final double? longitude;
|
|
||||||
final DateTime lastSeen;
|
|
||||||
|
|
||||||
DiscoveryContact({
|
|
||||||
required this.rawPacket,
|
|
||||||
required this.publicKey,
|
|
||||||
required this.name,
|
|
||||||
required this.type,
|
|
||||||
required this.pathLength,
|
|
||||||
required this.path,
|
|
||||||
this.latitude,
|
|
||||||
this.longitude,
|
|
||||||
required this.lastSeen,
|
|
||||||
});
|
|
||||||
|
|
||||||
String get publicKeyHex => pubKeyToHex(publicKey);
|
|
||||||
|
|
||||||
String get typeLabel {
|
|
||||||
switch (type) {
|
|
||||||
case advTypeChat:
|
|
||||||
return 'Chat';
|
|
||||||
case advTypeRepeater:
|
|
||||||
return 'Repeater';
|
|
||||||
case advTypeRoom:
|
|
||||||
return 'Room';
|
|
||||||
case advTypeSensor:
|
|
||||||
return 'Sensor';
|
|
||||||
default:
|
|
||||||
return 'Unknown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String get pathLabel {
|
|
||||||
if (pathLength < 0) return 'Flood';
|
|
||||||
if (pathLength == 0) return 'Direct';
|
|
||||||
return '$pathLength hops';
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get hasLocation => latitude != null && longitude != null;
|
|
||||||
|
|
||||||
DiscoveryContact copyWith({
|
|
||||||
Uint8List? rawPacket,
|
|
||||||
Uint8List? publicKey,
|
|
||||||
String? name,
|
|
||||||
int? type,
|
|
||||||
int? pathLength,
|
|
||||||
Uint8List? path,
|
|
||||||
double? latitude,
|
|
||||||
double? longitude,
|
|
||||||
DateTime? lastSeen,
|
|
||||||
}) {
|
|
||||||
return DiscoveryContact(
|
|
||||||
rawPacket: rawPacket ?? this.rawPacket,
|
|
||||||
publicKey: publicKey ?? this.publicKey,
|
|
||||||
name: name ?? this.name,
|
|
||||||
type: type ?? this.type,
|
|
||||||
pathLength: pathLength ?? this.pathLength,
|
|
||||||
path: path ?? this.path,
|
|
||||||
latitude: latitude ?? this.latitude,
|
|
||||||
longitude: longitude ?? this.longitude,
|
|
||||||
lastSeen: lastSeen ?? this.lastSeen,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String get pathIdList {
|
|
||||||
final pathBytes = path;
|
|
||||||
if (pathBytes.isEmpty) return '';
|
|
||||||
final parts = <String>[];
|
|
||||||
final groupSize = pathHashSize;
|
|
||||||
for (int i = 0; i < pathBytes.length; i += groupSize) {
|
|
||||||
final end = (i + groupSize) <= pathBytes.length
|
|
||||||
? (i + groupSize)
|
|
||||||
: pathBytes.length;
|
|
||||||
final chunk = pathBytes.sublist(i, end);
|
|
||||||
parts.add(
|
|
||||||
chunk
|
|
||||||
.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase())
|
|
||||||
.join(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return parts.join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
String get shortPubKeyHex {
|
|
||||||
return "<${publicKeyHex.substring(0, 8)}...${publicKeyHex.substring(publicKeyHex.length - 8)}>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
other is DiscoveryContact && publicKeyHex == other.publicKeyHex;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => publicKeyHex.hashCode;
|
|
||||||
}
|
|
||||||
@ -1,17 +1,49 @@
|
|||||||
|
import '../utils/app_logger.dart';
|
||||||
import 'prefs_manager.dart';
|
import 'prefs_manager.dart';
|
||||||
|
|
||||||
class ChannelSettingsStore {
|
class ChannelSettingsStore {
|
||||||
static const String _smazKeyPrefix = 'channel_smaz_';
|
static const String _keyPrefix = 'channel_smaz_';
|
||||||
|
|
||||||
|
String publicKeyHex = '';
|
||||||
|
set setPublicKeyHex(String value) =>
|
||||||
|
publicKeyHex = value.length > 10 ? value.substring(0, 10) : '';
|
||||||
|
|
||||||
|
String get keyFor => '$_keyPrefix$publicKeyHex';
|
||||||
|
|
||||||
Future<bool> loadSmazEnabled(int channelIndex) async {
|
Future<bool> loadSmazEnabled(int channelIndex) async {
|
||||||
|
if (publicKeyHex.isEmpty) {
|
||||||
|
appLogger.warn(
|
||||||
|
'Public key hex is not set. Cannot load channel settings.',
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
final prefs = PrefsManager.instance;
|
final prefs = PrefsManager.instance;
|
||||||
final key = '$_smazKeyPrefix$channelIndex';
|
final key = '$keyFor$channelIndex';
|
||||||
return prefs.getBool(key) ?? false;
|
final oldKey = '$_keyPrefix$channelIndex';
|
||||||
|
bool? enabled = prefs.getBool(oldKey);
|
||||||
|
if (enabled == null) {
|
||||||
|
// Attempt migration from legacy unscoped key on first load
|
||||||
|
enabled = prefs.getBool(oldKey);
|
||||||
|
prefs.remove(oldKey);
|
||||||
|
if (enabled != null) {
|
||||||
|
appLogger.info(
|
||||||
|
'Migrating channel settings from legacy key $oldKey to scoped key $key',
|
||||||
|
);
|
||||||
|
await prefs.setBool(key, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enabled ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveSmazEnabled(int channelIndex, bool enabled) async {
|
Future<void> saveSmazEnabled(int channelIndex, bool enabled) async {
|
||||||
|
if (publicKeyHex.isEmpty) {
|
||||||
|
appLogger.warn(
|
||||||
|
'Public key hex is not set. Cannot save channel settings.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
final prefs = PrefsManager.instance;
|
final prefs = PrefsManager.instance;
|
||||||
final key = '$_smazKeyPrefix$channelIndex';
|
final key = '$keyFor$channelIndex';
|
||||||
await prefs.setBool(key, enabled);
|
await prefs.setBool(key, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,49 @@
|
|||||||
|
import '../utils/app_logger.dart';
|
||||||
import 'prefs_manager.dart';
|
import 'prefs_manager.dart';
|
||||||
|
|
||||||
class ContactSettingsStore {
|
class ContactSettingsStore {
|
||||||
static const String _smazKeyPrefix = 'contact_smaz_';
|
static const String _keyPrefix = 'contact_smaz_';
|
||||||
|
|
||||||
|
String publicKeyHex = '';
|
||||||
|
set setPublicKeyHex(String value) =>
|
||||||
|
publicKeyHex = value.length > 10 ? value.substring(0, 10) : '';
|
||||||
|
|
||||||
|
String get keyFor => '$_keyPrefix$publicKeyHex';
|
||||||
|
|
||||||
Future<bool> loadSmazEnabled(String contactKeyHex) async {
|
Future<bool> loadSmazEnabled(String contactKeyHex) async {
|
||||||
|
if (publicKeyHex.isEmpty) {
|
||||||
|
appLogger.warn(
|
||||||
|
'Public key hex is not set. Cannot load contact settings.',
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
final prefs = PrefsManager.instance;
|
final prefs = PrefsManager.instance;
|
||||||
final key = '$_smazKeyPrefix$contactKeyHex';
|
final key = '$keyFor$contactKeyHex';
|
||||||
|
final oldKey = '$_keyPrefix$contactKeyHex';
|
||||||
|
bool? enabled = prefs.getBool(key);
|
||||||
|
if (enabled == null) {
|
||||||
|
// Attempt migration from legacy unscoped key on first load
|
||||||
|
enabled = prefs.getBool(oldKey);
|
||||||
|
prefs.remove(oldKey);
|
||||||
|
if (enabled != null) {
|
||||||
|
appLogger.info(
|
||||||
|
'Migrating contact settings from legacy key $oldKey to scoped key $key',
|
||||||
|
);
|
||||||
|
await prefs.setBool(key, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
return prefs.getBool(key) ?? false;
|
return prefs.getBool(key) ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveSmazEnabled(String contactKeyHex, bool enabled) async {
|
Future<void> saveSmazEnabled(String contactKeyHex, bool enabled) async {
|
||||||
|
if (publicKeyHex.isEmpty) {
|
||||||
|
appLogger.warn(
|
||||||
|
'Public key hex is not set. Cannot save contact settings.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
final prefs = PrefsManager.instance;
|
final prefs = PrefsManager.instance;
|
||||||
final key = '$_smazKeyPrefix$contactKeyHex';
|
final key = '$keyFor$contactKeyHex';
|
||||||
await prefs.setBool(key, enabled);
|
await prefs.setBool(key, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in new issue