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:
Benoit Marty
2024-01-23 18:55:02 +01:00
committed by GitHub
18 changed files with 83 additions and 50 deletions

View File

@@ -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

View File

@@ -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(

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)
}
}
}
}

View File

@@ -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(

View File

@@ -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()
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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()

View File

@@ -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
)

View File

@@ -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 = {}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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()
}
}
}

View File

@@ -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)
}
}
}