Merge pull request #2264 from element-hq/renovate/io.nlopez.compose.rules-detekt-0.x
Update dependency io.nlopez.compose.rules:detekt to v0.3.10
This commit is contained in:
@@ -60,7 +60,7 @@ allprojects {
|
||||
config.from(files("$rootDir/tools/detekt/detekt.yml"))
|
||||
}
|
||||
dependencies {
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.3.9")
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.3.10")
|
||||
}
|
||||
|
||||
// KtLint
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.features.ftue.impl.migration
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.ftue.impl.R
|
||||
@@ -32,8 +34,9 @@ fun MigrationScreenView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (migrationState.isMigrating.not()) {
|
||||
val latestOnMigrationFinished by rememberUpdatedState(onMigrationFinished)
|
||||
LaunchedEffect(Unit) {
|
||||
onMigrationFinished()
|
||||
latestOnMigrationFinished()
|
||||
}
|
||||
}
|
||||
SunsetPage(
|
||||
|
||||
@@ -28,6 +28,8 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
@@ -57,8 +59,9 @@ fun InviteListView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (state.acceptedAction is AsyncData.Success) {
|
||||
val latestOnInviteAccepted by rememberUpdatedState(onInviteAccepted)
|
||||
LaunchedEffect(state.acceptedAction) {
|
||||
onInviteAccepted(state.acceptedAction.data)
|
||||
latestOnInviteAccepted(state.acceptedAction.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.features.lockscreen.impl.unlock
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import io.element.android.features.lockscreen.impl.biometric.BiometricUnlockManager
|
||||
import io.element.android.features.lockscreen.impl.biometric.DefaultBiometricUnlockCallback
|
||||
import io.element.android.features.lockscreen.impl.pin.DefaultPinCodeManagerCallback
|
||||
@@ -30,15 +32,16 @@ class PinUnlockHelper @Inject constructor(
|
||||
) {
|
||||
@Composable
|
||||
fun OnUnlockEffect(onUnlock: () -> Unit) {
|
||||
val latestOnUnlock by rememberUpdatedState(onUnlock)
|
||||
DisposableEffect(Unit) {
|
||||
val biometricUnlockCallback = object : DefaultBiometricUnlockCallback() {
|
||||
override fun onBiometricUnlockSuccess() {
|
||||
onUnlock()
|
||||
latestOnUnlock()
|
||||
}
|
||||
}
|
||||
val pinCodeVerifiedCallback = object : DefaultPinCodeManagerCallback() {
|
||||
override fun onPinCodeVerified() {
|
||||
onUnlock()
|
||||
latestOnUnlock()
|
||||
}
|
||||
}
|
||||
biometricUnlockManager.addCallback(biometricUnlockCallback)
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.features.login.impl.changeserver
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.login.impl.dialogs.SlidingSyncNotSupportedDialog
|
||||
@@ -63,8 +65,11 @@ fun ChangeServerView(
|
||||
}
|
||||
}
|
||||
is AsyncData.Loading -> ProgressDialog()
|
||||
is AsyncData.Success -> LaunchedEffect(state.changeServerAction) {
|
||||
onDone()
|
||||
is AsyncData.Success -> {
|
||||
val latestOnDone by rememberUpdatedState(onDone)
|
||||
LaunchedEffect(state.changeServerAction) {
|
||||
latestOnDone()
|
||||
}
|
||||
}
|
||||
AsyncData.Uninitialized -> Unit
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.features.logout.impl.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.features.logout.impl.R
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
@@ -52,9 +54,11 @@ fun LogoutActionDialog(
|
||||
onRetry = onForceLogoutClicked,
|
||||
onDismiss = onDismissError,
|
||||
)
|
||||
is AsyncAction.Success ->
|
||||
is AsyncAction.Success -> {
|
||||
val latestOnSuccessLogout by rememberUpdatedState(onSuccessLogout)
|
||||
LaunchedEffect(state) {
|
||||
onSuccessLogout(state.data)
|
||||
latestOnSuccessLogout(state.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,10 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
@@ -294,8 +296,11 @@ private fun AttachmentStateView(
|
||||
) {
|
||||
when (state) {
|
||||
AttachmentsState.None -> Unit
|
||||
is AttachmentsState.Previewing -> LaunchedEffect(state) {
|
||||
onPreviewAttachments(state.attachments)
|
||||
is AttachmentsState.Previewing -> {
|
||||
val latestOnPreviewAttachments by rememberUpdatedState(onPreviewAttachments)
|
||||
LaunchedEffect(state) {
|
||||
latestOnPreviewAttachments(state.attachments)
|
||||
}
|
||||
}
|
||||
is AttachmentsState.Sending -> {
|
||||
ProgressDialog(
|
||||
|
||||
@@ -24,6 +24,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -57,8 +59,9 @@ fun AttachmentsPreviewView(
|
||||
}
|
||||
|
||||
if (state.sendActionState is SendActionState.Done) {
|
||||
val latestOnDismiss by rememberUpdatedState(onDismiss)
|
||||
LaunchedEffect(state.sendActionState) {
|
||||
onDismiss()
|
||||
latestOnDismiss()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
@@ -193,10 +194,11 @@ private fun BoxScope.TimelineScrollHelper(
|
||||
}
|
||||
}
|
||||
|
||||
val latestOnScrollFinishedAt by rememberUpdatedState(onScrollFinishedAt)
|
||||
LaunchedEffect(isScrollFinished, isTimelineEmpty) {
|
||||
if (isScrollFinished && !isTimelineEmpty) {
|
||||
// Notify the parent composable about the first visible item index when scrolling finishes
|
||||
onScrollFinishedAt(lazyListState.firstVisibleItemIndex)
|
||||
latestOnScrollFinishedAt(lazyListState.firstVisibleItemIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.features.rageshake.api.detection
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -73,9 +75,10 @@ private fun TakeScreenshot(
|
||||
onScreenshotTaken: (ImageResult) -> Unit
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val latestOnScreenshotTaken by rememberUpdatedState(onScreenshotTaken)
|
||||
LaunchedEffect(Unit) {
|
||||
view.screenshot {
|
||||
onScreenshotTaken(it)
|
||||
latestOnScreenshotTaken(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import io.element.android.features.securebackup.impl.loggerTagDisable
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
@@ -36,14 +36,14 @@ class SecureBackupEnablePresenter @Inject constructor(
|
||||
) : Presenter<SecureBackupEnableState> {
|
||||
@Composable
|
||||
override fun present(): SecureBackupEnableState {
|
||||
val enableAction = remember { mutableStateOf<AsyncData<Unit>>(AsyncData.Uninitialized) }
|
||||
val enableAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
fun handleEvents(event: SecureBackupEnableEvents) {
|
||||
when (event) {
|
||||
is SecureBackupEnableEvents.EnableBackup ->
|
||||
coroutineScope.enableBackup(enableAction)
|
||||
SecureBackupEnableEvents.DismissDialog -> {
|
||||
enableAction.value = AsyncData.Uninitialized
|
||||
enableAction.value = AsyncAction.Uninitialized
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class SecureBackupEnablePresenter @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.enableBackup(action: MutableState<AsyncData<Unit>>) = launch {
|
||||
private fun CoroutineScope.enableBackup(action: MutableState<AsyncAction<Unit>>) = launch {
|
||||
suspend {
|
||||
Timber.tag(loggerTagDisable.value).d("Calling encryptionService.enableBackups()")
|
||||
encryptionService.enableBackups().getOrThrow()
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package io.element.android.features.securebackup.impl.enable
|
||||
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
|
||||
data class SecureBackupEnableState(
|
||||
val enableAction: AsyncData<Unit>,
|
||||
val enableAction: AsyncAction<Unit>,
|
||||
val eventSink: (SecureBackupEnableEvents) -> Unit
|
||||
)
|
||||
|
||||
@@ -17,20 +17,20 @@
|
||||
package io.element.android.features.securebackup.impl.enable
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
|
||||
open class SecureBackupEnableStateProvider : PreviewParameterProvider<SecureBackupEnableState> {
|
||||
override val values: Sequence<SecureBackupEnableState>
|
||||
get() = sequenceOf(
|
||||
aSecureBackupEnableState(),
|
||||
aSecureBackupEnableState(enableAction = AsyncData.Loading()),
|
||||
aSecureBackupEnableState(enableAction = AsyncData.Failure(Exception("Failed to enable"))),
|
||||
aSecureBackupEnableState(enableAction = AsyncAction.Loading),
|
||||
aSecureBackupEnableState(enableAction = AsyncAction.Failure(Exception("Failed to enable"))),
|
||||
// Add other states here
|
||||
)
|
||||
}
|
||||
|
||||
fun aSecureBackupEnableState(
|
||||
enableAction: AsyncData<Unit> = AsyncData.Uninitialized,
|
||||
enableAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||
) = SecureBackupEnableState(
|
||||
enableAction = enableAction,
|
||||
eventSink = {}
|
||||
|
||||
@@ -19,16 +19,14 @@ package io.element.android.features.securebackup.impl.enable
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.features.securebackup.impl.R
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
@@ -41,11 +39,6 @@ fun SecureBackupEnableView(
|
||||
onBackClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LaunchedEffect(state.enableAction) {
|
||||
if (state.enableAction is AsyncData.Success) {
|
||||
onDone()
|
||||
}
|
||||
}
|
||||
FlowStepPage(
|
||||
modifier = modifier,
|
||||
onBackClicked = onBackClicked,
|
||||
@@ -53,12 +46,12 @@ fun SecureBackupEnableView(
|
||||
iconVector = ImageVector.vectorResource(CommonDrawables.ic_key),
|
||||
buttons = { Buttons(state = state) }
|
||||
)
|
||||
if (state.enableAction is AsyncData.Failure) {
|
||||
ErrorDialog(
|
||||
content = state.enableAction.error.let { it.message ?: it.toString() },
|
||||
onDismiss = { state.eventSink.invoke(SecureBackupEnableEvents.DismissDialog) },
|
||||
)
|
||||
}
|
||||
AsyncActionView(
|
||||
async = state.enableAction,
|
||||
progressDialog = { },
|
||||
onSuccess = { onDone() },
|
||||
onErrorDismiss = { state.eventSink.invoke(SecureBackupEnableEvents.DismissDialog) }
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -20,7 +20,7 @@ import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
@@ -40,7 +40,7 @@ class SecureBackupEnablePresenterTest {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.enableAction).isEqualTo(AsyncData.Uninitialized)
|
||||
assertThat(initialState.enableAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +53,9 @@ class SecureBackupEnablePresenterTest {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(SecureBackupEnableEvents.EnableBackup)
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.enableAction).isInstanceOf(AsyncData.Loading::class.java)
|
||||
assertThat(loadingState.enableAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.enableAction).isEqualTo(AsyncData.Success(Unit))
|
||||
assertThat(finalState.enableAction).isEqualTo(AsyncAction.Success(Unit))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,12 +70,12 @@ class SecureBackupEnablePresenterTest {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(SecureBackupEnableEvents.EnableBackup)
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.enableAction).isInstanceOf(AsyncData.Loading::class.java)
|
||||
assertThat(loadingState.enableAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.enableAction).isEqualTo(AsyncData.Failure<Unit>(AN_EXCEPTION))
|
||||
assertThat(errorState.enableAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
errorState.eventSink(SecureBackupEnableEvents.DismissDialog)
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.enableAction).isEqualTo(AsyncData.Uninitialized)
|
||||
assertThat(finalState.enableAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.libraries.designsystem.components.async
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.designsystem.components.ProgressDialog
|
||||
@@ -67,8 +69,9 @@ fun <T> AsyncActionView(
|
||||
}
|
||||
}
|
||||
is AsyncAction.Success -> {
|
||||
val latestOnSuccess by rememberUpdatedState(onSuccess)
|
||||
LaunchedEffect(async) {
|
||||
onSuccess(async.data)
|
||||
latestOnSuccess(async.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package io.element.android.libraries.textcomposer
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import io.element.android.libraries.androidutils.ui.awaitWindowFocus
|
||||
@@ -40,8 +42,10 @@ internal fun <T> SoftKeyboardEffect(
|
||||
predicate: (T) -> Boolean,
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val latestOnRequestFocus by rememberUpdatedState(onRequestFocus)
|
||||
val latestPredicate by rememberUpdatedState(predicate)
|
||||
LaunchedEffect(key) {
|
||||
if (predicate(key)) {
|
||||
if (latestPredicate(key)) {
|
||||
// Await window focus in case returning from a dialog
|
||||
view.awaitWindowFocus()
|
||||
|
||||
@@ -49,7 +53,7 @@ internal fun <T> SoftKeyboardEffect(
|
||||
view.showKeyboard(andRequestFocus = true)
|
||||
|
||||
// Refocus to the correct view
|
||||
onRequestFocus()
|
||||
latestOnRequestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@@ -274,12 +275,13 @@ fun TextComposer(
|
||||
}
|
||||
|
||||
val menuAction = state.menuAction
|
||||
val latestOnSuggestionReceived by rememberUpdatedState(onSuggestionReceived)
|
||||
LaunchedEffect(menuAction) {
|
||||
if (menuAction is MenuAction.Suggestion) {
|
||||
val suggestion = Suggestion(menuAction.suggestionPattern)
|
||||
onSuggestionReceived(suggestion)
|
||||
latestOnSuggestionReceived(suggestion)
|
||||
} else {
|
||||
onSuggestionReceived(null)
|
||||
latestOnSuggestionReceived(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user