mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Update log display handling
This commit is contained in:
@@ -5,24 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.001473">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000235">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.569758">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.385323">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="95.271262">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="93.530304">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="91.795184">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="210.562484">
|
||||||
|
|
||||||
<failure message="/opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/actions/actions_helper.rb:67:in 'Fastlane::Actions.execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:255:in 'block in Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:157:in 'Fastlane::Runner#trigger_action_by_name' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/fast_file.rb:159:in 'Fastlane::FastFile#method_missing' Fastfile:23:in 'block (2 levels) in Fastlane::FastFile#parsing_binding' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/cli_tools_distributor.rb:132:in 'Fastlane::CLIToolsDistributor.take_off' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/bin/fastlane:23:in '<top (required)>' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Kernel#load' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Gem.activate_and_load_bin_path' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/bin/fastlane:25:in '<main>' Invalid username and password combination. Used 'hey@dz0n.dev' as the username." />
|
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -549,6 +549,15 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final incomingPathBytes = receptionDetailsSnapshot?.pathBytes;
|
||||||
|
if (incomingPathBytes != null &&
|
||||||
|
incomingPathBytes.isNotEmpty &&
|
||||||
|
finalMessage.pathBytes == null) {
|
||||||
|
finalMessage = finalMessage.copyWith(
|
||||||
|
pathBytes: Uint8List.fromList(incomingPathBytes),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Debug: Check if message is SAR
|
// Debug: Check if message is SAR
|
||||||
if (message.text.startsWith('S:')) {
|
if (message.text.startsWith('S:')) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
@@ -582,6 +591,15 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
if (receptionDetailsSnapshot != null) {
|
if (receptionDetailsSnapshot != null) {
|
||||||
_messageReceptionDetails[existingId] = receptionDetailsSnapshot;
|
_messageReceptionDetails[existingId] = receptionDetailsSnapshot;
|
||||||
|
final existingMessage = _messages[duplicateIndex];
|
||||||
|
final duplicatePathBytes = receptionDetailsSnapshot.pathBytes;
|
||||||
|
if (existingMessage.pathBytes == null &&
|
||||||
|
duplicatePathBytes != null &&
|
||||||
|
duplicatePathBytes.isNotEmpty) {
|
||||||
|
_messages[duplicateIndex] = existingMessage.copyWith(
|
||||||
|
pathBytes: Uint8List.fromList(duplicatePathBytes),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_persistMessages();
|
_persistMessages();
|
||||||
return; // Skip duplicate
|
return; // Skip duplicate
|
||||||
@@ -692,7 +710,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
incomingSenderName != null &&
|
incomingSenderName != null &&
|
||||||
existingSenderName == incomingSenderName) {
|
existingSenderName == incomingSenderName) {
|
||||||
if (!existing.isSentMessage && !message.isSentMessage) {
|
if (!existing.isSentMessage && !message.isSentMessage) {
|
||||||
return true;
|
return withinChannelRepeatWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!withinChannelRepeatWindow) {
|
if (!withinChannelRepeatWindow) {
|
||||||
@@ -715,7 +733,8 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
// System messages and other types: never deduplicate by scope alone.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add multiple messages
|
/// Add multiple messages
|
||||||
@@ -725,7 +744,33 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
for (final message in messages) {
|
for (final message in messages) {
|
||||||
// Always enhance message with SAR parser to detect SAR markers
|
// Always enhance message with SAR parser to detect SAR markers
|
||||||
final enhancedMessage = SarMessageParser.enhanceMessage(message);
|
var enhancedMessage = SarMessageParser.enhanceMessage(message);
|
||||||
|
|
||||||
|
// Check if it's a drawing message (D:...) and not already marked
|
||||||
|
if (DrawingMessageParser.isDrawingMessage(enhancedMessage.text) &&
|
||||||
|
!enhancedMessage.isDrawing) {
|
||||||
|
final drawing = DrawingMessageParser.parseDrawingMessage(
|
||||||
|
enhancedMessage.text,
|
||||||
|
senderName: enhancedMessage.senderName,
|
||||||
|
messageId: enhancedMessage.id,
|
||||||
|
);
|
||||||
|
enhancedMessage = enhancedMessage.copyWith(
|
||||||
|
isDrawing: true,
|
||||||
|
drawingId: drawing?.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's a voice message and not already marked
|
||||||
|
if (!enhancedMessage.isVoice) {
|
||||||
|
final envelope = VoiceEnvelope.tryParseText(enhancedMessage.text);
|
||||||
|
if (envelope != null) {
|
||||||
|
enhancedMessage = enhancedMessage.copyWith(
|
||||||
|
isVoice: true,
|
||||||
|
voiceId: envelope.sessionId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enhancedMessage = _resolveSenderNameIfNeeded(enhancedMessage);
|
||||||
|
|
||||||
// Check for duplicates
|
// Check for duplicates
|
||||||
if (_findDuplicateMessageIndex(enhancedMessage) != -1) {
|
if (_findDuplicateMessageIndex(enhancedMessage) != -1) {
|
||||||
@@ -1028,6 +1073,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
for (final messageId in messageIdsToRemove) {
|
for (final messageId in messageIdsToRemove) {
|
||||||
_timeoutTimers[messageId]?.cancel();
|
_timeoutTimers[messageId]?.cancel();
|
||||||
_timeoutTimers.remove(messageId);
|
_timeoutTimers.remove(messageId);
|
||||||
|
_clearChannelSendWarning(messageId);
|
||||||
_messageContactMap.remove(messageId);
|
_messageContactMap.remove(messageId);
|
||||||
_groupedMessageMapping.remove(messageId);
|
_groupedMessageMapping.remove(messageId);
|
||||||
_messageContactLocations.remove(messageId);
|
_messageContactLocations.remove(messageId);
|
||||||
@@ -1245,11 +1291,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
/// Clear all messages
|
/// Clear all messages
|
||||||
void clearMessages() {
|
void clearMessages() {
|
||||||
for (final timer in _channelEchoWarningTimers.values) {
|
_cancelAllTimers();
|
||||||
timer.cancel();
|
|
||||||
}
|
|
||||||
_channelEchoWarningTimers.clear();
|
|
||||||
_channelEchoWarningMessageIds.clear();
|
|
||||||
_messages.clear();
|
_messages.clear();
|
||||||
_sarMarkers.clear();
|
_sarMarkers.clear();
|
||||||
_removedSarMarkerIds.clear();
|
_removedSarMarkerIds.clear();
|
||||||
@@ -1257,6 +1299,14 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
_messageReceptionDetails.clear();
|
_messageReceptionDetails.clear();
|
||||||
_messageTransferDetails.clear();
|
_messageTransferDetails.clear();
|
||||||
_messageRouteMetadata.clear();
|
_messageRouteMetadata.clear();
|
||||||
|
_pendingSentMessages.clear();
|
||||||
|
_messageContactMap.clear();
|
||||||
|
_groupedMessageMapping.clear();
|
||||||
|
_ackTagToRecipients.clear();
|
||||||
|
_messageAckHistory.clear();
|
||||||
|
_ackHistoryLookup.clear();
|
||||||
|
_completedAckHistory.clear();
|
||||||
|
_retryManager.clearAll();
|
||||||
_persistMessages();
|
_persistMessages();
|
||||||
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -1272,11 +1322,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
/// Clear all data
|
/// Clear all data
|
||||||
void clearAll() {
|
void clearAll() {
|
||||||
for (final timer in _channelEchoWarningTimers.values) {
|
_cancelAllTimers();
|
||||||
timer.cancel();
|
|
||||||
}
|
|
||||||
_channelEchoWarningTimers.clear();
|
|
||||||
_channelEchoWarningMessageIds.clear();
|
|
||||||
_messages.clear();
|
_messages.clear();
|
||||||
_sarMarkers.clear();
|
_sarMarkers.clear();
|
||||||
_removedSarMarkerIds.clear();
|
_removedSarMarkerIds.clear();
|
||||||
@@ -1284,6 +1330,14 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
_messageReceptionDetails.clear();
|
_messageReceptionDetails.clear();
|
||||||
_messageTransferDetails.clear();
|
_messageTransferDetails.clear();
|
||||||
_messageRouteMetadata.clear();
|
_messageRouteMetadata.clear();
|
||||||
|
_pendingSentMessages.clear();
|
||||||
|
_messageContactMap.clear();
|
||||||
|
_groupedMessageMapping.clear();
|
||||||
|
_ackTagToRecipients.clear();
|
||||||
|
_messageAckHistory.clear();
|
||||||
|
_ackHistoryLookup.clear();
|
||||||
|
_completedAckHistory.clear();
|
||||||
|
_retryManager.clearAll();
|
||||||
_persistMessages();
|
_persistMessages();
|
||||||
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
unawaited(_storageService.saveRemovedSarMarkerIds(_removedSarMarkerIds));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -1964,7 +2018,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
debugPrint(' Message index in list: $index');
|
debugPrint(' Message index in list: $index');
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
final updatedMessage = message.copyWith(
|
final updatedMessage = _messages[index].copyWith(
|
||||||
deliveryStatus: MessageDeliveryStatus.delivered,
|
deliveryStatus: MessageDeliveryStatus.delivered,
|
||||||
roundTripTimeMs: roundTripTimeMs,
|
roundTripTimeMs: roundTripTimeMs,
|
||||||
deliveredAt: DateTime.now(),
|
deliveredAt: DateTime.now(),
|
||||||
@@ -2323,6 +2377,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
senderPublicKeyPrefix: message.senderPublicKeyPrefix,
|
senderPublicKeyPrefix: message.senderPublicKeyPrefix,
|
||||||
channelIdx: message.channelIdx,
|
channelIdx: message.channelIdx,
|
||||||
pathLen: message.pathLen,
|
pathLen: message.pathLen,
|
||||||
|
pathBytes: message.pathBytes,
|
||||||
textType: message.textType,
|
textType: message.textType,
|
||||||
senderTimestamp: message.senderTimestamp,
|
senderTimestamp: message.senderTimestamp,
|
||||||
text: message.text,
|
text: message.text,
|
||||||
@@ -2410,7 +2465,19 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
// Cancel all pending timeout timers
|
_cancelAllTimers();
|
||||||
|
_completedAckHistory.clear();
|
||||||
|
_messageAckHistory.clear();
|
||||||
|
_ackHistoryLookup.clear();
|
||||||
|
|
||||||
|
// Clear retry manager
|
||||||
|
_retryManager.clearAll();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cancel all pending timers (timeout + echo warning).
|
||||||
|
void _cancelAllTimers() {
|
||||||
for (final timer in _timeoutTimers.values) {
|
for (final timer in _timeoutTimers.values) {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
}
|
}
|
||||||
@@ -2420,14 +2487,6 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
_channelEchoWarningTimers.clear();
|
_channelEchoWarningTimers.clear();
|
||||||
_channelEchoWarningMessageIds.clear();
|
_channelEchoWarningMessageIds.clear();
|
||||||
_completedAckHistory.clear();
|
|
||||||
_messageAckHistory.clear();
|
|
||||||
_ackHistoryLookup.clear();
|
|
||||||
|
|
||||||
// Clear retry manager
|
|
||||||
_retryManager.clearAll();
|
|
||||||
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _rememberCompletedAck(int ackCode) {
|
void _rememberCompletedAck(int ackCode) {
|
||||||
|
|||||||
@@ -329,6 +329,8 @@ class MessageStorageService {
|
|||||||
Message message, {
|
Message message, {
|
||||||
MessageReceptionDetails? receptionDetails,
|
MessageReceptionDetails? receptionDetails,
|
||||||
}) {
|
}) {
|
||||||
|
final persistedPathBytes =
|
||||||
|
message.pathBytes ?? _pathBytesFromSnapshot(receptionDetails);
|
||||||
return {
|
return {
|
||||||
'id': message.id,
|
'id': message.id,
|
||||||
'messageType': message.messageType.name,
|
'messageType': message.messageType.name,
|
||||||
@@ -337,6 +339,7 @@ class MessageStorageService {
|
|||||||
: null,
|
: null,
|
||||||
'channelIdx': message.channelIdx,
|
'channelIdx': message.channelIdx,
|
||||||
'pathLen': message.pathLen,
|
'pathLen': message.pathLen,
|
||||||
|
'pathBytes': persistedPathBytes?.toList(),
|
||||||
'textType': message.textType.value,
|
'textType': message.textType.value,
|
||||||
'senderTimestamp': message.senderTimestamp,
|
'senderTimestamp': message.senderTimestamp,
|
||||||
'text': message.text,
|
'text': message.text,
|
||||||
@@ -465,6 +468,14 @@ class MessageStorageService {
|
|||||||
: null,
|
: null,
|
||||||
channelIdx: json['channelIdx'] as int?,
|
channelIdx: json['channelIdx'] as int?,
|
||||||
pathLen: json['pathLen'] as int,
|
pathLen: json['pathLen'] as int,
|
||||||
|
pathBytes: json['pathBytes'] is List
|
||||||
|
? Uint8List.fromList(
|
||||||
|
(json['pathBytes'] as List<dynamic>)
|
||||||
|
.whereType<num>()
|
||||||
|
.map((b) => b.toInt())
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
textType: MessageTextType.fromValue(json['textType'] as int),
|
textType: MessageTextType.fromValue(json['textType'] as int),
|
||||||
senderTimestamp: json['senderTimestamp'] as int,
|
senderTimestamp: json['senderTimestamp'] as int,
|
||||||
text: json['text'] as String,
|
text: json['text'] as String,
|
||||||
@@ -562,4 +573,12 @@ class MessageStorageService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uint8List? _pathBytesFromSnapshot(MessageReceptionDetails? receptionDetails) {
|
||||||
|
final pathBytes = receptionDetails?.pathBytes;
|
||||||
|
if (pathBytes == null || pathBytes.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Uint8List.fromList(pathBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -795,8 +795,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "461f010"
|
ref: "27e65f4"
|
||||||
resolved-ref: "461f010a2f1fcd343357c152228891e295d391be"
|
resolved-ref: "27e65f48b1b5dc3dbcafc0167c4c5755770116ba"
|
||||||
url: "https://github.com/dz0ny/meshcore_client.git"
|
url: "https://github.com/dz0ny/meshcore_client.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.1.0"
|
version: "0.1.0"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ dependencies:
|
|||||||
meshcore_client:
|
meshcore_client:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/dz0ny/meshcore_client.git
|
url: https://github.com/dz0ny/meshcore_client.git
|
||||||
ref: "461f010"
|
ref: "27e65f4"
|
||||||
|
|
||||||
# Codec2 ultra-low-bitrate speech codec (FFI plugin)
|
# Codec2 ultra-low-bitrate speech codec (FFI plugin)
|
||||||
codec2_flutter:
|
codec2_flutter:
|
||||||
|
|||||||
@@ -43,9 +43,11 @@ void main() {
|
|||||||
await prefs.remove('stored_message_reception_details');
|
await prefs.remove('stored_message_reception_details');
|
||||||
|
|
||||||
final restoredDetails = await storage.loadMessageReceptionDetails();
|
final restoredDetails = await storage.loadMessageReceptionDetails();
|
||||||
|
final restoredMessages = await storage.loadMessages();
|
||||||
|
|
||||||
expect(restoredDetails.keys, contains(message.id));
|
expect(restoredDetails.keys, contains(message.id));
|
||||||
expect(restoredDetails[message.id]?.pathBytes, [0xAA, 0xBB, 0xCC]);
|
expect(restoredDetails[message.id]?.pathBytes, [0xAA, 0xBB, 0xCC]);
|
||||||
|
expect(restoredMessages.single.pathBytes, [0xAA, 0xBB, 0xCC]);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user