mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: Keep received replays separate
This commit is contained in:
@@ -489,7 +489,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -511,7 +511,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -530,7 +530,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -679,7 +679,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -702,7 +702,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 125;
|
CURRENT_PROJECT_VERSION = 126;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>125</string>
|
<string>126</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000216">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="1.086406">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.728696">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="96.919368">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="101.589371">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="563.579992">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="690.798016">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -664,6 +664,11 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
return; // Skip duplicate
|
return; // Skip duplicate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final matchingSentReplayIndex = _findMatchingSentReplayIndex(finalMessage);
|
||||||
|
if (matchingSentReplayIndex != -1) {
|
||||||
|
_clearChannelSendWarning(_messages[matchingSentReplayIndex].id);
|
||||||
|
}
|
||||||
|
|
||||||
_messages.add(finalMessage);
|
_messages.add(finalMessage);
|
||||||
if (contactLocationSnapshot != null) {
|
if (contactLocationSnapshot != null) {
|
||||||
_messageContactLocations[finalMessage.id] = contactLocationSnapshot;
|
_messageContactLocations[finalMessage.id] = contactLocationSnapshot;
|
||||||
@@ -712,7 +717,8 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
for (int index = 0; index < _messages.length; index++) {
|
for (int index = 0; index < _messages.length; index++) {
|
||||||
final existing = _messages[index];
|
final existing = _messages[index];
|
||||||
if (!_matchesDuplicateScope(existing, message) ||
|
if (existing.isSentMessage ||
|
||||||
|
!_matchesDuplicateScope(existing, message) ||
|
||||||
existing.text != message.text) {
|
existing.text != message.text) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -790,6 +796,27 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
existingSenderName == incomingSenderName;
|
existingSenderName == incomingSenderName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _findMatchingSentReplayIndex(Message message) {
|
||||||
|
if (!message.isChannelMessage || message.isSentMessage) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < _messages.length; index++) {
|
||||||
|
final existing = _messages[index];
|
||||||
|
if (!existing.isSentMessage ||
|
||||||
|
!existing.isChannelMessage ||
|
||||||
|
existing.text != message.text) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_matchesDuplicateScope(existing, message)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Add multiple messages
|
/// Add multiple messages
|
||||||
void addMessages(List<Message> messages) {
|
void addMessages(List<Message> messages) {
|
||||||
int addedCount = 0;
|
int addedCount = 0;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2026.0322.2+39
|
version: 2026.0323.1+40
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.9.2
|
sdk: ^3.9.2
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('channel warning clears when replay is deduped into sent bubble', () {
|
test('channel warning clears when replay arrives after send', () {
|
||||||
fakeAsync((async) {
|
fakeAsync((async) {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
||||||
@@ -239,11 +239,11 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(provider.hasChannelSendWarning('c-warn-replay'), isFalse);
|
expect(provider.hasChannelSendWarning('c-warn-replay'), isFalse);
|
||||||
expect(provider.messages, hasLength(1));
|
expect(provider.messages, hasLength(2));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('channel replay is deduped for self sender within repeat window', () {
|
test('channel replay is kept separate for self sender within repeat window', () {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
provider.resolveContactNameCallback = (_) => 'dz0ny (SI)';
|
||||||
provider.addSentMessage(
|
provider.addSentMessage(
|
||||||
@@ -259,9 +259,10 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(provider.messages, hasLength(1));
|
expect(provider.messages, hasLength(2));
|
||||||
expect(provider.messages.single.id, equals('c-echo'));
|
expect(provider.messages.first.id, equals('c-echo'));
|
||||||
expect(provider.messages.single.senderName, equals('dz0ny (SI)'));
|
expect(provider.messages.last.id, equals('c-echo-incoming'));
|
||||||
|
expect(provider.messages.last.senderName, equals('dz0ny (SI)'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
@@ -308,7 +309,7 @@ void main() {
|
|||||||
expect(provider.messages, hasLength(2));
|
expect(provider.messages, hasLength(2));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('channel replay can dedupe using lazily resolved self name', () {
|
test('channel replay stays separate using lazily resolved self name', () {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.addSentMessage(
|
provider.addSentMessage(
|
||||||
_buildSentChannelMessage(id: 'c-lazy', senderTimestamp: 1700000400),
|
_buildSentChannelMessage(id: 'c-lazy', senderTimestamp: 1700000400),
|
||||||
@@ -324,11 +325,12 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(provider.messages, hasLength(1));
|
expect(provider.messages, hasLength(2));
|
||||||
expect(provider.messages.single.id, equals('c-lazy'));
|
expect(provider.messages.first.id, equals('c-lazy'));
|
||||||
|
expect(provider.messages.last.id, equals('c-lazy-incoming'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('channel replay dedupes meshcore-prefixed self sender name', () {
|
test('channel replay stays separate for meshcore-prefixed self sender name', () {
|
||||||
final provider = MessagesProvider();
|
final provider = MessagesProvider();
|
||||||
provider.resolveContactNameCallback = (_) => 'MeshCore-dz0ny (SI)';
|
provider.resolveContactNameCallback = (_) => 'MeshCore-dz0ny (SI)';
|
||||||
provider.addSentMessage(
|
provider.addSentMessage(
|
||||||
@@ -344,8 +346,9 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(provider.messages, hasLength(1));
|
expect(provider.messages, hasLength(2));
|
||||||
expect(provider.messages.single.id, equals('c-prefix'));
|
expect(provider.messages.first.id, equals('c-prefix'));
|
||||||
|
expect(provider.messages.last.id, equals('c-prefix-incoming'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('duplicate incoming message increments received copy count', () {
|
test('duplicate incoming message increments received copy count', () {
|
||||||
|
|||||||
Reference in New Issue
Block a user