diff --git a/core/src/main/kotlin/app/dapk/st/core/JobBag.kt b/core/src/main/kotlin/app/dapk/st/core/JobBag.kt
index 3d91bfc..1e22518 100644
--- a/core/src/main/kotlin/app/dapk/st/core/JobBag.kt
+++ b/core/src/main/kotlin/app/dapk/st/core/JobBag.kt
@@ -1,6 +1,7 @@
package app.dapk.st.core
import kotlinx.coroutines.Job
+import kotlin.reflect.KClass
class JobBag {
@@ -11,8 +12,17 @@ class JobBag {
jobs[key] = job
}
+ fun replace(key: KClass<*>, job: Job) {
+ jobs[key.java.canonicalName]?.cancel()
+ jobs[key.java.canonicalName] = job
+ }
+
fun cancel(key: String) {
jobs.remove(key)?.cancel()
}
+ fun cancel(key: KClass<*>) {
+ jobs.remove(key.java.canonicalName)?.cancel()
+ }
+
}
\ No newline at end of file
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
index f33464a..aa43a46 100644
--- 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
@@ -4,32 +4,12 @@ import app.dapk.st.design.components.SpiderPage
import app.dapk.state.*
import kotlin.reflect.KClass
-fun
createPageReducer(
- initialPage: SpiderPage
-): ReducerFactory> {
- return createReducer(
- initialState = PageContainer(
- page = initialPage
- ),
-
- change(PageAction.GoTo::class) { action, state ->
- state.copy(page = action.page as SpiderPage)
- },
-
- change(PageAction.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
- }
- },
- )
+sealed interface PageAction : Action {
+ data class GoTo(val page: SpiderPage
) : PageAction
}
-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
}
@@ -37,26 +17,23 @@ data class PageContainer
(
val page: SpiderPage
)
-fun PageContainer<*>.isDifferentPage(page: SpiderPage<*>): Boolean {
- return page::class != this.page::class
-}
-
-interface PageReducerScope {
+interface PageReducerScope {
fun withPageContent(page: KClass, block: PageDispatchScope.() -> Unit)
+ fun rawPage(): SpiderPage
}
-interface PageDispatchScope {
- fun ReducerScope<*>.pageDispatch(action: PageAction
)
- fun getPageState(): P?
+interface PageDispatchScope {
+ fun ReducerScope<*>.pageDispatch(action: PageAction)
+ fun getPageState(): PC?
}
fun createPageReducer(
initialPage: SpiderPage,
- factory: PageReducerScope.() -> ReducerFactory,
+ factory: PageReducerScope.() -> ReducerFactory,
): ReducerFactory, S>> = shareState {
combineReducers(
createPageReducer(initialPage),
- factory(object : PageReducerScope {
+ factory(object : PageReducerScope {
override fun withPageContent(page: KClass, block: PageDispatchScope.() -> Unit) {
val currentPage = getSharedState().state1.page.state
if (currentPage::class == page) {
@@ -73,11 +50,45 @@ fun createPageReducer(
block(pageDispatchScope)
}
}
+
+ override fun rawPage() = getSharedState().state1.page
})
)
}
-inline fun PageReducerScope.withPageContext(crossinline block: PageDispatchScope.(PC) -> Unit) {
+@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))
+ }
+ },
+
+ 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/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 360467f..fd37f1b 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
@@ -3,11 +3,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.PageContainer
-import app.dapk.st.core.page.isDifferentPage
+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.*
-import app.dapk.state.*
+import app.dapk.st.messenger.gallery.FetchMediaFoldersUseCase
+import app.dapk.st.messenger.gallery.FetchMediaUseCase
+import app.dapk.state.async
+import app.dapk.state.createReducer
+import app.dapk.state.sideEffect
import kotlinx.coroutines.launch
fun imageGalleryReducer(
@@ -15,54 +19,47 @@ fun imageGalleryReducer(
foldersUseCase: FetchMediaFoldersUseCase,
fetchMediaUseCase: FetchMediaUseCase,
jobBag: JobBag,
-) = shareState {
- combineReducers(
- createPageReducer(roomName),
- createImageGalleryPageReducer(jobBag, foldersUseCase, fetchMediaUseCase),
- )
-}
-
-private fun createPageReducer(roomName: String): ReducerFactory> = app.dapk.st.core.page.createPageReducer(
- initialPage = SpiderPage(
+) = createPageReducer(
+ initialPage = SpiderPage(
route = ImageGalleryPage.Routes.folders,
label = "Send to $roomName",
parent = null,
state = ImageGalleryPage.Folders(Lce.Loading())
- )
-)
+ ),
+ factory = {
+ createReducer(
+ initialState = Unit,
-private fun SharedStateScope, Unit>>.createImageGalleryPageReducer(
- jobBag: JobBag,
- foldersUseCase: FetchMediaFoldersUseCase,
- fetchMediaUseCase: FetchMediaUseCase
-) = createReducer(
- initialState = Unit,
+ async(ImageGalleryActions.Visible::class) {
+ jobBag.replace(ImageGalleryPage.Folders::class, coroutineScope.launch {
+ val folders = foldersUseCase.fetchFolders()
+ withPageContext {
+ pageDispatch(PageStateChange.UpdatePage(it.copy(content = Lce.Content(folders))))
+ }
+ })
+ },
- async(ImageGalleryActions.Visible::class) {
- jobBag.replace("page", coroutineScope.launch {
- val folders = foldersUseCase.fetchFolders()
- dispatch(PageAction.UpdatePage(ImageGalleryPage.Folders(Lce.Content(folders))))
- })
- },
+ async(ImageGalleryActions.SelectFolder::class) { action ->
+ val page = SpiderPage(
+ route = ImageGalleryPage.Routes.files,
+ label = rawPage().label,
+ parent = ImageGalleryPage.Routes.folders,
+ state = ImageGalleryPage.Files(Lce.Loading(), action.folder)
+ )
- async(ImageGalleryActions.SelectFolder::class) { action ->
- val page = SpiderPage(
- route = ImageGalleryPage.Routes.files,
- label = getSharedState().state1.page.label,
- parent = ImageGalleryPage.Routes.folders,
- state = ImageGalleryPage.Files(Lce.Loading(), action.folder)
+ dispatch(PageAction.GoTo(page))
+
+ jobBag.replace(ImageGalleryPage.Files::class, coroutineScope.launch {
+ val media = fetchMediaUseCase.getMediaInBucket(action.folder.bucketId)
+ withPageContext {
+ pageDispatch(PageStateChange.UpdatePage(it.copy(content = Lce.Content(media))))
+ }
+ })
+ },
+
+ sideEffect(PageStateChange.ChangePage::class) { action, _ ->
+ jobBag.cancel(action.previous::class)
+ },
)
- dispatch(PageAction.GoTo(page))
-
- jobBag.replace("page", coroutineScope.launch {
- val media = fetchMediaUseCase.getMediaInBucket(action.folder.bucketId)
- dispatch(PageAction.UpdatePage(page.state.copy(content = Lce.Content(media))))
- })
- },
-
- sideEffect(PageAction.GoTo::class) { action, _ ->
- if (getSharedState().state1.isDifferentPage(action.page)) {
- jobBag.cancel("page")
- }
}
)
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 173aa5c..9ccc1b9 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
@@ -5,10 +5,7 @@ import app.dapk.st.core.JobBag
import app.dapk.st.core.Lce
import app.dapk.st.core.State
import app.dapk.st.core.ThemeStore
-import app.dapk.st.core.page.PageAction
-import app.dapk.st.core.page.PageContainer
-import app.dapk.st.core.page.createPageReducer
-import app.dapk.st.core.page.withPageContext
+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
@@ -57,14 +54,14 @@ internal fun settingsReducer(
async(RootActions.FetchProviders::class) {
withPageContext {
- pageDispatch(PageAction.UpdatePage(it.copy(options = Lce.Loading())))
+ pageDispatch(PageStateChange.UpdatePage(it.copy(options = Lce.Loading())))
}
val currentSelection = pushTokenRegistrars.currentSelection()
val options = pushTokenRegistrars.options()
withPageContext {
pageDispatch(
- PageAction.UpdatePage(
+ PageStateChange.UpdatePage(
it.copy(
selection = currentSelection,
options = Lce.Content(options)
@@ -82,7 +79,7 @@ internal fun settingsReducer(
async(RootActions.ImportKeysFromFile::class) { action ->
withPageContext {
- pageDispatch(PageAction.UpdatePage(it.copy(importProgress = ImportResult.Update(0))))
+ pageDispatch(PageStateChange.UpdatePage(it.copy(importProgress = ImportResult.Update(0))))
}
with(chatEngine) {
@@ -92,7 +89,7 @@ internal fun settingsReducer(
fileStream.importRoomKeys(action.passphrase)
.onEach { progress ->
withPageContext {
- pageDispatch(PageAction.UpdatePage(it.copy(importProgress = progress)))
+ pageDispatch(PageStateChange.UpdatePage(it.copy(importProgress = progress)))
}
}
.launchIn(coroutineScope)
@@ -100,7 +97,7 @@ internal fun settingsReducer(
onFailure = {
withPageContext {
- pageDispatch(PageAction.UpdatePage(it.copy(importProgress = ImportResult.Error(ImportResult.Error.Type.UnableToOpenFile))))
+ pageDispatch(PageStateChange.UpdatePage(it.copy(importProgress = ImportResult.Error(ImportResult.Error.Type.UnableToOpenFile))))
}
}
)
@@ -114,7 +111,7 @@ internal fun settingsReducer(
)
withPageContext {
- pageDispatch(PageAction.UpdatePage(it.copy(selectedFile = namedFile)))
+ pageDispatch(PageStateChange.UpdatePage(it.copy(selectedFile = namedFile)))
}
},
@@ -181,5 +178,4 @@ internal fun settingsReducer(
}
)
-
internal typealias SettingsState = State, Unit>, SettingsEvent>