port profile and page to reducer pattern
This commit is contained in:
parent
72fa795d38
commit
70bc1be72d
|
@ -10,6 +10,11 @@ class JobBag {
|
||||||
jobs[key] = job
|
jobs[key] = job
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun replace(key: String, job: Job) {
|
||||||
|
jobs[key]?.cancel()
|
||||||
|
jobs[key] = job
|
||||||
|
}
|
||||||
|
|
||||||
fun cancel(key: String) {
|
fun cancel(key: String) {
|
||||||
jobs.remove(key)?.cancel()
|
jobs.remove(key)?.cancel()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import app.dapk.st.core.JobBag
|
||||||
|
import io.mockk.mockk
|
||||||
|
|
||||||
|
class FakeJobBag {
|
||||||
|
val instance = mockk<JobBag>()
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,48 @@ sealed interface ActionHandler<S> {
|
||||||
class Delegate<S>(override val key: KClass<Action>, val handler: ReducerScope<S>.(Action) -> ActionHandler<S>) : ActionHandler<S>
|
class Delegate<S>(override val key: KClass<Action>, val handler: ReducerScope<S>.(Action) -> ActionHandler<S>) : ActionHandler<S>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Combined2<S1, S2>(val state1: S1, val state2: S2)
|
||||||
|
|
||||||
|
fun interface SharedStateScope<C> {
|
||||||
|
fun getSharedState(): C
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S> shareState(block: SharedStateScope<S>.() -> ReducerFactory<S>): ReducerFactory<S> {
|
||||||
|
var internalScope: ReducerScope<S>? = null
|
||||||
|
val scope = SharedStateScope { internalScope!!.getState() }
|
||||||
|
val combinedFactory = block(scope)
|
||||||
|
return object : ReducerFactory<S> {
|
||||||
|
override fun create(scope: ReducerScope<S>) = combinedFactory.create(scope).also { internalScope = scope }
|
||||||
|
override fun initialState() = combinedFactory.initialState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <S1, S2> combineReducers(r1: ReducerFactory<S1>, r2: ReducerFactory<S2>): ReducerFactory<Combined2<S1, S2>> {
|
||||||
|
return object : ReducerFactory<Combined2<S1, S2>> {
|
||||||
|
override fun create(scope: ReducerScope<Combined2<S1, S2>>): Reducer<Combined2<S1, S2>> {
|
||||||
|
val r1Scope = object : ReducerScope<S1> {
|
||||||
|
override val coroutineScope: CoroutineScope = scope.coroutineScope
|
||||||
|
override suspend fun dispatch(action: Action) = scope.dispatch(action)
|
||||||
|
override fun getState() = scope.getState().state1
|
||||||
|
}
|
||||||
|
|
||||||
|
val r2Scope = object : ReducerScope<S2> {
|
||||||
|
override val coroutineScope: CoroutineScope = scope.coroutineScope
|
||||||
|
override suspend fun dispatch(action: Action) = scope.dispatch(action)
|
||||||
|
override fun getState() = 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<S1, S2> = Combined2(r1.initialState(), r2.initialState())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun <S> createReducer(
|
fun <S> createReducer(
|
||||||
initialState: S,
|
initialState: S,
|
||||||
vararg reducers: (ReducerScope<S>) -> ActionHandler<S>,
|
vararg reducers: (ReducerScope<S>) -> ActionHandler<S>,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package app.dapk.st.directory
|
package app.dapk.st.directory
|
||||||
|
|
||||||
import app.dapk.st.core.JobBag
|
|
||||||
import app.dapk.st.directory.state.*
|
import app.dapk.st.directory.state.*
|
||||||
import app.dapk.st.engine.DirectoryItem
|
import app.dapk.st.engine.DirectoryItem
|
||||||
import app.dapk.st.engine.UnreadCount
|
import app.dapk.st.engine.UnreadCount
|
||||||
import fake.FakeChatEngine
|
import fake.FakeChatEngine
|
||||||
|
import fake.FakeJobBag
|
||||||
import fixture.aRoomOverview
|
import fixture.aRoomOverview
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
@ -91,8 +91,3 @@ class DirectoryReducerTest {
|
||||||
internal class FakeShortcutHandler {
|
internal class FakeShortcutHandler {
|
||||||
val instance = mockk<ShortcutHandler>()
|
val instance = mockk<ShortcutHandler>()
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeJobBag {
|
|
||||||
val instance = mockk<JobBag>()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ import kotlinx.parcelize.Parcelize
|
||||||
class ImageGalleryActivity : DapkActivity() {
|
class ImageGalleryActivity : DapkActivity() {
|
||||||
|
|
||||||
private val module by unsafeLazy { module<ImageGalleryModule>() }
|
private val module by unsafeLazy { module<ImageGalleryModule>() }
|
||||||
private val viewModel by viewModel {
|
private val imageGalleryState by state {
|
||||||
val payload = intent.getParcelableExtra("key") as? ImageGalleryActivityPayload
|
val payload = intent.getParcelableExtra("key") as? ImageGalleryActivityPayload
|
||||||
module.imageGalleryViewModel(payload!!.roomName)
|
module.imageGalleryState(payload!!.roomName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -42,7 +42,7 @@ class ImageGalleryActivity : DapkActivity() {
|
||||||
setContent {
|
setContent {
|
||||||
Surface {
|
Surface {
|
||||||
PermissionGuard(permissionState) {
|
PermissionGuard(permissionState) {
|
||||||
ImageGalleryScreen(viewModel, onTopLevelBack = { finish() }) { media ->
|
ImageGalleryScreen(imageGalleryState, onTopLevelBack = { finish() }) { media ->
|
||||||
setResult(RESULT_OK, Intent().setData(media.uri))
|
setResult(RESULT_OK, Intent().setData(media.uri))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
package app.dapk.st.messenger.gallery
|
package app.dapk.st.messenger.gallery
|
||||||
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import app.dapk.st.core.CoroutineDispatchers
|
import app.dapk.st.core.*
|
||||||
import app.dapk.st.core.ProvidableModule
|
import app.dapk.st.messenger.gallery.state.ImageGalleryState
|
||||||
|
import app.dapk.st.messenger.gallery.state.imageGalleryReducer
|
||||||
|
|
||||||
class ImageGalleryModule(
|
class ImageGalleryModule(
|
||||||
private val contentResolver: ContentResolver,
|
private val contentResolver: ContentResolver,
|
||||||
private val dispatchers: CoroutineDispatchers,
|
private val dispatchers: CoroutineDispatchers,
|
||||||
) : ProvidableModule {
|
) : ProvidableModule {
|
||||||
|
|
||||||
fun imageGalleryViewModel(roomName: String) = ImageGalleryViewModel(
|
fun imageGalleryState(roomName: String): ImageGalleryState = createStateViewModel {
|
||||||
|
imageGalleryReducer(
|
||||||
|
roomName = roomName,
|
||||||
FetchMediaFoldersUseCase(contentResolver, dispatchers),
|
FetchMediaFoldersUseCase(contentResolver, dispatchers),
|
||||||
FetchMediaUseCase(contentResolver, dispatchers),
|
FetchMediaUseCase(contentResolver, dispatchers),
|
||||||
roomName = roomName,
|
JobBag(),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,35 +24,41 @@ import app.dapk.st.core.components.CenteredLoading
|
||||||
import app.dapk.st.design.components.GenericError
|
import app.dapk.st.design.components.GenericError
|
||||||
import app.dapk.st.design.components.Spider
|
import app.dapk.st.design.components.Spider
|
||||||
import app.dapk.st.design.components.SpiderPage
|
import app.dapk.st.design.components.SpiderPage
|
||||||
|
import app.dapk.st.messenger.gallery.state.ImageGalleryActions
|
||||||
|
import app.dapk.st.messenger.gallery.state.ImageGalleryPage
|
||||||
|
import app.dapk.st.messenger.gallery.state.ImageGalleryState
|
||||||
import coil.compose.rememberAsyncImagePainter
|
import coil.compose.rememberAsyncImagePainter
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageGalleryScreen(viewModel: ImageGalleryViewModel, onTopLevelBack: () -> Unit, onImageSelected: (Media) -> Unit) {
|
fun ImageGalleryScreen(state: ImageGalleryState, onTopLevelBack: () -> Unit, onImageSelected: (Media) -> Unit) {
|
||||||
LifecycleEffect(onStart = {
|
LifecycleEffect(onStart = {
|
||||||
viewModel.start()
|
state.dispatch(ImageGalleryActions.Visible)
|
||||||
})
|
})
|
||||||
|
|
||||||
val onNavigate: (SpiderPage<out ImageGalleryPage>?) -> Unit = {
|
val onNavigate: (SpiderPage<out ImageGalleryPage>?) -> Unit = {
|
||||||
when (it) {
|
when (it) {
|
||||||
null -> onTopLevelBack()
|
null -> onTopLevelBack()
|
||||||
else -> viewModel.goTo(it)
|
else -> state.dispatch(PageAction.GoTo(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spider(currentPage = viewModel.state.page, onNavigate = onNavigate) {
|
Spider(currentPage = state.current.state1.page, onNavigate = onNavigate) {
|
||||||
item(ImageGalleryPage.Routes.folders) {
|
item(ImageGalleryPage.Routes.folders) {
|
||||||
ImageGalleryFolders(it, onClick = { viewModel.selectFolder(it) }, onRetry = { viewModel.start() })
|
ImageGalleryFolders(
|
||||||
|
it,
|
||||||
|
onClick = { state.dispatch(ImageGalleryActions.SelectFolder(it)) },
|
||||||
|
onRetry = { state.dispatch(ImageGalleryActions.Visible) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
item(ImageGalleryPage.Routes.files) {
|
item(ImageGalleryPage.Routes.files) {
|
||||||
ImageGalleryMedia(it, onImageSelected, onRetry = { viewModel.selectFolder(it.folder) })
|
ImageGalleryMedia(it, onImageSelected, onRetry = { state.dispatch(ImageGalleryActions.SelectFolder(it.folder)) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageGalleryFolders(state: ImageGalleryPage.Folders, onClick: (Folder) -> Unit, onRetry: () -> Unit) {
|
private fun ImageGalleryFolders(state: ImageGalleryPage.Folders, onClick: (Folder) -> Unit, onRetry: () -> Unit) {
|
||||||
val screenWidth = LocalConfiguration.current.screenWidthDp
|
val screenWidth = LocalConfiguration.current.screenWidthDp
|
||||||
|
|
||||||
val gradient = Brush.verticalGradient(
|
val gradient = Brush.verticalGradient(
|
||||||
|
@ -108,7 +114,7 @@ fun ImageGalleryFolders(state: ImageGalleryPage.Folders, onClick: (Folder) -> Un
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageGalleryMedia(state: ImageGalleryPage.Files, onFileSelected: (Media) -> Unit, onRetry: () -> Unit) {
|
private fun ImageGalleryMedia(state: ImageGalleryPage.Files, onFileSelected: (Media) -> Unit, onRetry: () -> Unit) {
|
||||||
val screenWidth = LocalConfiguration.current.screenWidthDp
|
val screenWidth = LocalConfiguration.current.screenWidthDp
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
package app.dapk.st.messenger.gallery
|
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import app.dapk.st.core.Lce
|
|
||||||
import app.dapk.st.design.components.Route
|
|
||||||
import app.dapk.st.design.components.SpiderPage
|
|
||||||
import app.dapk.st.viewmodel.DapkViewModel
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class ImageGalleryViewModel(
|
|
||||||
private val foldersUseCase: FetchMediaFoldersUseCase,
|
|
||||||
private val fetchMediaUseCase: FetchMediaUseCase,
|
|
||||||
roomName: String,
|
|
||||||
) : DapkViewModel<ImageGalleryState, ImageGalleryEvent>(
|
|
||||||
initialState = ImageGalleryState(
|
|
||||||
page = SpiderPage(
|
|
||||||
route = ImageGalleryPage.Routes.folders,
|
|
||||||
label = "Send to $roomName",
|
|
||||||
parent = null,
|
|
||||||
state = ImageGalleryPage.Folders(Lce.Loading())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
|
|
||||||
private var currentPageJob: Job? = null
|
|
||||||
|
|
||||||
fun start() {
|
|
||||||
currentPageJob?.cancel()
|
|
||||||
currentPageJob = viewModelScope.launch {
|
|
||||||
val folders = foldersUseCase.fetchFolders()
|
|
||||||
updatePageState<ImageGalleryPage.Folders> { copy(content = Lce.Content(folders)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun goTo(page: SpiderPage<out ImageGalleryPage>) {
|
|
||||||
currentPageJob?.cancel()
|
|
||||||
updateState { copy(page = page) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun selectFolder(folder: Folder) {
|
|
||||||
currentPageJob?.cancel()
|
|
||||||
|
|
||||||
updateState {
|
|
||||||
copy(
|
|
||||||
page = SpiderPage(
|
|
||||||
route = ImageGalleryPage.Routes.files,
|
|
||||||
label = page.label,
|
|
||||||
parent = ImageGalleryPage.Routes.folders,
|
|
||||||
state = ImageGalleryPage.Files(Lce.Loading(), folder)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPageJob = viewModelScope.launch {
|
|
||||||
val media = fetchMediaUseCase.getMediaInBucket(folder.bucketId)
|
|
||||||
updatePageState<ImageGalleryPage.Files> {
|
|
||||||
copy(content = Lce.Content(media))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private inline fun <reified S : ImageGalleryPage> updatePageState(crossinline block: S.() -> S) {
|
|
||||||
val page = state.page
|
|
||||||
val currentState = page.state
|
|
||||||
require(currentState is S)
|
|
||||||
updateState { copy(page = (page as SpiderPage<S>).copy(state = block(page.state))) }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ImageGalleryState(
|
|
||||||
val page: SpiderPage<out ImageGalleryPage>,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
sealed interface ImageGalleryPage {
|
|
||||||
data class Folders(val content: Lce<List<Folder>>) : ImageGalleryPage
|
|
||||||
data class Files(val content: Lce<List<Media>>, val folder: Folder) : ImageGalleryPage
|
|
||||||
|
|
||||||
object Routes {
|
|
||||||
val folders = Route<Folders>("Folders")
|
|
||||||
val files = Route<Files>("Files")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed interface ImageGalleryEvent
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package app.dapk.st.messenger.gallery
|
||||||
|
|
||||||
|
import app.dapk.st.design.components.SpiderPage
|
||||||
|
import app.dapk.state.Action
|
||||||
|
import app.dapk.state.ReducerFactory
|
||||||
|
import app.dapk.state.change
|
||||||
|
import app.dapk.state.createReducer
|
||||||
|
|
||||||
|
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 : Action {
|
||||||
|
data class GoTo<P : Any>(val page: SpiderPage<P>) : PageAction
|
||||||
|
data class UpdatePage<P : Any>(val pageContent: P) : PageAction
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PageContainer<P>(
|
||||||
|
val page: SpiderPage<out P>
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package app.dapk.st.messenger.gallery.state
|
||||||
|
|
||||||
|
import app.dapk.st.messenger.gallery.Folder
|
||||||
|
import app.dapk.state.Action
|
||||||
|
|
||||||
|
sealed interface ImageGalleryActions : Action {
|
||||||
|
object Visible : ImageGalleryActions
|
||||||
|
data class SelectFolder(val folder: Folder) : ImageGalleryActions
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package app.dapk.st.messenger.gallery.state
|
||||||
|
|
||||||
|
import app.dapk.st.core.JobBag
|
||||||
|
import app.dapk.st.core.Lce
|
||||||
|
import app.dapk.st.design.components.SpiderPage
|
||||||
|
import app.dapk.st.messenger.gallery.*
|
||||||
|
import app.dapk.state.*
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
fun imageGalleryReducer(
|
||||||
|
roomName: String,
|
||||||
|
foldersUseCase: FetchMediaFoldersUseCase,
|
||||||
|
fetchMediaUseCase: FetchMediaUseCase,
|
||||||
|
jobBag: JobBag,
|
||||||
|
) = shareState {
|
||||||
|
combineReducers(
|
||||||
|
createPageReducer(roomName),
|
||||||
|
createImageGalleryPageReducer(jobBag, foldersUseCase, fetchMediaUseCase),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPageReducer(roomName: String): ReducerFactory<PageContainer<ImageGalleryPage>> = createPageReducer(
|
||||||
|
initialPage = SpiderPage(
|
||||||
|
route = ImageGalleryPage.Routes.folders,
|
||||||
|
label = "Send to $roomName",
|
||||||
|
parent = null,
|
||||||
|
state = ImageGalleryPage.Folders(Lce.Loading())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun SharedStateScope<Combined2<PageContainer<ImageGalleryPage>, Unit>>.createImageGalleryPageReducer(
|
||||||
|
jobBag: JobBag,
|
||||||
|
foldersUseCase: FetchMediaFoldersUseCase,
|
||||||
|
fetchMediaUseCase: FetchMediaUseCase
|
||||||
|
) = createReducer(
|
||||||
|
initialState = Unit,
|
||||||
|
|
||||||
|
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 = getSharedState().state1.page.label,
|
||||||
|
parent = ImageGalleryPage.Routes.folders,
|
||||||
|
state = ImageGalleryPage.Files(Lce.Loading(), action.folder)
|
||||||
|
)
|
||||||
|
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))))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
|
@ -0,0 +1,21 @@
|
||||||
|
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.messenger.gallery.Folder
|
||||||
|
import app.dapk.st.messenger.gallery.Media
|
||||||
|
import app.dapk.st.messenger.gallery.PageContainer
|
||||||
|
import app.dapk.state.Combined2
|
||||||
|
|
||||||
|
typealias ImageGalleryState = State<Combined2<PageContainer<ImageGalleryPage>, Unit>, Unit>
|
||||||
|
|
||||||
|
sealed interface ImageGalleryPage {
|
||||||
|
data class Folders(val content: Lce<List<Folder>>) : ImageGalleryPage
|
||||||
|
data class Files(val content: Lce<List<Media>>, val folder: Folder) : ImageGalleryPage
|
||||||
|
|
||||||
|
object Routes {
|
||||||
|
val folders = Route<Folders>("Folders")
|
||||||
|
val files = Route<Files>("Files")
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import app.dapk.st.matrix.common.asString
|
||||||
import app.dapk.st.messenger.state.*
|
import app.dapk.st.messenger.state.*
|
||||||
import app.dapk.st.navigator.MessageAttachment
|
import app.dapk.st.navigator.MessageAttachment
|
||||||
import fake.FakeChatEngine
|
import fake.FakeChatEngine
|
||||||
|
import fake.FakeJobBag
|
||||||
import fake.FakeMessageOptionsStore
|
import fake.FakeMessageOptionsStore
|
||||||
import fixture.*
|
import fixture.*
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
@ -351,10 +352,6 @@ class FakeCopyToClipboard {
|
||||||
val instance = mockk<CopyToClipboard>()
|
val instance = mockk<CopyToClipboard>()
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeJobBag {
|
|
||||||
val instance = mockk<JobBag>()
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeDeviceMeta {
|
class FakeDeviceMeta {
|
||||||
val instance = mockk<DeviceMeta>()
|
val instance = mockk<DeviceMeta>()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue