updated ui added new features

This commit is contained in:
zach
2025-12-27 15:32:32 -07:00
parent 02ca7801ea
commit a2cfae3a22
589 changed files with 181780 additions and 569 deletions
+31
View File
@@ -1,4 +1,6 @@
class AppSettings {
static const Object _unset = Object();
final bool clearPathOnMaxRetry;
final bool mapShowRepeaters;
final bool mapShowChatNodes;
@@ -7,8 +9,12 @@ class AppSettings {
final bool mapKeyPrefixEnabled;
final String mapKeyPrefix;
final bool mapShowMarkers;
final Map<String, double>? mapCacheBounds;
final int mapCacheMinZoom;
final int mapCacheMaxZoom;
final bool notificationsEnabled;
final bool notifyOnNewMessage;
final bool notifyOnNewChannelMessage;
final bool notifyOnNewAdvert;
final bool autoRouteRotationEnabled;
final String themeMode;
@@ -23,8 +29,12 @@ class AppSettings {
this.mapKeyPrefixEnabled = false,
this.mapKeyPrefix = '',
this.mapShowMarkers = true,
this.mapCacheBounds,
this.mapCacheMinZoom = 10,
this.mapCacheMaxZoom = 15,
this.notificationsEnabled = true,
this.notifyOnNewMessage = true,
this.notifyOnNewChannelMessage = true,
this.notifyOnNewAdvert = true,
this.autoRouteRotationEnabled = false,
this.themeMode = 'system',
@@ -41,8 +51,12 @@ class AppSettings {
'map_key_prefix_enabled': mapKeyPrefixEnabled,
'map_key_prefix': mapKeyPrefix,
'map_show_markers': mapShowMarkers,
'map_cache_bounds': mapCacheBounds,
'map_cache_min_zoom': mapCacheMinZoom,
'map_cache_max_zoom': mapCacheMaxZoom,
'notifications_enabled': notificationsEnabled,
'notify_on_new_message': notifyOnNewMessage,
'notify_on_new_channel_message': notifyOnNewChannelMessage,
'notify_on_new_advert': notifyOnNewAdvert,
'auto_route_rotation_enabled': autoRouteRotationEnabled,
'theme_mode': themeMode,
@@ -60,8 +74,15 @@ class AppSettings {
mapKeyPrefixEnabled: json['map_key_prefix_enabled'] as bool? ?? false,
mapKeyPrefix: json['map_key_prefix'] as String? ?? '',
mapShowMarkers: json['map_show_markers'] as bool? ?? true,
mapCacheBounds: (json['map_cache_bounds'] as Map?)?.map(
(key, value) => MapEntry(key.toString(), (value as num).toDouble()),
),
mapCacheMinZoom: json['map_cache_min_zoom'] as int? ?? 10,
mapCacheMaxZoom: json['map_cache_max_zoom'] as int? ?? 15,
notificationsEnabled: json['notifications_enabled'] as bool? ?? true,
notifyOnNewMessage: json['notify_on_new_message'] as bool? ?? true,
notifyOnNewChannelMessage:
json['notify_on_new_channel_message'] as bool? ?? true,
notifyOnNewAdvert: json['notify_on_new_advert'] as bool? ?? true,
autoRouteRotationEnabled: json['auto_route_rotation_enabled'] as bool? ?? false,
themeMode: json['theme_mode'] as String? ?? 'system',
@@ -81,8 +102,12 @@ class AppSettings {
bool? mapKeyPrefixEnabled,
String? mapKeyPrefix,
bool? mapShowMarkers,
Object? mapCacheBounds = _unset,
int? mapCacheMinZoom,
int? mapCacheMaxZoom,
bool? notificationsEnabled,
bool? notifyOnNewMessage,
bool? notifyOnNewChannelMessage,
bool? notifyOnNewAdvert,
bool? autoRouteRotationEnabled,
String? themeMode,
@@ -97,8 +122,14 @@ class AppSettings {
mapKeyPrefixEnabled: mapKeyPrefixEnabled ?? this.mapKeyPrefixEnabled,
mapKeyPrefix: mapKeyPrefix ?? this.mapKeyPrefix,
mapShowMarkers: mapShowMarkers ?? this.mapShowMarkers,
mapCacheBounds:
mapCacheBounds == _unset ? this.mapCacheBounds : mapCacheBounds as Map<String, double>?,
mapCacheMinZoom: mapCacheMinZoom ?? this.mapCacheMinZoom,
mapCacheMaxZoom: mapCacheMaxZoom ?? this.mapCacheMaxZoom,
notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled,
notifyOnNewMessage: notifyOnNewMessage ?? this.notifyOnNewMessage,
notifyOnNewChannelMessage:
notifyOnNewChannelMessage ?? this.notifyOnNewChannelMessage,
notifyOnNewAdvert: notifyOnNewAdvert ?? this.notifyOnNewAdvert,
autoRouteRotationEnabled: autoRouteRotationEnabled ?? this.autoRouteRotationEnabled,
themeMode: themeMode ?? this.themeMode,
+41 -1
View File
@@ -32,6 +32,7 @@ class ChannelMessage {
final int repeatCount;
final int? pathLength;
final Uint8List pathBytes;
final List<Uint8List> pathVariants;
final int? channelIndex;
ChannelMessage({
@@ -45,8 +46,13 @@ class ChannelMessage {
this.repeatCount = 0,
this.pathLength,
Uint8List? pathBytes,
List<Uint8List>? pathVariants,
this.channelIndex,
}) : pathBytes = pathBytes ?? Uint8List(0);
}) : pathBytes = pathBytes ?? Uint8List(0),
pathVariants = _mergePathVariants(
pathBytes ?? Uint8List(0),
pathVariants,
);
String? get senderKeyHex => senderKey != null ? pubKeyToHex(senderKey!) : null;
@@ -56,6 +62,7 @@ class ChannelMessage {
int? repeatCount,
int? pathLength,
Uint8List? pathBytes,
List<Uint8List>? pathVariants,
}) {
return ChannelMessage(
senderKey: senderKey,
@@ -68,6 +75,7 @@ class ChannelMessage {
repeatCount: repeatCount ?? this.repeatCount,
pathLength: pathLength ?? this.pathLength,
pathBytes: pathBytes ?? this.pathBytes,
pathVariants: pathVariants ?? this.pathVariants,
channelIndex: channelIndex,
);
}
@@ -164,7 +172,39 @@ class ChannelMessage {
status: ChannelMessageStatus.pending,
pathLength: null,
pathBytes: Uint8List(0),
pathVariants: const [],
channelIndex: channelIndex,
);
}
static List<Uint8List> _mergePathVariants(
Uint8List pathBytes,
List<Uint8List>? pathVariants,
) {
final merged = <Uint8List>[];
void addPath(Uint8List bytes) {
if (bytes.isEmpty) return;
for (final existing in merged) {
if (_pathsEqual(existing, bytes)) return;
}
merged.add(bytes);
}
if (pathVariants != null) {
for (final variant in pathVariants) {
addPath(variant);
}
}
addPath(pathBytes);
return merged;
}
static bool _pathsEqual(Uint8List a, Uint8List b) {
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
}
+27 -1
View File
@@ -10,6 +10,7 @@ class Contact {
final double? latitude;
final double? longitude;
final DateTime lastSeen;
final DateTime lastMessageAt;
Contact({
required this.publicKey,
@@ -20,7 +21,8 @@ class Contact {
this.latitude,
this.longitude,
required this.lastSeen,
});
DateTime? lastMessageAt,
}) : lastMessageAt = lastMessageAt ?? lastSeen;
String get publicKeyHex => pubKeyToHex(publicKey);
@@ -47,6 +49,30 @@ class Contact {
bool get hasLocation => latitude != null && longitude != null;
Contact copyWith({
Uint8List? publicKey,
String? name,
int? type,
int? pathLength,
Uint8List? path,
double? latitude,
double? longitude,
DateTime? lastSeen,
DateTime? lastMessageAt,
}) {
return Contact(
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,
lastMessageAt: lastMessageAt ?? this.lastMessageAt,
);
}
String get pathIdList {
if (path.isEmpty) return '';
final parts = <String>[];
+18
View File
@@ -10,6 +10,10 @@ class Message {
final bool isOutgoing;
final bool isCli;
final MessageStatus status;
final bool isVoice;
final String? voicePath;
final int? voiceDurationMs;
final String? voiceCodec;
// NEW: Retry logic fields
final String? messageId;
@@ -30,6 +34,10 @@ class Message {
required this.isOutgoing,
this.isCli = false,
this.status = MessageStatus.pending,
this.isVoice = false,
this.voicePath,
this.voiceDurationMs,
this.voiceCodec,
this.messageId,
this.retryCount = 0,
this.estimatedTimeoutMs,
@@ -55,6 +63,10 @@ class Message {
int? pathLength,
Uint8List? pathBytes,
bool? isCli,
bool? isVoice,
String? voicePath,
int? voiceDurationMs,
String? voiceCodec,
}) {
return Message(
senderKey: senderKey,
@@ -63,6 +75,10 @@ class Message {
isOutgoing: isOutgoing,
isCli: isCli ?? this.isCli,
status: status ?? this.status,
isVoice: isVoice ?? this.isVoice,
voicePath: voicePath ?? this.voicePath,
voiceDurationMs: voiceDurationMs ?? this.voiceDurationMs,
voiceCodec: voiceCodec ?? this.voiceCodec,
messageId: messageId,
retryCount: retryCount ?? this.retryCount,
estimatedTimeoutMs: estimatedTimeoutMs ?? this.estimatedTimeoutMs,
@@ -101,6 +117,7 @@ class Message {
isOutgoing: false,
isCli: false,
status: MessageStatus.delivered,
isVoice: false,
pathBytes: Uint8List(0),
);
}
@@ -118,6 +135,7 @@ class Message {
isOutgoing: true,
isCli: false,
status: MessageStatus.pending,
isVoice: false,
pathLength: pathLength,
pathBytes: pathBytes,
);