Use EventSink lambda in state instead of Flow in Presenter

This commit is contained in:
ganfra 2023-01-11 15:53:52 +01:00
parent e56ba5e315
commit ad7bf21f6d
43 changed files with 277 additions and 490 deletions

View file

@ -25,8 +25,8 @@ import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import io.element.android.x.architecture.createNode
import io.element.android.x.architecture.presenterConnector
import io.element.android.x.core.compose.OnLifecycleEvent
import io.element.android.x.core.di.DaggerComponentOwner
import io.element.android.x.core.screenshot.ImageResult
import io.element.android.x.di.SessionComponentsOwner
import io.element.android.x.features.rageshake.bugreport.BugReportNode
import io.element.android.x.matrix.Matrix
@ -77,22 +77,6 @@ class RootFlowNode(
private val presenterConnector = presenterConnector(rootPresenter)
init {
Timber.v("Init")
lifecycle.subscribe(
onCreate = { Timber.v("OnCreate") },
onResume = {
Timber.v("OnResume")
presenterConnector.emitEvent(RootEvents.StartRageshakeDetection)
},
onPause = {
Timber.v("OnPause")
presenterConnector.emitEvent(RootEvents.StopRageshakeDetection)
},
onDestroy = { Timber.v("OnDestroy") }
)
}
init {
matrix.isLoggedIn()
.distinctUntilChanged()
@ -114,47 +98,21 @@ class RootFlowNode(
.launchIn(lifecycleScope)
}
private fun hideShowkaseButton() {
presenterConnector.emitEvent(RootEvents.HideShowkaseButton)
}
private fun onOpenBugReport() {
presenterConnector.emitEvent(RootEvents.ResetAppHasCrashed)
backstack.push(NavTarget.BugReport)
}
private fun onCrashDetectedDismissed() {
presenterConnector.emitEvent(RootEvents.ResetAllCrashData)
}
private fun onDismissRageshake() {
presenterConnector.emitEvent(RootEvents.DismissRageshake)
}
private fun onDisableRageshake() {
presenterConnector.emitEvent(RootEvents.DisableRageshake)
}
@Composable
override fun View(modifier: Modifier) {
val state by presenterConnector.stateFlow.collectAsState()
RootView(
state = state,
onHideShowkaseClicked = this::hideShowkaseButton,
onOpenBugReport = this::onOpenBugReport,
onCrashDetectedDismissed = this::onCrashDetectedDismissed,
onDisableRageshake = this::onDisableRageshake,
onDismissRageshake = this::onDismissRageshake,
onScreenshotTaken = this::onScreenshotTaken
) {
Children(navModel = backstack)
}
}
private fun onScreenshotTaken(imageResult: ImageResult) {
presenterConnector.emitEvent(RootEvents.ProcessScreenshot(imageResult))
}
private val bugReportNodeCallback = object : BugReportNode.Callback {
override fun onBugReportSent() {
backstack.pop()

View file

@ -1,14 +1,5 @@
package io.element.android.x.root
import io.element.android.x.core.screenshot.ImageResult
sealed interface RootEvents {
data class ProcessScreenshot(val imageResult: ImageResult) : RootEvents
object HideShowkaseButton: RootEvents
object ResetAllCrashData : RootEvents
object ResetAppHasCrashed: RootEvents
object DisableRageshake: RootEvents
object DismissRageshake: RootEvents
object StartRageshakeDetection: RootEvents
object StopRageshakeDetection: RootEvents
object HideShowkaseButton : RootEvents
}

View file

@ -1,62 +1,45 @@
package io.element.android.x.root
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import io.element.android.x.architecture.Presenter
import io.element.android.x.architecture.SharedFlowHolder
import io.element.android.x.features.rageshake.bugreport.BugReportEvents
import io.element.android.x.features.rageshake.bugreport.BugReportPresenter
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionEvents
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionPresenter
import io.element.android.x.features.rageshake.detection.RageshakeDetectionEvents
import io.element.android.x.features.rageshake.detection.RageshakeDetectionPresenter
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class RootPresenter @Inject constructor(
private val bugReportPresenter: BugReportPresenter,
private val crashDetectionPresenter: CrashDetectionPresenter,
private val rageshakeDetectionPresenter: RageshakeDetectionPresenter,
) : Presenter<RootState, RootEvents> {
private val rageshakeDetectionEventsFlow = SharedFlowHolder<RageshakeDetectionEvents>()
private val bugReporterEventsFlow = SharedFlowHolder<BugReportEvents>()
private val crashDetectionEventsFlow = SharedFlowHolder<CrashDetectionEvents>()
) : Presenter<RootState> {
@Composable
override fun present(events: Flow<RootEvents>): RootState {
override fun present(): RootState {
val isBugReportVisible = rememberSaveable {
mutableStateOf(false)
}
val isShowkaseButtonVisible = rememberSaveable {
mutableStateOf(true)
}
val rageshakeDetectionState = rageshakeDetectionPresenter.present(events = rageshakeDetectionEventsFlow.asSharedFlow())
val crashDetectionState = crashDetectionPresenter.present(events = crashDetectionEventsFlow.asSharedFlow())
val bugReportState = bugReportPresenter.present(events = bugReporterEventsFlow.asSharedFlow())
val rageshakeDetectionState = rageshakeDetectionPresenter.present()
val crashDetectionState = crashDetectionPresenter.present()
val bugReportState = bugReportPresenter.present()
LaunchedEffect(Unit) {
events.collect { event ->
when (event) {
RootEvents.HideShowkaseButton -> isShowkaseButtonVisible.value = false
RootEvents.ResetAllCrashData -> crashDetectionEventsFlow.emit(CrashDetectionEvents.ResetAllCrashData)
RootEvents.ResetAppHasCrashed -> crashDetectionEventsFlow.emit(CrashDetectionEvents.ResetAppHasCrashed)
RootEvents.DisableRageshake -> rageshakeDetectionEventsFlow.emit(RageshakeDetectionEvents.Disable)
RootEvents.DismissRageshake -> rageshakeDetectionEventsFlow.emit(RageshakeDetectionEvents.Dismiss)
RootEvents.StartRageshakeDetection -> rageshakeDetectionEventsFlow.emit(RageshakeDetectionEvents.StartDetection)
RootEvents.StopRageshakeDetection -> rageshakeDetectionEventsFlow.emit(RageshakeDetectionEvents.StopDetection)
is RootEvents.ProcessScreenshot -> rageshakeDetectionEventsFlow.emit(RageshakeDetectionEvents.ProcessScreenshot(event.imageResult))
}
fun handleEvent(event: RootEvents) {
when (event) {
RootEvents.HideShowkaseButton -> isShowkaseButtonVisible.value = false
}
}
return RootState(
isBugReportVisible = isBugReportVisible.value,
isShowkaseButtonVisible = isShowkaseButtonVisible.value,
rageshakeDetectionState = rageshakeDetectionState,
crashDetectionState = crashDetectionState,
bugReportState = bugReportState
bugReportState = bugReportState,
eventSink = ::handleEvent
)
}
}

View file

@ -11,5 +11,6 @@ data class RootState(
val isShowkaseButtonVisible: Boolean,
val rageshakeDetectionState: RageshakeDetectionState,
val crashDetectionState: CrashDetectionState,
val bugReportState: BugReportState
val bugReportState: BugReportState,
val eventSink: (RootEvents) -> Unit
)

View file

@ -10,8 +10,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
import com.airbnb.android.showkase.models.Showkase
import io.element.android.x.component.ShowkaseButton
import io.element.android.x.core.screenshot.ImageResult
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionEvents
import io.element.android.x.features.rageshake.crash.ui.CrashDetectionView
import io.element.android.x.features.rageshake.detection.RageshakeDetectionEvents
import io.element.android.x.features.rageshake.detection.RageshakeDetectionView
import io.element.android.x.getBrowserIntent
@ -19,12 +20,7 @@ import io.element.android.x.getBrowserIntent
fun RootView(
state: RootState,
modifier: Modifier = Modifier,
onHideShowkaseClicked: () -> Unit = { },
onOpenBugReport: () -> Unit = {},
onCrashDetectedDismissed: () -> Unit = {},
onDisableRageshake: () -> Unit = {},
onDismissRageshake: () -> Unit = {},
onScreenshotTaken: (ImageResult) -> Unit = {},
children: @Composable BoxScope.() -> Unit,
) {
Box(
@ -33,23 +29,27 @@ fun RootView(
contentAlignment = Alignment.TopCenter,
) {
children()
val eventSink = state.eventSink
val context = LocalContext.current
fun onOpenBugReport() {
state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed)
state.rageshakeDetectionState.eventSink(RageshakeDetectionEvents.Dismiss)
onOpenBugReport.invoke()
}
ShowkaseButton(
isVisible = state.isShowkaseButtonVisible,
onCloseClicked = onHideShowkaseClicked,
onCloseClicked = { eventSink(RootEvents.HideShowkaseButton) },
onClick = { ContextCompat.startActivity(context, Showkase.getBrowserIntent(context), null) }
)
RageshakeDetectionView(
state = state.rageshakeDetectionState,
onOpenBugReport = onOpenBugReport,
onDisableClicked = onDisableRageshake,
onNoClicked = onDismissRageshake,
onScreenshotTaken = onScreenshotTaken
onOpenBugReport = ::onOpenBugReport,
)
CrashDetectionView(
state = state.crashDetectionState,
onOpenBugReport = onOpenBugReport,
onPopupDismissed = onCrashDetectedDismissed
onOpenBugReport = ::onOpenBugReport,
)
}
}