1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-10 10:00:44 +09:00

DROID-946 Widgets | Enhancement | GUI basics for link-styled widgets + Processing widget object payload updates (#2901)

This commit is contained in:
Evgenii Kozlov 2023-02-07 17:58:30 +01:00 committed by GitHub
parent 25a184085f
commit 878f84a052
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 202 additions and 22 deletions

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectView
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.ext.process
import com.anytypeio.anytype.core_utils.ext.replace
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Resultat
@ -18,10 +19,12 @@ import com.anytypeio.anytype.domain.search.ObjectSearchSubscriptionContainer
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.presentation.widgets.LinkWidgetContainer
import com.anytypeio.anytype.presentation.widgets.TreePath
import com.anytypeio.anytype.presentation.widgets.TreeWidgetBranchStateHolder
import com.anytypeio.anytype.presentation.widgets.TreeWidgetContainer
import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetContainer
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.presentation.widgets.parseWidgets
@ -52,7 +55,7 @@ class HomeScreenViewModel(
private val objectViewState = MutableStateFlow<ObjectViewState>(ObjectViewState.Idle)
private val widgets = MutableStateFlow<List<Widget>>(emptyList())
private val containers = MutableStateFlow<List<TreeWidgetContainer>>(emptyList())
private val containers = MutableStateFlow<List<WidgetContainer>>(emptyList())
private val expanded = TreeWidgetBranchStateHolder()
init {
@ -107,14 +110,14 @@ class HomeScreenViewModel(
widgets.map {
it.map { w ->
when (w) {
is Widget.Link -> TODO()
is Widget.Tree -> {
TreeWidgetContainer(
widget = w,
container = objectSearchSubscriptionContainer,
expandedBranches = expanded.stream(w.id)
)
}
is Widget.Link -> LinkWidgetContainer(
widget = w
)
is Widget.Tree -> TreeWidgetContainer(
widget = w,
container = objectSearchSubscriptionContainer,
expandedBranches = expanded.stream(w.id)
)
}
}
}.collect {
@ -217,9 +220,7 @@ class HomeScreenViewModel(
event.events.forEach { e ->
when (e) {
is Event.Command.AddBlock -> {
curr = curr.copy(
blocks = curr.blocks + e.blocks
)
curr = curr.copy(blocks = curr.blocks + e.blocks)
}
is Event.Command.UpdateStructure -> {
curr = curr.copy(
@ -231,6 +232,9 @@ class HomeScreenViewModel(
)
)
}
is Event.Command.Details -> {
curr = curr.copy(details = curr.details.process(e))
}
else -> {
Timber.d("Skipping event: $e")
}

View file

@ -0,0 +1,15 @@
package com.anytypeio.anytype.presentation.widgets
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
class LinkWidgetContainer(
private val widget: Widget.Link
) : WidgetContainer {
override val view: Flow<WidgetView.Link> = flowOf(
WidgetView.Link(
id = widget.id,
obj = widget.source
)
)
}

View file

@ -15,11 +15,11 @@ class TreeWidgetContainer(
private val widget: Widget.Tree,
private val container: ObjectSearchSubscriptionContainer,
private val expandedBranches: Flow<List<TreePath>>
) {
) : WidgetContainer {
private val store = mutableMapOf<Id, ObjectWrapper.Basic>()
val view: Flow<WidgetView.Tree> = expandedBranches.mapLatest {
override val view: Flow<WidgetView.Tree> = expandedBranches.mapLatest {
container.get(
subscription = widget.id,
keys = keys,

View file

@ -56,9 +56,11 @@ fun List<Block>.parseWidgets(
)
}
Block.Content.Widget.Layout.LINK -> {
Widget.Link(
id = w.id,
source = data
add(
Widget.Link(
id = w.id,
source = data
)
)
}
}

View file

@ -0,0 +1,7 @@
package com.anytypeio.anytype.presentation.widgets
import kotlinx.coroutines.flow.Flow
sealed interface WidgetContainer {
val view: Flow<WidgetView>
}

View file

@ -24,6 +24,11 @@ sealed class WidgetView {
}
}
data class Link(
val id: Id,
val obj: ObjectWrapper.Basic,
) : WidgetView()
sealed class Action : WidgetView() {
object EditWidgets : Action()
object CreateWidget: Action()

View file

@ -199,6 +199,81 @@ class HomeViewModelTest {
}
}
@Test
fun `should emit link-widget and actions`() = runTest {
// SETUP
val sourceObject = StubObject(
id = "SOURCE OBJECT",
links = emptyList()
)
val sourceLink = StubLinkToObjectBlock(
id = "SOURCE LINK",
target = sourceObject.id
)
val widgetBlock = StubWidgetBlock(
id = "WIDGET BLOCK",
layout = Block.Content.Widget.Layout.LINK,
children = listOf(sourceLink.id)
)
val smartBlock = StubSmartBlock(
id = WIDGET_OBJECT_ID,
children = listOf(widgetBlock.id),
type = SmartBlockType.WIDGET
)
val givenObjectView = StubObjectView(
root = WIDGET_OBJECT_ID,
type = SmartBlockType.WIDGET,
blocks = listOf(
smartBlock,
widgetBlock,
sourceLink
),
details = mapOf(
sourceObject.id to sourceObject.map
)
)
stubConfig()
stubInterceptEvents(events = emptyFlow())
stubOpenObject(givenObjectView)
stubObjectSearchContainer(
subscription = widgetBlock.id,
targets = emptyList()
)
val vm = buildViewModel()
// TESTING
vm.views.test {
val firstTimeState = awaitItem()
assertEquals(
actual = firstTimeState,
expected = HomeScreenViewModel.actions
)
val secondTimeItem = awaitItem()
assertEquals(
expected = buildList {
add(
WidgetView.Link(
id = widgetBlock.id,
obj = sourceObject
)
)
addAll(HomeScreenViewModel.actions)
},
actual = secondTimeItem
)
verify(openObject, times(1)).invoke(WIDGET_OBJECT_ID)
}
}
private fun stubInterceptEvents(events: Flow<List<Event>>) {
interceptEvents.stub {
on { build(InterceptEvents.Params(WIDGET_OBJECT_ID)) } doReturn events