From bb7e8603dc88115ccad52e5fadf774a1b4281df7 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 28 Nov 2022 18:57:50 +0000 Subject: [PATCH 1/3] Make use of extract state modules --- build.gradle | 7 +- .../app/dapk/st/design/components/Spider.kt | 64 ------ domains/android/compose-core/build.gradle | 1 - .../app/dapk/st/core/ActivityExtensions.kt | 50 ----- .../kotlin/app/dapk/st/core/StateViewModel.kt | 48 ----- .../app/dapk/st/core/page/PageReducer.kt | 95 --------- domains/state/build.gradle | 14 -- .../src/main/kotlin/app/dapk/state/State.kt | 194 ------------------ .../kotlin/fake/FakeEventSource.kt | 20 -- .../testFixtures/kotlin/test/ReducerTest.kt | 153 -------------- features/directory/build.gradle | 4 +- .../app/dapk/st/directory/DirectoryModule.kt | 2 +- .../dapk/st/directory/state/DirectoryState.kt | 2 +- features/home/build.gradle | 2 +- .../kotlin/app/dapk/st/home/MainActivity.kt | 2 +- features/messenger/build.gradle | 4 +- .../dapk/st/messenger/MessengerActivity.kt | 12 +- .../app/dapk/st/messenger/MessengerModule.kt | 2 +- .../messenger/gallery/ImageGalleryActivity.kt | 9 +- .../messenger/gallery/ImageGalleryModule.kt | 2 +- .../messenger/gallery/ImageGalleryScreen.kt | 7 +- .../gallery/state/ImageGalleryReducer.kt | 10 +- .../gallery/state/ImageGalleryState.kt | 6 +- .../dapk/st/messenger/state/MessengerState.kt | 2 +- .../gallery/state/ImageGalleryReducerTest.kt | 9 +- features/profile/build.gradle | 4 +- .../app/dapk/st/profile/ProfileModule.kt | 2 +- .../app/dapk/st/profile/ProfileScreen.kt | 5 +- .../dapk/st/profile/state/ProfileReducer.kt | 10 +- .../app/dapk/st/profile/state/ProfileState.kt | 6 +- .../st/profile/state/ProfileReducerTest.kt | 8 +- features/settings/build.gradle | 3 +- .../app/dapk/st/settings/SettingsActivity.kt | 8 +- .../app/dapk/st/settings/SettingsModule.kt | 1 + .../app/dapk/st/settings/SettingsScreen.kt | 5 +- .../app/dapk/st/settings/SettingsState.kt | 10 +- .../dapk/st/settings/state/SettingsReducer.kt | 10 +- .../dapk/st/settings/SettingsReducerTest.kt | 8 +- .../kotlin/internalfixture/PageFixture.kt | 2 +- settings.gradle | 3 + 40 files changed, 91 insertions(+), 715 deletions(-) delete mode 100644 design-library/src/main/kotlin/app/dapk/st/design/components/Spider.kt delete mode 100644 domains/android/compose-core/src/main/kotlin/app/dapk/st/core/StateViewModel.kt delete mode 100644 domains/android/compose-core/src/main/kotlin/app/dapk/st/core/page/PageReducer.kt delete mode 100644 domains/state/build.gradle delete mode 100644 domains/state/src/main/kotlin/app/dapk/state/State.kt delete mode 100644 domains/state/src/testFixtures/kotlin/fake/FakeEventSource.kt delete mode 100644 domains/state/src/testFixtures/kotlin/test/ReducerTest.kt diff --git a/build.gradle b/build.gradle index 997f289..e1c1e9b 100644 --- a/build.gradle +++ b/build.gradle @@ -151,6 +151,12 @@ ext.androidImportFixturesWorkaround = { project, fixtures -> project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar") } +ext.androidImportCompositeFixturesWorkaround = { project, fixtures -> + project.dependencies.testImplementation(project.dependencies.testFixtures(fixtures)) + project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}-test-fixtures.jar") + project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar") +} + ext.isFoss = { return rootProject.hasProperty("foss") } @@ -163,7 +169,6 @@ ext.firebase = { dependencies, name -> } } - if (launchTask.contains("codeCoverageReport".toLowerCase())) { apply from: 'tools/coverage.gradle' } diff --git a/design-library/src/main/kotlin/app/dapk/st/design/components/Spider.kt b/design-library/src/main/kotlin/app/dapk/st/design/components/Spider.kt deleted file mode 100644 index 8d28d8c..0000000 --- a/design-library/src/main/kotlin/app/dapk/st/design/components/Spider.kt +++ /dev/null @@ -1,64 +0,0 @@ -package app.dapk.st.design.components - -import androidx.activity.compose.BackHandler -import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember - -@Composable -fun Spider(currentPage: SpiderPage, onNavigate: (SpiderPage?) -> Unit, graph: SpiderScope.() -> Unit) { - val pageCache = remember { mutableMapOf, SpiderPage>() } - pageCache[currentPage.route] = currentPage - - val navigateAndPopStack = { - pageCache.remove(currentPage.route) - onNavigate(pageCache[currentPage.parent]) - } - val itemScope = object : SpiderItemScope { - override fun goBack() { - navigateAndPopStack() - } - } - - val computedWeb = remember(true) { - mutableMapOf, @Composable (T) -> Unit>().also { computedWeb -> - val scope = object : SpiderScope { - override fun item(route: Route, content: @Composable SpiderItemScope.(T) -> Unit) { - computedWeb[route] = { content(itemScope, it as T) } - } - } - graph.invoke(scope) - } - } - - Column { - if (currentPage.hasToolbar) { - Toolbar( - onNavigate = navigateAndPopStack, - title = currentPage.label - ) - } - BackHandler(onBack = navigateAndPopStack) - computedWeb[currentPage.route]!!.invoke(currentPage.state) - } -} - - -interface SpiderScope { - fun item(route: Route, content: @Composable SpiderItemScope.(T) -> Unit) -} - -interface SpiderItemScope { - fun goBack() -} - -data class SpiderPage( - val route: Route, - val label: String, - val parent: Route<*>?, - val state: T, - val hasToolbar: Boolean = true, -) - -@JvmInline -value class Route(val value: String) \ No newline at end of file diff --git a/domains/android/compose-core/build.gradle b/domains/android/compose-core/build.gradle index 5de977e..e04cf9f 100644 --- a/domains/android/compose-core/build.gradle +++ b/domains/android/compose-core/build.gradle @@ -5,5 +5,4 @@ dependencies { implementation project(":features:navigator") implementation project(":design-library") api project(":domains:android:core") - api project(":domains:state") } diff --git a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/ActivityExtensions.kt b/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/ActivityExtensions.kt index d935abf..9c1adec 100644 --- a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/ActivityExtensions.kt +++ b/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/ActivityExtensions.kt @@ -21,53 +21,3 @@ inline fun ComponentActivity.viewModel( } return ViewModelLazy(VM::class, { viewModelStore }, { factoryPromise }) } - - -inline fun ComponentActivity.state( - noinline factory: () -> State -): Lazy> { - val factoryPromise = object : Factory { - @Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { - return when(modelClass) { - StateViewModel::class.java -> factory() as T - else -> throw Error() - } - } - } - return KeyedViewModelLazy( - key = S::class.java.canonicalName!!, - StateViewModel::class, - { viewModelStore }, - { factoryPromise } - ) as Lazy> -} - -class KeyedViewModelLazy @JvmOverloads constructor( - private val key: String, - private val viewModelClass: KClass, - private val storeProducer: () -> ViewModelStore, - private val factoryProducer: () -> ViewModelProvider.Factory, -) : Lazy { - private var cached: VM? = null - - override val value: VM - get() { - val viewModel = cached - return if (viewModel == null) { - val factory = factoryProducer() - val store = storeProducer() - ViewModelProvider( - store, - factory, - CreationExtras.Empty - ).get(key, viewModelClass.java).also { - cached = it - } - } else { - viewModel - } - } - - override fun isInitialized(): Boolean = cached != null -} \ No newline at end of file diff --git a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/StateViewModel.kt b/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/StateViewModel.kt deleted file mode 100644 index a584b8a..0000000 --- a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/StateViewModel.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.dapk.st.core - -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import app.dapk.state.Action -import app.dapk.state.ReducerFactory -import app.dapk.state.Store -import app.dapk.state.createStore -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow - -class StateViewModel( - reducerFactory: ReducerFactory, - eventSource: MutableSharedFlow, -) : ViewModel(), State { - - private val store: Store = createStore(reducerFactory, viewModelScope) - override val events: SharedFlow = eventSource - override val current - get() = _state!! - private var _state: S by mutableStateOf(store.getState()) - - init { - _state = store.getState() - store.subscribe { - _state = it - } - } - - override fun dispatch(action: Action) { - store.dispatch(action) - } -} - -fun createStateViewModel(block: (suspend (E) -> Unit) -> ReducerFactory): StateViewModel { - val eventSource = MutableSharedFlow(extraBufferCapacity = 1) - val reducer = block { eventSource.emit(it) } - return StateViewModel(reducer, eventSource) -} - -interface State { - fun dispatch(action: Action) - val events: SharedFlow - val current: S -} diff --git a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/page/PageReducer.kt b/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/page/PageReducer.kt deleted file mode 100644 index f84b00a..0000000 --- a/domains/android/compose-core/src/main/kotlin/app/dapk/st/core/page/PageReducer.kt +++ /dev/null @@ -1,95 +0,0 @@ -package app.dapk.st.core.page - -import app.dapk.st.design.components.SpiderPage -import app.dapk.state.* -import kotlin.reflect.KClass - -sealed interface PageAction : Action { - data class GoTo

(val page: SpiderPage

) : PageAction

-} - -sealed interface PageStateChange : Action { - data class ChangePage

(val previous: SpiderPage, val newPage: SpiderPage) : PageAction

- data class UpdatePage

(val pageContent: P) : PageAction

-} - -data class PageContainer

( - val page: SpiderPage -) - -interface PageReducerScope

{ - fun withPageContent(page: KClass, block: PageDispatchScope.() -> Unit) - fun rawPage(): SpiderPage -} - -interface PageDispatchScope { - fun ReducerScope<*>.pageDispatch(action: PageAction) - fun getPageState(): PC? -} - -fun

createPageReducer( - initialPage: SpiderPage, - factory: PageReducerScope

.() -> ReducerFactory, -): ReducerFactory, S>> = shareState { - combineReducers(createPageReducer(initialPage), factory(pageReducerScope())) -} - -private fun

SharedStateScope, S>>.pageReducerScope() = object : PageReducerScope

{ - override fun withPageContent(page: KClass, block: PageDispatchScope.() -> Unit) { - val currentPage = getSharedState().state1.page.state - if (currentPage::class == page) { - val pageDispatchScope = object : PageDispatchScope { - override fun ReducerScope<*>.pageDispatch(action: PageAction) { - val currentPageGuard = getSharedState().state1.page.state - if (currentPageGuard::class == page) { - dispatch(action) - } - } - - override fun getPageState() = getSharedState().state1.page.state as? PC - } - block(pageDispatchScope) - } - } - - override fun rawPage() = getSharedState().state1.page -} - -@Suppress("UNCHECKED_CAST") -private fun

createPageReducer( - initialPage: SpiderPage -): ReducerFactory> { - return createReducer( - initialState = PageContainer( - page = initialPage - ), - - async(PageAction.GoTo::class) { action -> - val state = getState() - if (state.page.state::class != action.page.state::class) { - dispatch(PageStateChange.ChangePage(previous = state.page, newPage = action.page)) - } else { - dispatch(PageStateChange.UpdatePage(action.page.state)) - } - }, - - change(PageStateChange.ChangePage::class) { action, state -> - state.copy(page = action.newPage as SpiderPage) - }, - - change(PageStateChange.UpdatePage::class) { action, state -> - val isSamePage = state.page.state::class == action.pageContent::class - if (isSamePage) { - val updatedPageContent = (state.page as SpiderPage).copy(state = action.pageContent) - state.copy(page = updatedPageContent as SpiderPage) - } else { - state - } - }, - ) -} - -inline fun PageReducerScope<*>.withPageContext(crossinline block: PageDispatchScope.(PC) -> Unit) { - withPageContent(PC::class) { getPageState()?.let { block(it) } } -} - diff --git a/domains/state/build.gradle b/domains/state/build.gradle deleted file mode 100644 index 9db4d7f..0000000 --- a/domains/state/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id 'kotlin' - id 'java-test-fixtures' -} - -dependencies { - implementation Dependencies.mavenCentral.kotlinCoroutinesCore - - testFixturesImplementation testFixtures(project(":core")) - testFixturesImplementation Dependencies.mavenCentral.kotlinCoroutinesCore - testFixturesImplementation Dependencies.mavenCentral.kluent - testFixturesImplementation Dependencies.mavenCentral.mockk - testFixturesImplementation Dependencies.mavenCentral.kotlinCoroutinesTest -} \ No newline at end of file diff --git a/domains/state/src/main/kotlin/app/dapk/state/State.kt b/domains/state/src/main/kotlin/app/dapk/state/State.kt deleted file mode 100644 index 252043e..0000000 --- a/domains/state/src/main/kotlin/app/dapk/state/State.kt +++ /dev/null @@ -1,194 +0,0 @@ -package app.dapk.state - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import kotlin.reflect.KClass - -fun createStore(reducerFactory: ReducerFactory, coroutineScope: CoroutineScope): Store { - val subscribers = mutableListOf<(S) -> Unit>() - var state: S = reducerFactory.initialState() - return object : Store { - private val scope = createScope(coroutineScope, this) - private val reducer = reducerFactory.create(scope) - - override fun dispatch(action: Action) { - coroutineScope.launch { - state = reducer.reduce(action).also { nextState -> - if (nextState != state) { - subscribers.forEach { it.invoke(nextState) } - } - } - } - } - - override fun getState() = state - - override fun subscribe(subscriber: (S) -> Unit) { - subscribers.add(subscriber) - } - } -} - -interface ReducerFactory { - fun create(scope: ReducerScope): Reducer - fun initialState(): S -} - -fun interface Reducer { - fun reduce(action: Action): S -} - -private fun createScope(coroutineScope: CoroutineScope, store: Store) = object : ReducerScope { - override val coroutineScope = coroutineScope - override fun dispatch(action: Action) = store.dispatch(action) - override fun getState(): S = store.getState() -} - -interface Store { - fun dispatch(action: Action) - fun getState(): S - fun subscribe(subscriber: (S) -> Unit) -} - -interface ReducerScope { - val coroutineScope: CoroutineScope - fun dispatch(action: Action) - fun getState(): S -} - -sealed interface ActionHandler { - val key: KClass - - class Async(override val key: KClass, val handler: suspend ReducerScope.(Action) -> Unit) : ActionHandler - class Sync(override val key: KClass, val handler: (Action, S) -> S) : ActionHandler - class Delegate(override val key: KClass, val handler: ReducerScope.(Action) -> ActionHandler) : ActionHandler -} - -data class Combined2(val state1: S1, val state2: S2) - -fun interface SharedStateScope { - fun getSharedState(): C -} - -fun shareState(block: SharedStateScope.() -> ReducerFactory): ReducerFactory { - var internalScope: ReducerScope? = null - val scope = SharedStateScope { internalScope!!.getState() } - val combinedFactory = block(scope) - return object : ReducerFactory { - override fun create(scope: ReducerScope) = combinedFactory.create(scope).also { internalScope = scope } - override fun initialState() = combinedFactory.initialState() - } -} - -fun combineReducers(r1: ReducerFactory, r2: ReducerFactory): ReducerFactory> { - return object : ReducerFactory> { - override fun create(scope: ReducerScope>): Reducer> { - val r1Scope = createReducerScope(scope) { scope.getState().state1 } - val r2Scope = createReducerScope(scope) { scope.getState().state2 } - - val r1Reducer = r1.create(r1Scope) - val r2Reducer = r2.create(r2Scope) - return Reducer { - Combined2(r1Reducer.reduce(it), r2Reducer.reduce(it)) - } - } - - override fun initialState(): Combined2 = Combined2(r1.initialState(), r2.initialState()) - } -} - -private fun createReducerScope(scope: ReducerScope<*>, state: () -> S) = object : ReducerScope { - override val coroutineScope: CoroutineScope = scope.coroutineScope - override fun dispatch(action: Action) = scope.dispatch(action) - override fun getState() = state.invoke() -} - -fun createReducer( - initialState: S, - vararg reducers: (ReducerScope) -> ActionHandler, -): ReducerFactory { - return object : ReducerFactory { - override fun create(scope: ReducerScope): Reducer { - val reducersMap = reducers - .map { it.invoke(scope) } - .groupBy { it.key } - - return Reducer { action -> - val result = reducersMap.keys - .filter { it.java.isAssignableFrom(action::class.java) } - .fold(scope.getState()) { acc, key -> - val actionHandlers = reducersMap[key]!! - actionHandlers.fold(acc) { acc, handler -> - when (handler) { - is ActionHandler.Async -> { - scope.coroutineScope.launch { - handler.handler.invoke(scope, action) - } - acc - } - - is ActionHandler.Sync -> handler.handler.invoke(action, acc) - is ActionHandler.Delegate -> when (val next = handler.handler.invoke(scope, action)) { - is ActionHandler.Async -> { - scope.coroutineScope.launch { - next.handler.invoke(scope, action) - } - acc - } - - is ActionHandler.Sync -> next.handler.invoke(action, acc) - is ActionHandler.Delegate -> error("is not possible") - } - } - } - } - result - } - } - - override fun initialState(): S = initialState - - } -} - -fun sideEffect(klass: KClass, block: suspend (A, S) -> Unit): (ReducerScope) -> ActionHandler { - return { - ActionHandler.Async(key = klass as KClass) { action -> block(action as A, getState()) } - } -} - -fun change(klass: KClass, block: (A, S) -> S): (ReducerScope) -> ActionHandler { - return { - ActionHandler.Sync(key = klass as KClass, block as (Action, S) -> S) - } -} - -fun async(klass: KClass, block: suspend ReducerScope.(A) -> Unit): (ReducerScope) -> ActionHandler { - return { - ActionHandler.Async(key = klass as KClass, block as suspend ReducerScope.(Action) -> Unit) - } -} - -fun multi(klass: KClass, block: Multi.(A) -> (ReducerScope) -> ActionHandler): (ReducerScope) -> ActionHandler { - val multiScope = object : Multi { - override fun sideEffect(block: suspend (S) -> Unit): (ReducerScope) -> ActionHandler = sideEffect(klass) { _, state -> block(state) } - override fun change(block: (A, S) -> S): (ReducerScope) -> ActionHandler = change(klass, block) - override fun async(block: suspend ReducerScope.(A) -> Unit): (ReducerScope) -> ActionHandler = async(klass, block) - override fun nothing() = sideEffect { } - } - - return { - ActionHandler.Delegate(key = klass as KClass) { action -> - block(multiScope, action as A).invoke(this) - } - } -} - -interface Multi { - fun sideEffect(block: suspend (S) -> Unit): (ReducerScope) -> ActionHandler - fun nothing(): (ReducerScope) -> ActionHandler - fun change(block: (A, S) -> S): (ReducerScope) -> ActionHandler - fun async(block: suspend ReducerScope.(A) -> Unit): (ReducerScope) -> ActionHandler -} - -interface Action \ No newline at end of file diff --git a/domains/state/src/testFixtures/kotlin/fake/FakeEventSource.kt b/domains/state/src/testFixtures/kotlin/fake/FakeEventSource.kt deleted file mode 100644 index 9a2d816..0000000 --- a/domains/state/src/testFixtures/kotlin/fake/FakeEventSource.kt +++ /dev/null @@ -1,20 +0,0 @@ -package fake - -import org.amshove.kluent.internal.assertEquals - -class FakeEventSource : (E) -> Unit { - - private val captures = mutableListOf() - - override fun invoke(event: E) { - captures.add(event) - } - - fun assertEvents(expected: List) { - assertEquals(expected, captures) - } - - fun assertNoEvents() { - assertEquals(emptyList(), captures) - } -} \ No newline at end of file diff --git a/domains/state/src/testFixtures/kotlin/test/ReducerTest.kt b/domains/state/src/testFixtures/kotlin/test/ReducerTest.kt deleted file mode 100644 index b50846b..0000000 --- a/domains/state/src/testFixtures/kotlin/test/ReducerTest.kt +++ /dev/null @@ -1,153 +0,0 @@ -package test - -import app.dapk.state.Action -import app.dapk.state.Reducer -import app.dapk.state.ReducerFactory -import app.dapk.state.ReducerScope -import fake.FakeEventSource -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.test.runTest -import org.amshove.kluent.internal.assertEquals -import org.amshove.kluent.shouldBeEqualTo - -interface ReducerTest { - operator fun invoke(block: suspend ReducerTestScope.() -> Unit) -} - -fun testReducer(block: ((E) -> Unit) -> ReducerFactory): ReducerTest { - val fakeEventSource = FakeEventSource() - val reducerFactory = block(fakeEventSource) - return object : ReducerTest { - override fun invoke(block: suspend ReducerTestScope.() -> Unit) { - runReducerTest(reducerFactory, fakeEventSource, block) - } - } -} - -fun runReducerTest(reducerFactory: ReducerFactory, fakeEventSource: FakeEventSource, block: suspend ReducerTestScope.() -> Unit) { - runTest { - val expectTestScope = ExpectTest(coroutineContext) - block(ReducerTestScope(reducerFactory, fakeEventSource, expectTestScope)) - expectTestScope.verifyExpects() - } -} - -class ReducerTestScope( - private val reducerFactory: ReducerFactory, - private val fakeEventSource: FakeEventSource, - private val expectTestScope: ExpectTestScope -) : ExpectTestScope by expectTestScope, Reducer { - - private var invalidateCapturedState: Boolean = false - private val actionSideEffects = mutableMapOf S>() - private var manualState: S? = null - private var capturedResult: S? = null - - private val actionCaptures = mutableListOf() - private val reducerScope = object : ReducerScope { - override val coroutineScope = CoroutineScope(UnconfinedTestDispatcher()) - override fun dispatch(action: Action) { - actionCaptures.add(action) - - if (actionSideEffects.containsKey(action)) { - setState(actionSideEffects.getValue(action).invoke(), invalidateCapturedState = true) - } - } - - override fun getState() = manualState ?: reducerFactory.initialState() - } - private val reducer: Reducer = reducerFactory.create(reducerScope) - - override fun reduce(action: Action) = reducer.reduce(action).also { - capturedResult = if (invalidateCapturedState) manualState else it - } - - fun actionSideEffect(action: Action, handler: () -> S) { - actionSideEffects[action] = handler - } - - fun setState(state: S, invalidateCapturedState: Boolean = false) { - manualState = state - this.invalidateCapturedState = invalidateCapturedState - } - - fun setState(block: (S) -> S) { - setState(block(reducerScope.getState())) - } - - fun assertInitialState(expected: S) { - reducerFactory.initialState() shouldBeEqualTo expected - } - - fun assertEvents(events: List) { - fakeEventSource.assertEvents(events) - } - - fun assertOnlyStateChange(expected: S) { - assertStateChange(expected) - assertNoDispatches() - fakeEventSource.assertNoEvents() - } - - fun assertOnlyStateChange(block: (S) -> S) { - val expected = block(reducerScope.getState()) - assertStateChange(expected) - assertNoDispatches() - fakeEventSource.assertNoEvents() - } - - fun assertStateChange(expected: S) { - capturedResult shouldBeEqualTo expected - } - - fun assertDispatches(expected: List) { - assertEquals(expected, actionCaptures) - } - - fun assertNoDispatches() { - assertEquals(emptyList(), actionCaptures) - } - - fun assertNoStateChange() { - assertEquals(reducerScope.getState(), capturedResult) - } - - fun assertNoEvents() { - fakeEventSource.assertNoEvents() - } - - fun assertOnlyDispatches(expected: List) { - assertDispatches(expected) - fakeEventSource.assertNoEvents() - assertNoStateChange() - } - - fun assertOnlyEvents(events: List) { - fakeEventSource.assertEvents(events) - assertNoDispatches() - assertNoStateChange() - } - - fun assertNoChanges() { - assertNoStateChange() - assertNoEvents() - assertNoDispatches() - } -} - -fun ReducerTestScope.assertOnlyDispatches(vararg action: Action) { - this.assertOnlyDispatches(action.toList()) -} - -fun ReducerTestScope.assertDispatches(vararg action: Action) { - this.assertDispatches(action.toList()) -} - -fun ReducerTestScope.assertEvents(vararg event: E) { - this.assertEvents(event.toList()) -} - -fun ReducerTestScope.assertOnlyEvents(vararg event: E) { - this.assertOnlyEvents(event.toList()) -} \ No newline at end of file diff --git a/features/directory/build.gradle b/features/directory/build.gradle index a3d7490..26115b8 100644 --- a/features/directory/build.gradle +++ b/features/directory/build.gradle @@ -3,7 +3,7 @@ applyAndroidComposeLibraryModule(project) dependencies { implementation project(":chat-engine") implementation project(":domains:android:compose-core") - implementation project(":domains:state") + implementation 'screen-state:screen-android' implementation project(":features:messenger") implementation project(":core") implementation project(":design-library") @@ -11,9 +11,9 @@ dependencies { kotlinTest(it) + testImplementation 'screen-state:state-test' androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) - androidImportFixturesWorkaround(project, project(":domains:state")) androidImportFixturesWorkaround(project, project(":domains:store")) androidImportFixturesWorkaround(project, project(":domains:android:stub")) androidImportFixturesWorkaround(project, project(":chat-engine")) diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt index 58a95ee..8ef9027 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryModule.kt @@ -2,7 +2,7 @@ package app.dapk.st.directory import android.content.Context import app.dapk.st.core.ProvidableModule -import app.dapk.st.core.createStateViewModel +import app.dapk.st.state.createStateViewModel import app.dapk.st.core.JobBag import app.dapk.st.directory.state.DirectoryState import app.dapk.st.directory.state.directoryReducer diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/state/DirectoryState.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/state/DirectoryState.kt index 3f20567..87a032a 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/state/DirectoryState.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/state/DirectoryState.kt @@ -1,6 +1,6 @@ package app.dapk.st.directory.state -import app.dapk.st.core.State +import app.dapk.st.state.State import app.dapk.st.engine.DirectoryState typealias DirectoryState = State diff --git a/features/home/build.gradle b/features/home/build.gradle index 0237cb0..e508c14 100644 --- a/features/home/build.gradle +++ b/features/home/build.gradle @@ -9,7 +9,7 @@ dependencies { implementation project(":domains:android:compose-core") implementation project(":domains:android:viewmodel") implementation project(':domains:store') - implementation project(':domains:state') + implementation 'screen-state:screen-android' implementation project(":core") implementation project(":design-library") implementation Dependencies.mavenCentral.coil diff --git a/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt b/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt index 7ac8bc8..7bcb3e9 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/MainActivity.kt @@ -13,11 +13,11 @@ import androidx.compose.ui.Modifier import androidx.lifecycle.lifecycleScope import app.dapk.st.core.DapkActivity import app.dapk.st.core.module -import app.dapk.st.core.state import app.dapk.st.core.viewModel import app.dapk.st.directory.DirectoryModule import app.dapk.st.login.LoginModule import app.dapk.st.profile.ProfileModule +import app.dapk.st.state.state import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/features/messenger/build.gradle b/features/messenger/build.gradle index 59d3ed8..1e7aa46 100644 --- a/features/messenger/build.gradle +++ b/features/messenger/build.gradle @@ -6,7 +6,7 @@ dependencies { implementation project(":domains:android:compose-core") implementation project(":domains:android:viewmodel") implementation project(":domains:store") - implementation project(":domains:state") + implementation 'screen-state:screen-android' implementation project(":core") implementation project(":features:navigator") implementation project(":design-library") @@ -14,10 +14,10 @@ dependencies { kotlinTest(it) + testImplementation 'screen-state:state-test' androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) androidImportFixturesWorkaround(project, project(":domains:store")) - androidImportFixturesWorkaround(project, project(":domains:state")) androidImportFixturesWorkaround(project, project(":domains:android:viewmodel")) androidImportFixturesWorkaround(project, project(":domains:android:stub")) androidImportFixturesWorkaround(project, project(":chat-engine")) diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerActivity.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerActivity.kt index 69f8730..439fdfc 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerActivity.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerActivity.kt @@ -10,15 +10,17 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.Modifier -import app.dapk.st.core.* +import app.dapk.st.core.AndroidUri +import app.dapk.st.core.DapkActivity +import app.dapk.st.core.MimeType import app.dapk.st.core.extensions.unsafeLazy +import app.dapk.st.core.module import app.dapk.st.matrix.common.RoomId import app.dapk.st.messenger.gallery.GetImageFromGallery import app.dapk.st.messenger.state.ComposerStateChange -import app.dapk.st.messenger.state.MessengerEvent -import app.dapk.st.messenger.state.MessengerScreenState import app.dapk.st.messenger.state.MessengerState import app.dapk.st.navigator.MessageAttachment +import app.dapk.st.state.state import coil.request.ImageRequest import kotlinx.parcelize.Parcelize @@ -27,7 +29,7 @@ val LocalImageRequestFactory = staticCompositionLocalOf { class MessengerActivity : DapkActivity() { private val module by unsafeLazy { module() } - private val state by state { module.messengerState(readPayload()) } + private val state: MessengerState by state { module.messengerState(readPayload()) } companion object { @@ -87,4 +89,4 @@ data class MessagerActivityPayload( fun Activity.readPayload(): T = intent.getParcelableExtra("key") ?: intent.getStringExtra("shortcut_key")!!.let { MessagerActivityPayload(it) as T -} \ No newline at end of file +} diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerModule.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerModule.kt index 50f12ab..d2001c5 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerModule.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/MessengerModule.kt @@ -5,7 +5,7 @@ import android.content.Context import app.dapk.st.core.DeviceMeta import app.dapk.st.core.JobBag import app.dapk.st.core.ProvidableModule -import app.dapk.st.core.createStateViewModel +import app.dapk.st.state.createStateViewModel import app.dapk.st.domain.application.message.MessageOptionsStore import app.dapk.st.engine.ChatEngine import app.dapk.st.matrix.common.RoomId diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/ImageGalleryActivity.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/ImageGalleryActivity.kt index 599d104..c6379e1 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/ImageGalleryActivity.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/ImageGalleryActivity.kt @@ -15,16 +15,17 @@ import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.lifecycleScope import app.dapk.st.core.* -import app.dapk.st.core.extensions.unsafeLazy import app.dapk.st.design.components.GenericError +import app.dapk.st.messenger.gallery.state.ImageGalleryState +import app.dapk.st.state.state import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize class ImageGalleryActivity : DapkActivity() { - private val module by unsafeLazy { module() } - private val imageGalleryState by state { + private val imageGalleryState: ImageGalleryState by state { val payload = intent.getParcelableExtra("key") as? ImageGalleryActivityPayload + val module = module() module.imageGalleryState(payload!!.roomName) } @@ -94,4 +95,4 @@ class GetImageFromGallery : ActivityResultContract Unit, onI } } - Spider(currentPage = state.current.state1.page, onNavigate = onNavigate) { + Spider(currentPage = state.current.state1.page, onNavigate = onNavigate, toolbar = { navigate, title -> Toolbar(navigate, title) }) { item(ImageGalleryPage.Routes.folders) { ImageGalleryFolders( it, diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducer.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducer.kt index db75035..3bd33aa 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducer.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducer.kt @@ -2,15 +2,15 @@ package app.dapk.st.messenger.gallery.state import app.dapk.st.core.JobBag import app.dapk.st.core.Lce -import app.dapk.st.core.page.PageAction -import app.dapk.st.core.page.PageStateChange -import app.dapk.st.core.page.createPageReducer -import app.dapk.st.core.page.withPageContext -import app.dapk.st.design.components.SpiderPage import app.dapk.st.messenger.gallery.FetchMediaFoldersUseCase import app.dapk.st.messenger.gallery.FetchMediaUseCase +import app.dapk.state.SpiderPage import app.dapk.state.async import app.dapk.state.createReducer +import app.dapk.state.page.PageAction +import app.dapk.state.page.PageStateChange +import app.dapk.state.page.createPageReducer +import app.dapk.state.page.withPageContext import app.dapk.state.sideEffect import kotlinx.coroutines.launch diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryState.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryState.kt index 3e07c31..4f95a3f 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryState.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryState.kt @@ -1,12 +1,12 @@ package app.dapk.st.messenger.gallery.state import app.dapk.st.core.Lce -import app.dapk.st.core.State -import app.dapk.st.design.components.Route +import app.dapk.st.state.State import app.dapk.st.messenger.gallery.Folder import app.dapk.st.messenger.gallery.Media -import app.dapk.st.core.page.PageContainer import app.dapk.state.Combined2 +import app.dapk.state.Route +import app.dapk.state.page.PageContainer typealias ImageGalleryState = State, Unit>, Unit> diff --git a/features/messenger/src/main/kotlin/app/dapk/st/messenger/state/MessengerState.kt b/features/messenger/src/main/kotlin/app/dapk/st/messenger/state/MessengerState.kt index 0fa7a5c..385767c 100644 --- a/features/messenger/src/main/kotlin/app/dapk/st/messenger/state/MessengerState.kt +++ b/features/messenger/src/main/kotlin/app/dapk/st/messenger/state/MessengerState.kt @@ -1,7 +1,7 @@ package app.dapk.st.messenger.state import app.dapk.st.core.Lce -import app.dapk.st.core.State +import app.dapk.st.state.State import app.dapk.st.design.components.BubbleModel import app.dapk.st.engine.MessengerPageState import app.dapk.st.engine.RoomEvent diff --git a/features/messenger/src/test/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducerTest.kt b/features/messenger/src/test/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducerTest.kt index bb684b1..d4decf4 100644 --- a/features/messenger/src/test/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducerTest.kt +++ b/features/messenger/src/test/kotlin/app/dapk/st/messenger/gallery/state/ImageGalleryReducerTest.kt @@ -2,15 +2,15 @@ package app.dapk.st.messenger.gallery.state import android.net.Uri import app.dapk.st.core.Lce -import app.dapk.st.core.page.PageAction -import app.dapk.st.core.page.PageContainer -import app.dapk.st.core.page.PageStateChange -import app.dapk.st.design.components.SpiderPage import app.dapk.st.messenger.gallery.FetchMediaFoldersUseCase import app.dapk.st.messenger.gallery.FetchMediaUseCase import app.dapk.st.messenger.gallery.Folder import app.dapk.st.messenger.gallery.Media import app.dapk.state.Combined2 +import app.dapk.state.SpiderPage +import app.dapk.state.page.PageAction +import app.dapk.state.page.PageContainer +import app.dapk.state.page.PageStateChange import fake.FakeJobBag import fake.FakeUri import io.mockk.coEvery @@ -18,7 +18,6 @@ import io.mockk.mockk import org.junit.Test import test.assertOnlyDispatches import test.delegateReturn -import test.expect import test.testReducer private const val A_ROOM_NAME = "a room name" diff --git a/features/profile/build.gradle b/features/profile/build.gradle index f3697f1..f3bf95b 100644 --- a/features/profile/build.gradle +++ b/features/profile/build.gradle @@ -4,16 +4,16 @@ dependencies { implementation project(":chat-engine") implementation project(":features:settings") implementation project(':domains:store') - implementation project(':domains:state') + implementation 'screen-state:screen-android' implementation project(":domains:android:compose-core") implementation project(":design-library") implementation project(":core") kotlinTest(it) + testImplementation 'screen-state:state-test' androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) - androidImportFixturesWorkaround(project, project(":domains:state")) androidImportFixturesWorkaround(project, project(":domains:store")) androidImportFixturesWorkaround(project, project(":domains:android:stub")) androidImportFixturesWorkaround(project, project(":chat-engine")) diff --git a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt index 2b0037f..165f993 100644 --- a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt +++ b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileModule.kt @@ -2,7 +2,7 @@ package app.dapk.st.profile import app.dapk.st.core.JobBag import app.dapk.st.core.ProvidableModule -import app.dapk.st.core.createStateViewModel +import app.dapk.st.state.createStateViewModel import app.dapk.st.core.extensions.ErrorTracker import app.dapk.st.engine.ChatEngine import app.dapk.st.profile.state.ProfileState diff --git a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileScreen.kt b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileScreen.kt index 6b2fbdc..b740780 100644 --- a/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileScreen.kt +++ b/features/profile/src/main/kotlin/app/dapk/st/profile/ProfileScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.unit.dp import app.dapk.st.core.Lce import app.dapk.st.core.LifecycleEffect import app.dapk.st.core.components.CenteredLoading -import app.dapk.st.core.page.PageAction import app.dapk.st.design.components.* import app.dapk.st.engine.RoomInvite import app.dapk.st.engine.RoomInvite.InviteMeta @@ -28,6 +27,8 @@ import app.dapk.st.profile.state.Page import app.dapk.st.profile.state.ProfileAction import app.dapk.st.profile.state.ProfileState import app.dapk.st.settings.SettingsActivity +import app.dapk.state.SpiderPage +import app.dapk.state.page.PageAction @Composable fun ProfileScreen(viewModel: ProfileState, onTopLevelBack: () -> Unit) { @@ -47,7 +48,7 @@ fun ProfileScreen(viewModel: ProfileState, onTopLevelBack: () -> Unit) { } } - Spider(currentPage = viewModel.current.state1.page, onNavigate = onNavigate) { + Spider(currentPage = viewModel.current.state1.page, onNavigate = onNavigate, toolbar = { navigate, title -> Toolbar(navigate, title) }) { item(Page.Routes.profile) { ProfilePage(context, viewModel, it) } diff --git a/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileReducer.kt b/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileReducer.kt index 8d01ee7..1badceb 100644 --- a/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileReducer.kt +++ b/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileReducer.kt @@ -3,14 +3,14 @@ package app.dapk.st.profile.state import app.dapk.st.core.JobBag import app.dapk.st.core.Lce import app.dapk.st.core.extensions.ErrorTracker -import app.dapk.st.core.page.PageAction -import app.dapk.st.core.page.PageStateChange -import app.dapk.st.core.page.createPageReducer -import app.dapk.st.core.page.withPageContext -import app.dapk.st.design.components.SpiderPage import app.dapk.st.engine.ChatEngine +import app.dapk.state.SpiderPage import app.dapk.state.async import app.dapk.state.createReducer +import app.dapk.state.page.PageAction +import app.dapk.state.page.PageStateChange +import app.dapk.state.page.createPageReducer +import app.dapk.state.page.withPageContext import app.dapk.state.sideEffect import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileState.kt b/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileState.kt index 7490b49..3869bb8 100644 --- a/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileState.kt +++ b/features/profile/src/main/kotlin/app/dapk/st/profile/state/ProfileState.kt @@ -1,12 +1,12 @@ package app.dapk.st.profile.state import app.dapk.st.core.Lce -import app.dapk.st.core.State -import app.dapk.st.core.page.PageContainer -import app.dapk.st.design.components.Route +import app.dapk.st.state.State import app.dapk.st.engine.Me import app.dapk.st.engine.RoomInvite import app.dapk.state.Combined2 +import app.dapk.state.Route +import app.dapk.state.page.PageContainer typealias ProfileState = State, Unit>, Unit> diff --git a/features/profile/src/test/kotlin/app/dapk/st/profile/state/ProfileReducerTest.kt b/features/profile/src/test/kotlin/app/dapk/st/profile/state/ProfileReducerTest.kt index 68fb60c..e5849e5 100644 --- a/features/profile/src/test/kotlin/app/dapk/st/profile/state/ProfileReducerTest.kt +++ b/features/profile/src/test/kotlin/app/dapk/st/profile/state/ProfileReducerTest.kt @@ -1,13 +1,13 @@ package app.dapk.st.profile.state import app.dapk.st.core.Lce -import app.dapk.st.core.page.PageAction -import app.dapk.st.core.page.PageContainer -import app.dapk.st.core.page.PageStateChange -import app.dapk.st.design.components.SpiderPage import app.dapk.st.engine.Me import app.dapk.st.matrix.common.HomeServerUrl import app.dapk.state.Combined2 +import app.dapk.state.SpiderPage +import app.dapk.state.page.PageAction +import app.dapk.state.page.PageContainer +import app.dapk.state.page.PageStateChange import fake.FakeChatEngine import fake.FakeErrorTracker import fake.FakeJobBag diff --git a/features/settings/build.gradle b/features/settings/build.gradle index d88337d..d646822 100644 --- a/features/settings/build.gradle +++ b/features/settings/build.gradle @@ -7,15 +7,16 @@ dependencies { implementation project(':domains:android:push') implementation project(":domains:android:compose-core") implementation project(":domains:android:viewmodel") + implementation 'screen-state:screen-android' implementation project(":design-library") implementation project(":core") kotlinTest(it) + testImplementation 'screen-state:state-test' androidImportFixturesWorkaround(project, project(":matrix:common")) androidImportFixturesWorkaround(project, project(":core")) androidImportFixturesWorkaround(project, project(":domains:store")) - androidImportFixturesWorkaround(project, project(":domains:state")) androidImportFixturesWorkaround(project, project(":domains:android:viewmodel")) androidImportFixturesWorkaround(project, project(":domains:android:stub")) androidImportFixturesWorkaround(project, project(":chat-engine")) diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsActivity.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsActivity.kt index 1cc26df..216617f 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsActivity.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsActivity.kt @@ -4,11 +4,15 @@ import android.os.Bundle import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.ui.Modifier -import app.dapk.st.core.* +import app.dapk.st.core.DapkActivity +import app.dapk.st.core.module +import app.dapk.st.core.resetModules +import app.dapk.st.settings.state.SettingsState +import app.dapk.st.state.state class SettingsActivity : DapkActivity() { - private val settingsState by state { module().settingsState() } + private val settingsState: SettingsState by state { module().settingsState() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsModule.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsModule.kt index a3271e3..61d4a9a 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsModule.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsModule.kt @@ -10,6 +10,7 @@ import app.dapk.st.push.PushModule import app.dapk.st.settings.eventlogger.EventLoggerViewModel import app.dapk.st.settings.state.SettingsState import app.dapk.st.settings.state.settingsReducer +import app.dapk.st.state.createStateViewModel class SettingsModule( private val chatEngine: ChatEngine, diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsScreen.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsScreen.kt index 6e73893..f7038c3 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsScreen.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsScreen.kt @@ -41,7 +41,6 @@ import app.dapk.st.core.components.CenteredLoading import app.dapk.st.core.components.Header import app.dapk.st.core.extensions.takeAs import app.dapk.st.core.getActivity -import app.dapk.st.core.page.PageAction import app.dapk.st.design.components.* import app.dapk.st.engine.ImportResult import app.dapk.st.navigator.Navigator @@ -51,6 +50,8 @@ import app.dapk.st.settings.state.ComponentLifecycle import app.dapk.st.settings.state.RootActions import app.dapk.st.settings.state.ScreenAction import app.dapk.st.settings.state.SettingsState +import app.dapk.state.SpiderPage +import app.dapk.state.page.PageAction @OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class) @Composable @@ -66,7 +67,7 @@ internal fun SettingsScreen(settingsState: SettingsState, onSignOut: () -> Unit, else -> settingsState.dispatch(PageAction.GoTo(it)) } } - Spider(currentPage = settingsState.current.state1.page, onNavigate = onNavigate) { + Spider(currentPage = settingsState.current.state1.page, onNavigate = onNavigate, toolbar = { navigate, title -> Toolbar(navigate, title) }) { item(Page.Routes.root) { RootSettings( it, diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt index ff796c7..bb71728 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/SettingsState.kt @@ -2,10 +2,10 @@ package app.dapk.st.settings import android.net.Uri import app.dapk.st.core.Lce -import app.dapk.st.design.components.Route -import app.dapk.st.design.components.SpiderPage import app.dapk.st.engine.ImportResult import app.dapk.st.push.Registrar +import app.dapk.state.Route +import app.dapk.state.SpiderPage internal data class SettingsScreenState( val page: SpiderPage, @@ -26,9 +26,9 @@ internal sealed interface Page { object Routes { val root = Route("Settings") - val encryption = Route("Encryption") - val pushProviders = Route("PushProviders") - val importRoomKeys = Route("ImportRoomKey") + val encryption = Route("Encryption") + val pushProviders = Route("PushProviders") + val importRoomKeys = Route("ImportRoomKey") } } diff --git a/features/settings/src/main/kotlin/app/dapk/st/settings/state/SettingsReducer.kt b/features/settings/src/main/kotlin/app/dapk/st/settings/state/SettingsReducer.kt index a17dd55..075661c 100644 --- a/features/settings/src/main/kotlin/app/dapk/st/settings/state/SettingsReducer.kt +++ b/features/settings/src/main/kotlin/app/dapk/st/settings/state/SettingsReducer.kt @@ -3,10 +3,8 @@ package app.dapk.st.settings.state import android.content.ContentResolver import app.dapk.st.core.JobBag import app.dapk.st.core.Lce -import app.dapk.st.core.State +import app.dapk.st.state.State import app.dapk.st.core.ThemeStore -import app.dapk.st.core.page.* -import app.dapk.st.design.components.SpiderPage import app.dapk.st.domain.StoreCleaner import app.dapk.st.domain.application.eventlog.LoggingStore import app.dapk.st.domain.application.message.MessageOptionsStore @@ -16,10 +14,8 @@ import app.dapk.st.push.PushTokenRegistrars import app.dapk.st.settings.* import app.dapk.st.settings.SettingItem.Id.* import app.dapk.st.settings.SettingsEvent.* -import app.dapk.state.Combined2 -import app.dapk.state.async -import app.dapk.state.createReducer -import app.dapk.state.multi +import app.dapk.state.* +import app.dapk.state.page.* import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch diff --git a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsReducerTest.kt b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsReducerTest.kt index 4b6e2ec..837a5ad 100644 --- a/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsReducerTest.kt +++ b/features/settings/src/test/kotlin/app/dapk/st/settings/SettingsReducerTest.kt @@ -1,10 +1,6 @@ package app.dapk.st.settings import app.dapk.st.core.Lce -import app.dapk.st.core.page.PageAction -import app.dapk.st.core.page.PageContainer -import app.dapk.st.core.page.PageStateChange -import app.dapk.st.design.components.SpiderPage import app.dapk.st.engine.ImportResult import app.dapk.st.push.Registrar import app.dapk.st.settings.state.ComponentLifecycle @@ -12,6 +8,10 @@ import app.dapk.st.settings.state.RootActions import app.dapk.st.settings.state.ScreenAction import app.dapk.st.settings.state.settingsReducer import app.dapk.state.Combined2 +import app.dapk.state.SpiderPage +import app.dapk.state.page.PageAction +import app.dapk.state.page.PageContainer +import app.dapk.state.page.PageStateChange import fake.* import fixture.aRoomId import internalfake.FakeSettingsItemFactory diff --git a/features/settings/src/test/kotlin/internalfixture/PageFixture.kt b/features/settings/src/test/kotlin/internalfixture/PageFixture.kt index d42834f..61ae7a9 100644 --- a/features/settings/src/test/kotlin/internalfixture/PageFixture.kt +++ b/features/settings/src/test/kotlin/internalfixture/PageFixture.kt @@ -1,7 +1,7 @@ package internalfixture -import app.dapk.st.design.components.SpiderPage import app.dapk.st.settings.Page +import app.dapk.state.SpiderPage internal fun aImportRoomKeysPage( state: Page.ImportRoomKey = Page.ImportRoomKey() diff --git a/settings.gradle b/settings.gradle index bd5242f..f677ed5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,9 @@ dependencyResolutionManagement { } } rootProject.name = "SmallTalk" + +includeBuild '../screen-state' + include ':app' include ':design-library' From 37ad97c76123d468e89da6570da05445f9bd6037 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 28 Nov 2022 19:03:43 +0000 Subject: [PATCH 2/3] using screen-state submodule --- .gitmodules | 3 +++ build.gradle | 6 ------ screen-state | 1 + settings.gradle | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 .gitmodules create mode 160000 screen-state diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..74b800c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "screen-state"] + path = screen-state + url = git@github.com:ouchadam/screen-state.git diff --git a/build.gradle b/build.gradle index e1c1e9b..944d6f1 100644 --- a/build.gradle +++ b/build.gradle @@ -151,12 +151,6 @@ ext.androidImportFixturesWorkaround = { project, fixtures -> project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar") } -ext.androidImportCompositeFixturesWorkaround = { project, fixtures -> - project.dependencies.testImplementation(project.dependencies.testFixtures(fixtures)) - project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}-test-fixtures.jar") - project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar") -} - ext.isFoss = { return rootProject.hasProperty("foss") } diff --git a/screen-state b/screen-state new file mode 160000 index 0000000..4e92f14 --- /dev/null +++ b/screen-state @@ -0,0 +1 @@ +Subproject commit 4e92f14031cc8be907cba09b3bfc1d9dbd380072 diff --git a/settings.gradle b/settings.gradle index f677ed5..d24e38e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,7 +7,7 @@ dependencyResolutionManagement { } rootProject.name = "SmallTalk" -includeBuild '../screen-state' +includeBuild 'screen-state' include ':app' From 99c9556fb3cb07c639530e680112e1b184d0c2e7 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 28 Nov 2022 19:09:53 +0000 Subject: [PATCH 3/3] use recursive submodule checkout --- .github/workflows/assemble.yml | 3 +++ .github/workflows/check_size.yml | 3 +++ .github/workflows/release-candidate.yml | 3 +++ .github/workflows/release-train.yml | 2 ++ .github/workflows/test.yml | 2 ++ 5 files changed, 13 insertions(+) diff --git a/.github/workflows/assemble.yml b/.github/workflows/assemble.yml index 26935f8..3db296c 100644 --- a/.github/workflows/assemble.yml +++ b/.github/workflows/assemble.yml @@ -17,6 +17,9 @@ jobs: steps: - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - uses: actions/setup-java@v3 with: distribution: 'adopt' diff --git a/.github/workflows/check_size.yml b/.github/workflows/check_size.yml index 1a855e0..4a40c71 100644 --- a/.github/workflows/check_size.yml +++ b/.github/workflows/check_size.yml @@ -14,6 +14,9 @@ jobs: steps: - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - uses: actions/setup-java@v2 with: distribution: 'adopt' diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index c07920d..50b3a25 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -16,6 +16,9 @@ jobs: steps: - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - uses: actions/setup-java@v2 with: distribution: 'adopt' diff --git a/.github/workflows/release-train.yml b/.github/workflows/release-train.yml index f9f2a85..0ec1e2d 100644 --- a/.github/workflows/release-train.yml +++ b/.github/workflows/release-train.yml @@ -16,6 +16,8 @@ jobs: steps: - uses: actions/checkout@v2 + with: + submodules: 'recursive' - uses: actions/setup-node@v3 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fd29ec1..31224d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,6 +17,8 @@ jobs: steps: - uses: actions/checkout@v2 + with: + submodules: 'recursive' - uses: actions/setup-java@v2 with: distribution: 'adopt'