1
0
Fork 0
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:
Konstantin Ivanov 2023-01-25 13:27:20 +01:00 committed by GitHub
parent bdd8548695
commit d94b07a338
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 781 additions and 7 deletions

View file

@ -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
}

View file

@ -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 {

View file

@ -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)
}
}