Fix Crash Bug in Android (ShareFile and Reconnect)

In rare situtaitons (exacerbated by debug mode and multiple
file shares in succession) ReconnectCwtchForeground events can result
in negative message counts being calculated in the UI.

This fix ensures that doesn't happen, but a complete fix will need to wait until #664
is implement in the backend
This commit is contained in:
Sarah Jamie Lewis 2024-01-02 10:48:31 -08:00
parent 44925783f5
commit d4e57f493e
4 changed files with 32 additions and 10 deletions

View File

@ -331,8 +331,9 @@ class MainActivity: FlutterActivity() {
val conversation: Int = call.argument("conversation") ?: 0
val indexI: Int = call.argument("index") ?: 0
val count: Int = call.argument("count") ?: 1
val ucount : Int = maxOf(1, count) // don't allow negative counts
result.success(Cwtch.getMessages(profile, conversation.toLong(), indexI.toLong(), count.toLong()))
result.success(Cwtch.getMessages(profile, conversation.toLong(), indexI.toLong(), ucount.toLong()))
return
}
"SendMessage" -> {

View File

@ -230,6 +230,7 @@ class ContactInfoState extends ChangeNotifier {
return this._newMarkerMsgIndex;
}
int get totalMessages => this._totalMessages;
int get totalMessages => this._totalMessages;
set totalMessages(int newVal) {

View File

@ -30,22 +30,27 @@ class LocalIndexMessage {
this.messageId = messageId;
this.cacheOnly = cacheOnly;
this.isLoading = isLoading;
if (isLoading) {
loader = Completer<void>();
loaded = loader.future;
loader = Completer<void>();
loaded = loader.future;
if (!isLoading) {
loader.complete(); // complete this
}
}
void finishLoad(int messageId) {
this.messageId = messageId;
isLoading = false;
loader.complete(true);
if (!loader.isCompleted) {
isLoading = false;
loader.complete(true);
}
}
void failLoad() {
this.messageId = null;
isLoading = false;
loader.complete(true);
if (!loader.isCompleted) {
isLoading = false;
loader.complete(true);
}
}
Future<void> waitForLoad() {
@ -95,7 +100,7 @@ class MessageCache extends ChangeNotifier {
this._storageMessageCount = newval;
}
// On android reconnect, if backend supplied message count > UI message count, add the differnce to the front of the index
// On android reconnect, if backend supplied message count > UI message count, add the difference to the front of the index
void addFrontIndexGap(int count) {
this._indexUnsynced = count;
}

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:math';
import 'package:cwtch/config.dart';
import 'package:cwtch/models/remoteserver.dart';
@ -248,8 +249,22 @@ class ProfileInfoState extends ChangeNotifier {
if (profileContact != null) {
profileContact.status = contact["status"];
var newCount = contact["numMessages"];
var newCount = contact["numMessages"] as int;
if (newCount != profileContact.totalMessages) {
if (newCount < profileContact.totalMessages) {
// on Android, when sharing a file the UI may be briefly unloaded for the
// OS to display the file management/selection screen. Afterwards a
// call to ReconnectCwtchForeground will be made which will refresh all values (including count of numMessages)
// **at the same time** the foreground will increment .totalMessages and send a new message to the backend.
// This will result in a negative number of messages being calculated here, and an incorrect totalMessage count.
// This bug is exacerbated in debug mode, and when multiple files are sent in succession. Both cases result in multiple ReconnectCwtchForeground
// events that have the potential to conflict with currentMessageCounts.
// Note that *if* a new message came in at the same time, we would be unable to distinguish this case - as such this is specific instance of a more general problem
// TODO: A true-fix to this bug is to implement a syncing step in the foreground where totalMessages and inFlightMessages can be distinguished
// This requires a change to the backend to confirm submission of an inFlightMessage, which will be implemented in #664
EnvironmentConfig.debugLog("Conflicting message counts: $newCount ${profileContact.totalMessages}");
newCount = max(newCount, profileContact.totalMessages);
}
profileContact.messageCache.addFrontIndexGap(newCount - profileContact.totalMessages);
}
profileContact.totalMessages = newCount;