Fix Qr Code errors

This commit is contained in:
Andrew 2024-06-25 23:21:22 +09:30
parent db15fe0840
commit 27fda9fd46
5 changed files with 32 additions and 15 deletions

View File

@ -44,7 +44,7 @@ private val TITLES = listOf(R.string.enter_account_id, R.string.qrScan)
@Composable
internal fun NewMessage(
state: State,
errors: Flow<String> = emptyFlow(),
qrErrors: Flow<String> = emptyFlow(),
callbacks: Callbacks = object: Callbacks {},
onClose: () -> Unit = {},
onBack: () -> Unit = {},
@ -58,7 +58,7 @@ internal fun NewMessage(
HorizontalPager(pagerState) {
when (TITLES[it]) {
R.string.enter_account_id -> EnterAccountId(state, callbacks, onHelp)
R.string.qrScan -> MaybeScanQrCode(errors, onScan = callbacks::onScanQrCode)
R.string.qrScan -> MaybeScanQrCode(qrErrors, onScan = callbacks::onScanQrCode)
}
}
}

View File

@ -7,6 +7,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
@ -34,7 +35,7 @@ internal class NewMessageViewModel @Inject constructor(
private val _success = MutableSharedFlow<Success>()
val success get() = _success.asSharedFlow()
private val _qrErrors = MutableSharedFlow<String>()
private val _qrErrors = MutableSharedFlow<String>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
val qrErrors = _qrErrors.asSharedFlow()
private var loadOnsJob: Job? = null

View File

@ -4,10 +4,13 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@ -36,7 +39,7 @@ internal class LinkDeviceViewModel @Inject constructor(
private val _events = MutableSharedFlow<LoadAccountEvent>()
val events = _events.asSharedFlow()
private val _qrErrors = MutableSharedFlow<Throwable>()
private val _qrErrors = MutableSharedFlow<Throwable>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
val qrErrors = _qrErrors.asSharedFlow()
.mapNotNull { application.getString(R.string.qrNotRecoveryPassword) }
@ -57,7 +60,7 @@ internal class LinkDeviceViewModel @Inject constructor(
try {
decode(string).let(::onSuccess)
} catch (e: Exception) {
onFailure(e)
onQrCodeScanFailure(e)
}
}
}

View File

@ -13,6 +13,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
@ -38,7 +39,7 @@ private val TITLES = listOf(R.string.view, R.string.scan)
class QRCodeActivity : PassphraseRequiredActionBarActivity() {
private val errors = MutableSharedFlow<String>()
private val errors = MutableSharedFlow<String>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
super.onCreate(savedInstanceState, isReady)

View File

@ -31,6 +31,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -51,15 +52,13 @@ import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import network.loki.messenger.R
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ui.LocalDimensions
import org.thoughtcrime.securesms.ui.color.LocalColors
import org.thoughtcrime.securesms.ui.base
import org.thoughtcrime.securesms.ui.color.LocalColors
import org.thoughtcrime.securesms.ui.xl
import java.util.concurrent.Executors
@ -161,12 +160,25 @@ fun ScanQrCode(errors: Flow<String>, onScan: (String) -> Unit) {
val scaffoldState = rememberScaffoldState()
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
errors.filter { scaffoldState.snackbarHostState.currentSnackbarData == null }
.buffer(0, BufferOverflow.DROP_OLDEST)
.collect { error ->
scaffoldState.snackbarHostState.showSnackbar(message = error)
}
errors.collect { error ->
scaffoldState.snackbarHostState
.takeIf { it.currentSnackbarData == null }
?.run {
scope.launch {
// showSnackbar() suspends until the Snackbar is dismissed.
// Launch in new scope so we drop new QR scan events, to prevent spamming
// snackbars to the user, or worse, queuing a chain of snackbars one after
// another to show and hide for the next minute or 2.
// Don't use debounce() because many QR scans can come through each second,
// and each scan could restart the timer which could mean no scan gets
// through until the user stops scanning; quite perplexing.
showSnackbar(message = error)
}
}
}
}
Scaffold(