mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 21:53:43 +00:00
Fix Qr Code errors
This commit is contained in:
parent
db15fe0840
commit
27fda9fd46
@ -44,7 +44,7 @@ private val TITLES = listOf(R.string.enter_account_id, R.string.qrScan)
|
|||||||
@Composable
|
@Composable
|
||||||
internal fun NewMessage(
|
internal fun NewMessage(
|
||||||
state: State,
|
state: State,
|
||||||
errors: Flow<String> = emptyFlow(),
|
qrErrors: Flow<String> = emptyFlow(),
|
||||||
callbacks: Callbacks = object: Callbacks {},
|
callbacks: Callbacks = object: Callbacks {},
|
||||||
onClose: () -> Unit = {},
|
onClose: () -> Unit = {},
|
||||||
onBack: () -> Unit = {},
|
onBack: () -> Unit = {},
|
||||||
@ -58,7 +58,7 @@ internal fun NewMessage(
|
|||||||
HorizontalPager(pagerState) {
|
HorizontalPager(pagerState) {
|
||||||
when (TITLES[it]) {
|
when (TITLES[it]) {
|
||||||
R.string.enter_account_id -> EnterAccountId(state, callbacks, onHelp)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.TimeoutCancellationException
|
import kotlinx.coroutines.TimeoutCancellationException
|
||||||
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
@ -34,7 +35,7 @@ internal class NewMessageViewModel @Inject constructor(
|
|||||||
private val _success = MutableSharedFlow<Success>()
|
private val _success = MutableSharedFlow<Success>()
|
||||||
val success get() = _success.asSharedFlow()
|
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()
|
val qrErrors = _qrErrors.asSharedFlow()
|
||||||
|
|
||||||
private var loadOnsJob: Job? = null
|
private var loadOnsJob: Job? = null
|
||||||
|
@ -4,10 +4,13 @@ import android.app.Application
|
|||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -36,7 +39,7 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
private val _events = MutableSharedFlow<LoadAccountEvent>()
|
private val _events = MutableSharedFlow<LoadAccountEvent>()
|
||||||
val events = _events.asSharedFlow()
|
val events = _events.asSharedFlow()
|
||||||
|
|
||||||
private val _qrErrors = MutableSharedFlow<Throwable>()
|
private val _qrErrors = MutableSharedFlow<Throwable>(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||||
val qrErrors = _qrErrors.asSharedFlow()
|
val qrErrors = _qrErrors.asSharedFlow()
|
||||||
.mapNotNull { application.getString(R.string.qrNotRecoveryPassword) }
|
.mapNotNull { application.getString(R.string.qrNotRecoveryPassword) }
|
||||||
|
|
||||||
@ -57,7 +60,7 @@ internal class LinkDeviceViewModel @Inject constructor(
|
|||||||
try {
|
try {
|
||||||
decode(string).let(::onSuccess)
|
decode(string).let(::onSuccess)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
onFailure(e)
|
onQrCodeScanFailure(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
@ -38,7 +39,7 @@ private val TITLES = listOf(R.string.view, R.string.scan)
|
|||||||
|
|
||||||
class QRCodeActivity : PassphraseRequiredActionBarActivity() {
|
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) {
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||||
super.onCreate(savedInstanceState, isReady)
|
super.onCreate(savedInstanceState, isReady)
|
||||||
|
@ -31,6 +31,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
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.BarcodeScanning
|
||||||
import com.google.mlkit.vision.barcode.common.Barcode
|
import com.google.mlkit.vision.barcode.common.Barcode
|
||||||
import com.google.mlkit.vision.common.InputImage
|
import com.google.mlkit.vision.common.InputImage
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.buffer
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.flow.filter
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.ui.LocalDimensions
|
import org.thoughtcrime.securesms.ui.LocalDimensions
|
||||||
import org.thoughtcrime.securesms.ui.color.LocalColors
|
|
||||||
import org.thoughtcrime.securesms.ui.base
|
import org.thoughtcrime.securesms.ui.base
|
||||||
|
import org.thoughtcrime.securesms.ui.color.LocalColors
|
||||||
import org.thoughtcrime.securesms.ui.xl
|
import org.thoughtcrime.securesms.ui.xl
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
@ -161,11 +160,24 @@ fun ScanQrCode(errors: Flow<String>, onScan: (String) -> Unit) {
|
|||||||
|
|
||||||
val scaffoldState = rememberScaffoldState()
|
val scaffoldState = rememberScaffoldState()
|
||||||
|
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
errors.filter { scaffoldState.snackbarHostState.currentSnackbarData == null }
|
errors.collect { error ->
|
||||||
.buffer(0, BufferOverflow.DROP_OLDEST)
|
scaffoldState.snackbarHostState
|
||||||
.collect { error ->
|
.takeIf { it.currentSnackbarData == null }
|
||||||
scaffoldState.snackbarHostState.showSnackbar(message = error)
|
?.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user