[Link new device] Improve UI transition between QRCodes.
This commit is contained in:
parent
a6f7c05458
commit
18bc6a27c4
4 changed files with 99 additions and 28 deletions
|
|
@ -22,6 +22,9 @@ import io.element.android.libraries.architecture.Presenter
|
|||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep
|
||||
import io.element.android.libraries.matrix.api.logs.LoggerTags
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
private val tag = LoggerTag("ShowQrCodePresenter", LoggerTags.linkNewDevice)
|
||||
|
|
@ -36,20 +39,54 @@ class ShowQrCodePresenter(
|
|||
fun create(initialData: String): ShowQrCodePresenter
|
||||
}
|
||||
|
||||
private var loadingJob: Job? = null
|
||||
|
||||
@Composable
|
||||
override fun present(): ShowQrCodeState {
|
||||
var qrCodeRotationCounter by remember { mutableIntStateOf(MAX_QR_CODE_ROTATION) }
|
||||
val data by produceState<AsyncData<String>>(AsyncData.Success(initialData)) {
|
||||
val state by produceState(
|
||||
initialValue = ShowQrCodeState(
|
||||
data1 = AsyncData.Success(initialData),
|
||||
data2 = AsyncData.Uninitialized,
|
||||
dataToRender = 1,
|
||||
)
|
||||
) {
|
||||
linkNewMobileHandler.stepFlow.collect { step ->
|
||||
val currentValue = value
|
||||
when (step) {
|
||||
is LinkMobileStep.QrReady -> {
|
||||
value = AsyncData.Success(step.data)
|
||||
loadingJob?.cancel()
|
||||
if (currentValue.dataToRender == 1) {
|
||||
value = currentValue.copy(
|
||||
data2 = AsyncData.Success(step.data),
|
||||
dataToRender = 2,
|
||||
)
|
||||
} else {
|
||||
value = currentValue.copy(
|
||||
data1 = AsyncData.Success(step.data),
|
||||
dataToRender = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
is LinkMobileStep.QrRotating -> {
|
||||
if (qrCodeRotationCounter-- > 0) {
|
||||
Timber.tag(tag.value).d("Rotating QrCode")
|
||||
linkNewMobileHandler.rotateQrCode()
|
||||
value = AsyncData.Loading()
|
||||
// Ensure that outdated data is not rendered too long while rotating QR code
|
||||
loadingJob = launch {
|
||||
delay(1000)
|
||||
if (currentValue.dataToRender == 1) {
|
||||
value = currentValue.copy(
|
||||
data2 = AsyncData.Loading(),
|
||||
dataToRender = 2,
|
||||
)
|
||||
} else {
|
||||
value = currentValue.copy(
|
||||
data1 = AsyncData.Loading(),
|
||||
dataToRender = 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.tag(tag.value).w("Max QR code rotation reached, not rotating anymore")
|
||||
linkNewMobileHandler.onTooManyRotation()
|
||||
|
|
@ -60,9 +97,7 @@ class ShowQrCodePresenter(
|
|||
}
|
||||
}
|
||||
|
||||
return ShowQrCodeState(
|
||||
data = data,
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -10,5 +10,7 @@ package io.element.android.features.linknewdevice.impl.screens.qrcode
|
|||
import io.element.android.libraries.architecture.AsyncData
|
||||
|
||||
data class ShowQrCodeState(
|
||||
val data: AsyncData<String>,
|
||||
val data1: AsyncData<String>,
|
||||
val data2: AsyncData<String>,
|
||||
val dataToRender: Int,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,14 +14,23 @@ class ShowQrCodeStateProvider : PreviewParameterProvider<ShowQrCodeState> {
|
|||
override val values: Sequence<ShowQrCodeState>
|
||||
get() = sequenceOf(
|
||||
aShowQrCodeState(),
|
||||
ShowQrCodeState(
|
||||
data = AsyncData.Loading(),
|
||||
aShowQrCodeState(
|
||||
data1 = AsyncData.Loading(),
|
||||
),
|
||||
aShowQrCodeState(
|
||||
data1 = AsyncData.Success("DATA"),
|
||||
data2 = AsyncData.Success("DATA2"),
|
||||
dataToRender = 2,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun aShowQrCodeState(
|
||||
data: AsyncData.Success<String> = AsyncData.Success("DATA"),
|
||||
data1: AsyncData<String> = AsyncData.Success("DATA"),
|
||||
data2: AsyncData<String> = AsyncData.Uninitialized,
|
||||
dataToRender: Int = 1,
|
||||
) = ShowQrCodeState(
|
||||
data = data,
|
||||
data1 = data1,
|
||||
data2 = data2,
|
||||
dataToRender = dataToRender,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
package io.element.android.features.linknewdevice.impl.screens.qrcode
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
|
@ -58,23 +61,15 @@ fun ShowQrCodeView(
|
|||
Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
when (val str = state.data.dataOrNull()) {
|
||||
null -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(220.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
QrCodeImage(
|
||||
data = str,
|
||||
modifier = Modifier
|
||||
.size(220.dp)
|
||||
)
|
||||
}
|
||||
Box {
|
||||
QrCodeOrLoading(
|
||||
isVisible = state.dataToRender == 1,
|
||||
data = state.data1.dataOrNull(),
|
||||
)
|
||||
QrCodeOrLoading(
|
||||
isVisible = state.dataToRender == 2,
|
||||
data = state.data2.dataOrNull(),
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
NumberedListOrganism(
|
||||
|
|
@ -95,6 +90,36 @@ fun ShowQrCodeView(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun QrCodeOrLoading(
|
||||
isVisible: Boolean,
|
||||
data: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
modifier = modifier,
|
||||
visible = isVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
if (data == null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(220.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
} else {
|
||||
QrCodeImage(
|
||||
data = data,
|
||||
modifier = Modifier
|
||||
.size(220.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun ShowQrCodeViewPreview(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue