fix(android): 使用同步标志修复参与方显示4/3的竞态条件bug
问题根因: - 之前使用异步的 sessionStatus 检查来防止 participant_joined 事件 在 session_started 之后继续添加参与方 - 但 sessionStatus 是通过 StateFlow 异步更新的,检查时状态可能还未更新 - 导致 participant_joined 事件仍能添加额外的参与方,显示4/3而非3/3 解决方案: - 添加同步标志 sessionStartedForSession: String? - 在 session_started 处理器的最开始同步设置此标志 - 在 participant_joined 处理器中检查此标志,而非异步状态 - 由于回调是顺序处理的,这种方式100%可靠 修改内容: 1. 添加 sessionStartedForSession 私有成员变量 2. 在 session_started 事件处理开始时立即设置标志 3. 在 participant_joined 事件处理开始时检查标志 4. 在所有 reset 方法中重置标志: - resetSessionState() - resetJoinKeygenState() - resetCoSignState() - resetTransferState() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1bc42c207a
commit
8a9a983cbd
|
|
@ -45,6 +45,11 @@ class MainViewModel @Inject constructor(
|
||||||
private val _hasEnteredSession = MutableStateFlow(false)
|
private val _hasEnteredSession = MutableStateFlow(false)
|
||||||
val hasEnteredSession: StateFlow<Boolean> = _hasEnteredSession.asStateFlow()
|
val hasEnteredSession: StateFlow<Boolean> = _hasEnteredSession.asStateFlow()
|
||||||
|
|
||||||
|
// Synchronous flag to prevent participant_joined from adding duplicates after session_started
|
||||||
|
// This is set immediately (synchronously) when session_started is processed, ensuring
|
||||||
|
// any subsequent participant_joined events in the same callback queue will see the flag
|
||||||
|
private var sessionStartedForSession: String? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Start initialization on app launch
|
// Start initialization on app launch
|
||||||
checkAllServices()
|
checkAllServices()
|
||||||
|
|
@ -339,6 +344,12 @@ class MainViewModel @Inject constructor(
|
||||||
|
|
||||||
when (event.eventType) {
|
when (event.eventType) {
|
||||||
"session_started" -> {
|
"session_started" -> {
|
||||||
|
// CRITICAL: Set flag immediately (synchronously) to prevent subsequent
|
||||||
|
// participant_joined events from adding duplicates. This must be the
|
||||||
|
// first line before any async operations.
|
||||||
|
sessionStartedForSession = event.sessionId
|
||||||
|
android.util.Log.d("MainViewModel", "Session started flag set for: ${event.sessionId}")
|
||||||
|
|
||||||
// Check if this is for keygen initiator (CreateWallet)
|
// Check if this is for keygen initiator (CreateWallet)
|
||||||
val currentSessionId = _currentSessionId.value
|
val currentSessionId = _currentSessionId.value
|
||||||
if (currentSessionId != null && event.sessionId == currentSessionId) {
|
if (currentSessionId != null && event.sessionId == currentSessionId) {
|
||||||
|
|
@ -396,11 +407,12 @@ class MainViewModel @Inject constructor(
|
||||||
"party_joined", "participant_joined" -> {
|
"party_joined", "participant_joined" -> {
|
||||||
android.util.Log.d("MainViewModel", "Processing participant_joined event...")
|
android.util.Log.d("MainViewModel", "Processing participant_joined event...")
|
||||||
|
|
||||||
// Don't add participants if keygen/sign has already started
|
// CRITICAL: Check synchronous flag first - if session_started was already
|
||||||
// This prevents duplicate additions after session_started event
|
// processed for this session, don't add more participants
|
||||||
val currentStatus = repository.sessionStatus.value
|
// This is 100% reliable because the flag is set synchronously in session_started
|
||||||
if (currentStatus == SessionStatus.IN_PROGRESS || currentStatus == SessionStatus.COMPLETED) {
|
// handler before any async operations, and callbacks are processed sequentially
|
||||||
android.util.Log.d("MainViewModel", " Session already in progress/completed, ignoring participant_joined")
|
if (sessionStartedForSession == event.sessionId) {
|
||||||
|
android.util.Log.d("MainViewModel", " Session already started for ${event.sessionId}, ignoring participant_joined")
|
||||||
return@setSessionEventCallback
|
return@setSessionEventCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -548,6 +560,8 @@ class MainViewModel @Inject constructor(
|
||||||
_publicKey.value = null
|
_publicKey.value = null
|
||||||
_createdInviteCode.value = null
|
_createdInviteCode.value = null
|
||||||
_hasEnteredSession.value = false
|
_hasEnteredSession.value = false
|
||||||
|
// Reset synchronous flag for fresh session
|
||||||
|
sessionStartedForSession = null
|
||||||
// Reset session status to WAITING for fresh start
|
// Reset session status to WAITING for fresh start
|
||||||
repository.resetSessionStatus()
|
repository.resetSessionStatus()
|
||||||
}
|
}
|
||||||
|
|
@ -740,6 +754,8 @@ class MainViewModel @Inject constructor(
|
||||||
pendingJoinToken = ""
|
pendingJoinToken = ""
|
||||||
pendingPassword = ""
|
pendingPassword = ""
|
||||||
pendingJoinKeygenInfo = null
|
pendingJoinKeygenInfo = null
|
||||||
|
// Reset synchronous flag for fresh session
|
||||||
|
sessionStartedForSession = null
|
||||||
// Reset session status to WAITING for fresh start
|
// Reset session status to WAITING for fresh start
|
||||||
repository.resetSessionStatus()
|
repository.resetSessionStatus()
|
||||||
}
|
}
|
||||||
|
|
@ -925,6 +941,8 @@ class MainViewModel @Inject constructor(
|
||||||
pendingCoSignInviteCode = ""
|
pendingCoSignInviteCode = ""
|
||||||
pendingCoSignJoinToken = ""
|
pendingCoSignJoinToken = ""
|
||||||
pendingJoinSignInfo = null
|
pendingJoinSignInfo = null
|
||||||
|
// Reset synchronous flag for fresh session
|
||||||
|
sessionStartedForSession = null
|
||||||
// Reset session status to WAITING for fresh start
|
// Reset session status to WAITING for fresh start
|
||||||
repository.resetSessionStatus()
|
repository.resetSessionStatus()
|
||||||
}
|
}
|
||||||
|
|
@ -1671,6 +1689,8 @@ class MainViewModel @Inject constructor(
|
||||||
_signature.value = null
|
_signature.value = null
|
||||||
_txHash.value = null
|
_txHash.value = null
|
||||||
pendingSignInitiatorInfo = null
|
pendingSignInitiatorInfo = null
|
||||||
|
// Reset synchronous flag for fresh session
|
||||||
|
sessionStartedForSession = null
|
||||||
// Reset session status to WAITING for fresh start
|
// Reset session status to WAITING for fresh start
|
||||||
repository.resetSessionStatus()
|
repository.resetSessionStatus()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue