porting page reducers to new iteration
This commit is contained in:
parent
7a13f530b0
commit
f0e5ae4502
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
|
@ -4,32 +4,12 @@ import app.dapk.st.design.components.SpiderPage
|
|||
import app.dapk.state.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun <P : Any> createPageReducer(
|
||||
initialPage: SpiderPage<out P>
|
||||
): ReducerFactory<PageContainer<P>> {
|
||||
return createReducer(
|
||||
initialState = PageContainer(
|
||||
page = initialPage
|
||||
),
|
||||
|
||||
change(PageAction.GoTo::class) { action, state ->
|
||||
state.copy(page = action.page as SpiderPage<P>)
|
||||
},
|
||||
|
||||
change(PageAction.UpdatePage::class) { action, state ->
|
||||
val isSamePage = state.page.state::class == action.pageContent::class
|
||||
if (isSamePage) {
|
||||
val updatedPageContent = (state.page as SpiderPage<Any>).copy(state = action.pageContent)
|
||||
state.copy(page = updatedPageContent as SpiderPage<out P>)
|
||||
} else {
|
||||
state
|
||||
}
|
||||
},
|
||||
)
|
||||
sealed interface PageAction<out P> : Action {
|
||||
data class GoTo<P : Any>(val page: SpiderPage<P>) : PageAction<P>
|
||||
}
|
||||
|
||||
sealed interface PageAction<P> : Action {
|
||||
data class GoTo<P : Any>(val page: SpiderPage<P>) : PageAction<P>
|
||||
sealed interface PageStateChange : Action {
|
||||
data class ChangePage<P : Any>(val previous: SpiderPage<out P>, val newPage: SpiderPage<out P>) : PageAction<P>
|
||||
data class UpdatePage<P : Any>(val pageContent: P) : PageAction<P>
|
||||
}
|
||||
|
||||
|
@ -37,26 +17,23 @@ data class PageContainer<P>(
|
|||
val page: SpiderPage<out P>
|
||||
)
|
||||
|
||||
fun PageContainer<*>.isDifferentPage(page: SpiderPage<*>): Boolean {
|
||||
return page::class != this.page::class
|
||||
}
|
||||
|
||||
interface PageReducerScope {
|
||||
interface PageReducerScope<P> {
|
||||
fun <PC : Any> withPageContent(page: KClass<PC>, block: PageDispatchScope<PC>.() -> Unit)
|
||||
fun rawPage(): SpiderPage<out P>
|
||||
}
|
||||
|
||||
interface PageDispatchScope<P> {
|
||||
fun ReducerScope<*>.pageDispatch(action: PageAction<P>)
|
||||
fun getPageState(): P?
|
||||
interface PageDispatchScope<PC> {
|
||||
fun ReducerScope<*>.pageDispatch(action: PageAction<PC>)
|
||||
fun getPageState(): PC?
|
||||
}
|
||||
|
||||
fun <P : Any, S : Any> createPageReducer(
|
||||
initialPage: SpiderPage<out P>,
|
||||
factory: PageReducerScope.() -> ReducerFactory<S>,
|
||||
factory: PageReducerScope<P>.() -> ReducerFactory<S>,
|
||||
): ReducerFactory<Combined2<PageContainer<P>, S>> = shareState {
|
||||
combineReducers(
|
||||
createPageReducer(initialPage),
|
||||
factory(object : PageReducerScope {
|
||||
factory(object : PageReducerScope<P> {
|
||||
override fun <PC : Any> withPageContent(page: KClass<PC>, block: PageDispatchScope<PC>.() -> Unit) {
|
||||
val currentPage = getSharedState().state1.page.state
|
||||
if (currentPage::class == page) {
|
||||
|
@ -73,11 +50,45 @@ fun <P : Any, S : Any> createPageReducer(
|
|||
block(pageDispatchScope)
|
||||
}
|
||||
}
|
||||
|
||||
override fun rawPage() = getSharedState().state1.page
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
inline fun <reified PC : Any> PageReducerScope.withPageContext(crossinline block: PageDispatchScope<PC>.(PC) -> Unit) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <P : Any> createPageReducer(
|
||||
initialPage: SpiderPage<out P>
|
||||
): ReducerFactory<PageContainer<P>> {
|
||||
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<out P>)
|
||||
},
|
||||
|
||||
change(PageStateChange.UpdatePage::class) { action, state ->
|
||||
val isSamePage = state.page.state::class == action.pageContent::class
|
||||
if (isSamePage) {
|
||||
val updatedPageContent = (state.page as SpiderPage<Any>).copy(state = action.pageContent)
|
||||
state.copy(page = updatedPageContent as SpiderPage<out P>)
|
||||
} else {
|
||||
state
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
inline fun <reified PC : Any> PageReducerScope<*>.withPageContext(crossinline block: PageDispatchScope<PC>.(PC) -> Unit) {
|
||||
withPageContent(PC::class) { getPageState()?.let { block(it) } }
|
||||
}
|
||||
|
||||
|
|
|
@ -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<PageContainer<ImageGalleryPage>> = app.dapk.st.core.page.createPageReducer(
|
||||
initialPage = SpiderPage(
|
||||
) = createPageReducer(
|
||||
initialPage = SpiderPage<ImageGalleryPage>(
|
||||
route = ImageGalleryPage.Routes.folders,
|
||||
label = "Send to $roomName",
|
||||
parent = null,
|
||||
state = ImageGalleryPage.Folders(Lce.Loading())
|
||||
)
|
||||
)
|
||||
),
|
||||
factory = {
|
||||
createReducer(
|
||||
initialState = Unit,
|
||||
|
||||
private fun SharedStateScope<Combined2<PageContainer<ImageGalleryPage>, 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<ImageGalleryPage.Folders> {
|
||||
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<ImageGalleryPage.Files> {
|
||||
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")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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<Page.PushProviders> {
|
||||
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<Page.PushProviders> {
|
||||
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<Page.ImportRoomKey> {
|
||||
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<Page.ImportRoomKey> {
|
||||
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<Page.ImportRoomKey> {
|
||||
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<Page.ImportRoomKey> {
|
||||
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<Combined2<PageContainer<Page>, Unit>, SettingsEvent>
|
||||
|
|
Loading…
Reference in New Issue