Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 0b23c20b authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #7292 from thunderbird/one_time_initialization

Add support for one-time (initialization) events
parents e86803c1 a1343b22
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ abstract class BaseViewModel<STATE, EVENT, EFFECT>(
    private val _effect = MutableSharedFlow<EFFECT>()
    override val effect: SharedFlow<EFFECT> = _effect.asSharedFlow()

    private val handledOneTimeEvents = mutableSetOf<EVENT>()

    /**
     * Updates the [STATE] of the ViewModel.
     *
@@ -54,4 +56,20 @@ abstract class BaseViewModel<STATE, EVENT, EFFECT>(
            _effect.emit(effect)
        }
    }

    /**
     * Ensures that one-time events are only handled once.
     *
     * When you can't ensure that an event is only sent once, but you want the event to only be handled once, call this
     * method. It will ensure [block] is only executed the first time this function is called. Subsequent calls with an
     * [event] argument equal to that of a previous invocation will not execute [block].
     *
     * Multiple one-time events are supported.
     */
    protected fun handleOneTimeEvent(event: EVENT, block: () -> Unit) {
        if (event !in handledOneTimeEvents) {
            handledOneTimeEvents.add(event)
            block()
        }
    }
}
+53 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@ import app.cash.turbine.test
import app.k9mail.core.ui.compose.testing.MainDispatcherRule
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@@ -47,10 +49,61 @@ class BaseViewModelTest {
        }
    }

    @Test
    fun `handleOneTimeEvent() should execute block`() = runTest {
        val viewModel = TestBaseViewModel()
        var eventHandled = false

        viewModel.callHandleOneTimeEvent(event = "event") {
            eventHandled = true
        }

        assertThat(eventHandled).isTrue()
    }

    @Test
    fun `handleOneTimeEvent() should execute block only once`() = runTest {
        val viewModel = TestBaseViewModel()
        var eventHandledCount = 0

        repeat(2) {
            viewModel.callHandleOneTimeEvent(event = "event") {
                eventHandledCount++
            }
        }

        assertThat(eventHandledCount).isEqualTo(1)
    }

    @Test
    fun `handleOneTimeEvent() should support multiple one-time events`() = runTest {
        val viewModel = TestBaseViewModel()
        var eventOneHandled = false
        var eventTwoHandled = false

        viewModel.callHandleOneTimeEvent(event = "eventOne") {
            eventOneHandled = true
        }

        assertThat(eventOneHandled).isTrue()
        assertThat(eventTwoHandled).isFalse()

        viewModel.callHandleOneTimeEvent(event = "eventTwo") {
            eventTwoHandled = true
        }

        assertThat(eventOneHandled).isTrue()
        assertThat(eventTwoHandled).isTrue()
    }

    private class TestBaseViewModel : BaseViewModel<String, String, String>("Initial state") {
        override fun event(event: String) {
            updateState { event }
            emitEffect(event)
        }

        fun callHandleOneTimeEvent(event: String, block: () -> Unit) {
            handleOneTimeEvent(event, block)
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ abstract class BaseSaveServerSettingsViewModel(

    override fun event(event: Event) {
        when (event) {
            Event.SaveServerSettings -> onSaveServerSettings()
            Event.SaveServerSettings -> handleOneTimeEvent(event, ::onSaveServerSettings)
            Event.OnNextClicked -> navigateNext()
            Event.OnBackClicked -> navigateBack()
        }
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ open class IncomingServerSettingsViewModel(
    @Suppress("CyclomaticComplexMethod")
    override fun event(event: Event) {
        when (event) {
            Event.LoadAccountState -> loadAccountState()
            Event.LoadAccountState -> handleOneTimeEvent(event, ::loadAccountState)

            is Event.ProtocolTypeChanged -> updateProtocolType(event.protocolType)
            is Event.ServerChanged -> updateState { it.copy(server = it.server.updateValue(event.server)) }
+1 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ open class OutgoingServerSettingsViewModel(

    override fun event(event: Event) {
        when (event) {
            Event.LoadAccountState -> loadAccountState()
            Event.LoadAccountState -> handleOneTimeEvent(event, ::loadAccountState)

            is Event.ServerChanged -> updateState { it.copy(server = it.server.updateValue(event.server)) }
            is Event.SecurityChanged -> updateSecurity(event.security)
Loading