mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-12 02:30:25 +09:00
DROID-609 Sets | Protocol | Atomic view changes (#2862)
* DROID-609 event blockDataviewViewUpdate + mapping * DROID-609 list extensions * DROID-609 updates mapping * DROID-609 reduce updateView event * DROID-609 updateView event model * DROID-609 update lists extensions + tests * DROID-609 UpdateView event mapping * DROID-609 tests * DROID-609 data view stubs * DROID-609 pr fix
This commit is contained in:
parent
bdd8548695
commit
d94b07a338
11 changed files with 781 additions and 7 deletions
|
@ -2,12 +2,17 @@ package com.anytypeio.anytype.presentation.sets
|
|||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.DV
|
||||
import com.anytypeio.anytype.core_models.DVFilter
|
||||
import com.anytypeio.anytype.core_models.DVRecord
|
||||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewerRelation
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_utils.ext.addAfterIndexInLine
|
||||
import com.anytypeio.anytype.core_utils.ext.replace
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
|
@ -19,6 +24,11 @@ import com.anytypeio.anytype.presentation.relations.objectTypeRelation
|
|||
import com.anytypeio.anytype.presentation.relations.view
|
||||
import com.anytypeio.anytype.presentation.sets.model.ObjectView
|
||||
import com.anytypeio.anytype.presentation.sets.model.SimpleRelationView
|
||||
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVSortUpdate
|
||||
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVFilterUpdate
|
||||
import com.anytypeio.anytype.core_models.Event.Command.DataView.UpdateView.DVViewerRelationUpdate
|
||||
import com.anytypeio.anytype.core_utils.ext.mapInPlace
|
||||
import com.anytypeio.anytype.core_utils.ext.moveAfterIndexInLine
|
||||
|
||||
fun ObjectSet.featuredRelations(
|
||||
ctx: Id,
|
||||
|
@ -179,4 +189,97 @@ fun ObjectWrapper.Basic.toObjectView(urlBuilder: UrlBuilder): ObjectView = when
|
|||
types = type,
|
||||
isRelation = type.contains(ObjectTypeIds.RELATION)
|
||||
)
|
||||
}
|
||||
|
||||
fun List<DVFilter>.updateFilters(updates: List<DVFilterUpdate>): List<DVFilter> {
|
||||
val filters = this.toMutableList()
|
||||
updates.forEach { update ->
|
||||
when (update) {
|
||||
is DVFilterUpdate.Add -> {
|
||||
filters.addAfterIndexInLine(
|
||||
predicateIndex = { it.relationKey == update.afterId },
|
||||
items = update.filters
|
||||
)
|
||||
}
|
||||
is DVFilterUpdate.Move -> {
|
||||
filters.moveAfterIndexInLine(
|
||||
predicateIndex = { filter -> filter.relationKey == update.afterId },
|
||||
predicateMove = { filter -> update.ids.contains(filter.relationKey) }
|
||||
)
|
||||
}
|
||||
is DVFilterUpdate.Remove -> {
|
||||
filters.retainAll {
|
||||
!update.ids.contains(it.relationKey)
|
||||
}
|
||||
}
|
||||
is DVFilterUpdate.Update -> {
|
||||
filters.mapInPlace { filter ->
|
||||
if (filter.relationKey == update.id) update.filter else filter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
fun List<DVSort>.updateSorts(updates: List<DVSortUpdate>): List<DVSort> {
|
||||
val sorts = this.toMutableList()
|
||||
updates.forEach { update ->
|
||||
when (update) {
|
||||
is DVSortUpdate.Add -> {
|
||||
sorts.addAfterIndexInLine(
|
||||
predicateIndex = { it.relationKey == update.afterId },
|
||||
items = update.sorts
|
||||
)
|
||||
}
|
||||
is DVSortUpdate.Move -> {
|
||||
sorts.moveAfterIndexInLine(
|
||||
predicateIndex = { sort -> sort.relationKey == update.afterId },
|
||||
predicateMove = { sort -> update.ids.contains(sort.relationKey) }
|
||||
)
|
||||
}
|
||||
is DVSortUpdate.Remove -> {
|
||||
sorts.retainAll {
|
||||
!update.ids.contains(it.relationKey)
|
||||
}
|
||||
}
|
||||
is DVSortUpdate.Update -> {
|
||||
sorts.mapInPlace { sort ->
|
||||
if (sort.relationKey == update.id) update.sort else sort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sorts
|
||||
}
|
||||
|
||||
fun List<DVViewerRelation>.updateViewerRelations(updates: List<DVViewerRelationUpdate>): List<DVViewerRelation> {
|
||||
val relations = this.toMutableList()
|
||||
updates.forEach { update ->
|
||||
when (update) {
|
||||
is DVViewerRelationUpdate.Add -> {
|
||||
relations.addAfterIndexInLine(
|
||||
predicateIndex = { it.key == update.afterId },
|
||||
items = update.relations
|
||||
)
|
||||
}
|
||||
is DVViewerRelationUpdate.Move -> {
|
||||
relations.moveAfterIndexInLine(
|
||||
predicateIndex = { relation -> relation.key == update.afterId },
|
||||
predicateMove = { relation -> update.ids.contains(relation.key) }
|
||||
)
|
||||
}
|
||||
is DVViewerRelationUpdate.Remove -> {
|
||||
relations.retainAll {
|
||||
!update.ids.contains(it.key)
|
||||
}
|
||||
}
|
||||
is DVViewerRelationUpdate.Update -> {
|
||||
relations.mapInPlace { relation ->
|
||||
if (relation.key == update.id) update.relation else relation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return relations
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.presentation.sets
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.DV
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Event.Command
|
||||
|
@ -146,6 +147,53 @@ class ObjectSetReducer {
|
|||
}
|
||||
)
|
||||
}
|
||||
is Command.DataView.UpdateView -> {
|
||||
val updatedBlocks = state.blocks.map { block: Block ->
|
||||
val content = block.content
|
||||
if (block.id == event.block && content is DV) {
|
||||
block.copy(
|
||||
content = content.copy(
|
||||
viewers = content.viewers.map { viewer ->
|
||||
if (viewer.id == event.viewerId) {
|
||||
val filters = if (event.filterUpdates.isNotEmpty()) {
|
||||
viewer.filters.updateFilters(
|
||||
updates = event.filterUpdates
|
||||
)
|
||||
} else {
|
||||
viewer.filters
|
||||
}
|
||||
val sorts = if (event.sortUpdates.isNotEmpty()) {
|
||||
viewer.sorts.updateSorts(
|
||||
updates = event.sortUpdates
|
||||
)
|
||||
} else {
|
||||
viewer.sorts
|
||||
}
|
||||
val viewerRelations =
|
||||
if (event.relationUpdates.isNotEmpty()) {
|
||||
viewer.viewerRelations.updateViewerRelations(
|
||||
updates = event.relationUpdates
|
||||
)
|
||||
} else {
|
||||
viewer.viewerRelations
|
||||
}
|
||||
viewer.copy(
|
||||
filters = filters,
|
||||
sorts = sorts,
|
||||
viewerRelations = viewerRelations
|
||||
)
|
||||
} else {
|
||||
viewer
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
} else {
|
||||
block
|
||||
}
|
||||
}
|
||||
state.copy(blocks = updatedBlocks)
|
||||
}
|
||||
is Command.Details.Set -> {
|
||||
state.copy(
|
||||
details = state.details.toMutableMap().apply {
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
package com.anytypeio.anytype.presentation.sets
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.StubDataView
|
||||
import com.anytypeio.anytype.core_models.StubDataViewView
|
||||
import com.anytypeio.anytype.core_models.StubDataViewViewRelation
|
||||
import com.anytypeio.anytype.core_models.StubFilter
|
||||
import com.anytypeio.anytype.core_models.StubSort
|
||||
import com.anytypeio.anytype.core_models.StubTitle
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
@ -361,4 +368,322 @@ class ObjectSetReducerTest {
|
|||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when getting add, move, update, remove sorts events, should proper update viewer`() {
|
||||
|
||||
val context = MockDataFactory.randomUuid()
|
||||
val title = StubTitle()
|
||||
|
||||
val relationKey1 = MockDataFactory.randomUuid()
|
||||
val relationKey2 = MockDataFactory.randomUuid()
|
||||
val relationKey3 = MockDataFactory.randomUuid()
|
||||
val relationKey4 = MockDataFactory.randomUuid()
|
||||
val relationKey5 = MockDataFactory.randomUuid()
|
||||
val sort1 = StubSort(relationKey = relationKey1)
|
||||
val sort2 = StubSort(relationKey = relationKey2)
|
||||
val sort3 = StubSort(relationKey = relationKey3)
|
||||
val sort4 = StubSort(relationKey = relationKey4)
|
||||
val sort5 = StubSort(relationKey = relationKey5)
|
||||
|
||||
val viewer1 = StubDataViewView(
|
||||
type = Block.Content.DataView.Viewer.Type.BOARD,
|
||||
sorts = listOf(sort1, sort2, sort3, sort4)
|
||||
)
|
||||
val viewer2 = StubDataViewView(
|
||||
type = Block.Content.DataView.Viewer.Type.GRID,
|
||||
sorts = listOf(sort1)
|
||||
)
|
||||
val dataView = StubDataView(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
views = listOf(viewer1, viewer2),
|
||||
sources = listOf(MockDataFactory.randomString())
|
||||
)
|
||||
|
||||
val blocks = listOf(title, dataView)
|
||||
|
||||
val objectSet = ObjectSet(blocks = blocks)
|
||||
|
||||
// TESTING
|
||||
|
||||
val event = Event.Command.DataView.UpdateView(
|
||||
context = context,
|
||||
block = dataView.id,
|
||||
viewerId = viewer1.id,
|
||||
sortUpdates = listOf(
|
||||
Event.Command.DataView.UpdateView.DVSortUpdate.Move(
|
||||
afterId = relationKey3,
|
||||
ids = listOf(relationKey1, relationKey2)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVSortUpdate.Add(
|
||||
afterId = relationKey3,
|
||||
sorts = listOf(sort5)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVSortUpdate.Update(
|
||||
id = relationKey2,
|
||||
sort = DVSort(relationKey2, Block.Content.DataView.Sort.Type.DESC)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVSortUpdate.Remove(
|
||||
ids = listOf(relationKey1)
|
||||
)
|
||||
),
|
||||
filterUpdates = listOf(),
|
||||
relationUpdates = listOf()
|
||||
)
|
||||
|
||||
val result = reducer.reduce(state = objectSet, events = listOf(event))
|
||||
|
||||
val expectedSorts = listOf(
|
||||
DVSort(
|
||||
relationKey = relationKey3,
|
||||
type = Block.Content.DataView.Sort.Type.ASC
|
||||
),
|
||||
DVSort(
|
||||
relationKey = relationKey5,
|
||||
type = Block.Content.DataView.Sort.Type.ASC
|
||||
),
|
||||
DVSort(
|
||||
relationKey = relationKey2,
|
||||
type = Block.Content.DataView.Sort.Type.DESC
|
||||
),
|
||||
DVSort(
|
||||
relationKey = relationKey4,
|
||||
type = Block.Content.DataView.Sort.Type.ASC
|
||||
)
|
||||
)
|
||||
val expectedDataView = Block(
|
||||
id = dataView.id,
|
||||
content = Block.Content.DataView(
|
||||
sources = (dataView.content as Block.Content.DataView).sources,
|
||||
viewers = listOf(
|
||||
Block.Content.DataView.Viewer(
|
||||
id = viewer1.id,
|
||||
name = viewer1.name,
|
||||
type = viewer1.type,
|
||||
viewerRelations = viewer1.viewerRelations,
|
||||
sorts = expectedSorts,
|
||||
filters = viewer1.filters
|
||||
),
|
||||
Block.Content.DataView.Viewer(
|
||||
id = viewer2.id,
|
||||
name = viewer2.name,
|
||||
type = Block.Content.DataView.Viewer.Type.GRID,
|
||||
viewerRelations = viewer2.viewerRelations,
|
||||
sorts = listOf(sort1),
|
||||
filters = listOf()
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
)
|
||||
|
||||
val expected = ObjectSetReducer.Transformation(
|
||||
state = ObjectSet(blocks = listOf(title, expectedDataView)),
|
||||
effects = emptyList()
|
||||
)
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when getting add, move, update, remove filters events, should proper update viewer`() {
|
||||
|
||||
val context = MockDataFactory.randomUuid()
|
||||
val title = StubTitle()
|
||||
|
||||
val relationKey1 = MockDataFactory.randomUuid()
|
||||
val relationKey2 = MockDataFactory.randomUuid()
|
||||
val relationKey3 = MockDataFactory.randomUuid()
|
||||
val relationKey4 = MockDataFactory.randomUuid()
|
||||
val relationKey5 = MockDataFactory.randomUuid()
|
||||
val filter1 = StubFilter(relationKey = relationKey1)
|
||||
val filter2 = StubFilter(relationKey = relationKey2)
|
||||
val filter3 = StubFilter(relationKey = relationKey3)
|
||||
val filter4 = StubFilter(relationKey = relationKey4)
|
||||
val filter5 = StubFilter(relationKey = relationKey5)
|
||||
|
||||
val viewer1 = StubDataViewView(
|
||||
type = Block.Content.DataView.Viewer.Type.BOARD,
|
||||
filters = listOf(filter1, filter2, filter3, filter4)
|
||||
)
|
||||
val dataView = StubDataView(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
views = listOf(viewer1),
|
||||
sources = listOf(MockDataFactory.randomString())
|
||||
)
|
||||
|
||||
val blocks = listOf(title, dataView)
|
||||
|
||||
val objectSet = ObjectSet(blocks = blocks)
|
||||
|
||||
// TESTING
|
||||
|
||||
val filter2Value = MockDataFactory.randomString()
|
||||
val event = Event.Command.DataView.UpdateView(
|
||||
context = context,
|
||||
block = dataView.id,
|
||||
viewerId = viewer1.id,
|
||||
sortUpdates = listOf(),
|
||||
filterUpdates = listOf(
|
||||
Event.Command.DataView.UpdateView.DVFilterUpdate.Move(
|
||||
afterId = relationKey3,
|
||||
ids = listOf(relationKey1, relationKey2)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVFilterUpdate.Add(
|
||||
afterId = relationKey3,
|
||||
filters = listOf(filter5)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVFilterUpdate.Update(
|
||||
id = relationKey2,
|
||||
filter = filter2.copy(
|
||||
value = filter2Value
|
||||
)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVFilterUpdate.Remove(
|
||||
ids = listOf(relationKey1)
|
||||
)
|
||||
),
|
||||
relationUpdates = listOf()
|
||||
)
|
||||
|
||||
val result = reducer.reduce(state = objectSet, events = listOf(event))
|
||||
|
||||
val expectedFilters = listOf(
|
||||
filter3,
|
||||
filter5,
|
||||
filter2.copy(
|
||||
value = filter2Value
|
||||
),
|
||||
filter4
|
||||
)
|
||||
|
||||
val expectedDataView = Block(
|
||||
id = dataView.id,
|
||||
content = Block.Content.DataView(
|
||||
sources = (dataView.content as Block.Content.DataView).sources,
|
||||
viewers = listOf(
|
||||
Block.Content.DataView.Viewer(
|
||||
id = viewer1.id,
|
||||
name = viewer1.name,
|
||||
type = viewer1.type,
|
||||
viewerRelations = viewer1.viewerRelations,
|
||||
sorts = viewer1.sorts,
|
||||
filters = expectedFilters
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
)
|
||||
|
||||
val expected = ObjectSetReducer.Transformation(
|
||||
state = ObjectSet(blocks = listOf(title, expectedDataView)),
|
||||
effects = emptyList()
|
||||
)
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when getting add, move, update, remove relations events, should proper update viewer`() {
|
||||
|
||||
val context = MockDataFactory.randomUuid()
|
||||
val title = StubTitle()
|
||||
|
||||
val relationKey1 = MockDataFactory.randomUuid()
|
||||
val relationKey2 = MockDataFactory.randomUuid()
|
||||
val relationKey3 = MockDataFactory.randomUuid()
|
||||
val relationKey4 = MockDataFactory.randomUuid()
|
||||
val relationKey5 = MockDataFactory.randomUuid()
|
||||
val relation1 = StubDataViewViewRelation(key = relationKey1)
|
||||
val relation2 = StubDataViewViewRelation(key = relationKey2)
|
||||
val relation3 = StubDataViewViewRelation(key = relationKey3)
|
||||
val relation4 = StubDataViewViewRelation(key = relationKey4)
|
||||
val relation5 = StubDataViewViewRelation(key = relationKey5)
|
||||
|
||||
val viewer1 = StubDataViewView(
|
||||
type = Block.Content.DataView.Viewer.Type.BOARD,
|
||||
viewerRelations = listOf(relation1, relation2, relation3, relation4)
|
||||
)
|
||||
val dataView = StubDataView(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
views = listOf(viewer1),
|
||||
sources = listOf(MockDataFactory.randomString())
|
||||
)
|
||||
|
||||
val blocks = listOf(title, dataView)
|
||||
|
||||
val objectSet = ObjectSet(blocks = blocks)
|
||||
|
||||
// TESTING
|
||||
|
||||
val relation2IsVisible = !relation2.isVisible
|
||||
val event = Event.Command.DataView.UpdateView(
|
||||
context = context,
|
||||
block = dataView.id,
|
||||
viewerId = viewer1.id,
|
||||
sortUpdates = listOf(),
|
||||
filterUpdates = listOf(),
|
||||
relationUpdates = listOf(
|
||||
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Move(
|
||||
afterId = relationKey3,
|
||||
ids = listOf(relationKey1, relationKey2)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Add(
|
||||
afterId = relationKey3,
|
||||
relations = listOf(relation5)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Update(
|
||||
id = relationKey2,
|
||||
relation = relation2.copy(
|
||||
isVisible = relation2IsVisible
|
||||
)
|
||||
),
|
||||
Event.Command.DataView.UpdateView.DVViewerRelationUpdate.Remove(
|
||||
ids = listOf(relationKey1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val result = reducer.reduce(state = objectSet, events = listOf(event))
|
||||
|
||||
val expectedRelations = listOf(
|
||||
relation3,
|
||||
relation5,
|
||||
relation2.copy(
|
||||
isVisible = relation2IsVisible
|
||||
),
|
||||
relation4
|
||||
)
|
||||
|
||||
val expectedDataView = Block(
|
||||
id = dataView.id,
|
||||
content = Block.Content.DataView(
|
||||
sources = (dataView.content as Block.Content.DataView).sources,
|
||||
viewers = listOf(
|
||||
Block.Content.DataView.Viewer(
|
||||
id = viewer1.id,
|
||||
name = viewer1.name,
|
||||
type = viewer1.type,
|
||||
viewerRelations = expectedRelations,
|
||||
sorts = viewer1.sorts,
|
||||
filters = viewer1.filters
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
)
|
||||
|
||||
val expected = ObjectSetReducer.Transformation(
|
||||
state = ObjectSet(blocks = listOf(title, expectedDataView)),
|
||||
effects = emptyList()
|
||||
)
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue