Show private conversation start failures and test stale confirmation isolation

This commit is contained in:
evgeny committed 2026-10-29 13:35:41 +01:00
1 parent 321a2c3ed7
commit ea67b491f9
3 files changed
+52 -1

No files matched your search

@@ -78,6 +78,7 @@ fun MemberListScreen(
val localSockets by viewModel.localSockets.collectAsState()
val channelOwner by viewModel.channelOwner.collectAsState()
val radioMuteFailed by viewModel.radioMuteFailed.collectAsState()
val dmStartFailed by viewModel.dmStartFailed.collectAsState()
val radioActive by viewModel.radioActive.collectAsState()
val radioTalkState by viewModel.radioTalkState.collectAsState()
val transmittingGroup by viewModel.radioAudio.transmittingGroup.collectAsState()
@@ -156,6 +157,11 @@ fun MemberListScreen(
confirmButton = { TextButton(onClick = viewModel::dismissRadioMuteError) { Text(stringResource(android.R.string.ok)) } }
)
}
if (dmStartFailed) AlertDialog(
onDismissRequest = viewModel::dismissDmStartError,
text = { Text(stringResource(R.string.invite_pm_start_failed)) },
confirmButton = { TextButton(onClick = viewModel::dismissDmStartError) { Text(stringResource(android.R.string.ok)) } }
)
val editingMember = editMember
if (showEditDialog && editingMember != null) key(channel.id, editingMember.nodeId) {
@@ -1339,7 +1339,9 @@ class ChatViewModel : ViewModel() {
}
fun startDm(channelId: String, nodeId: Long, name: String) {
val r = repo ?: return
val r = repo ?: run {
_dmStartFailed.value = true; LogManager.addLog("WARN", "PM", "Conversation start rejected: repository unavailable"); return
}
if (nodeId == 0L || nodeId == NativeLib.getMyNodeId()) return
cancelDmStart(); _dmStartFailed.value = false
try {
@@ -0,0 +1,43 @@
package com.utun.chat.data
import org.junit.Assert.*
import org.junit.Test
class PendingDmOpenTest {
@Test fun unrelatedConversationDoesNotConsumeRequestedPeer() {
val pending = PendingDmOpen()
val token = pending.begin("51", 12, "requested")
assertNull(pending.complete("99", 7))
assertTrue(pending.isPending(token))
val selected = pending.complete("51", 9)!!
assertEquals("51", selected.convId)
assertEquals(12L, selected.peerNodeId)
assertEquals("requested", selected.peerName)
assertEquals(9L, selected.generation)
assertFalse(pending.pending)
assertNull(pending.complete("51", 10))
}
@Test fun newRequestRejectsOldConfirmationAndTimeout() {
val pending = PendingDmOpen()
val previous = pending.begin("51", 12, "first")
val current = pending.begin("52", 13, "second")
assertFalse(pending.isPending(previous))
assertNull(pending.complete("51", 1))
assertTrue(pending.isPending(current))
assertEquals(13L, pending.complete("52", 2)!!.peerNodeId)
}
@Test fun navigationOrTimeoutCancellationIgnoresLateConfirmation() {
val pending = PendingDmOpen()
val token = pending.begin("51", 12, "first")
pending.cancel()
assertFalse(pending.isPending(token))
assertNull(pending.complete("51", 1))
}
@Test fun invalidGenerationKeepsPendingValidConfirmation() {
val pending = PendingDmOpen()
pending.begin("51", 12, "first")
assertNull(pending.complete("51", 0))
assertTrue(pending.pending)
assertNotNull(pending.complete("51", 1))
}
}