mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3240 Tech | Remove object relation links (#2000)
This commit is contained in:
parent
b3fdf89cbd
commit
c4968c3e4f
56 changed files with 304 additions and 1253 deletions
|
@ -121,7 +121,6 @@ class MentionUpdateTesting : EditorTestSetup() {
|
|||
context = root,
|
||||
root = root,
|
||||
details = customDetails,
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
|
|
|
@ -27,7 +27,6 @@ import com.anytypeio.anytype.domain.block.interactor.CreateBlock
|
|||
import com.anytypeio.anytype.domain.block.interactor.DuplicateBlock
|
||||
import com.anytypeio.anytype.domain.block.interactor.MergeBlocks
|
||||
import com.anytypeio.anytype.domain.block.interactor.Move
|
||||
import com.anytypeio.anytype.domain.block.interactor.MoveOld
|
||||
import com.anytypeio.anytype.domain.block.interactor.RemoveLinkMark
|
||||
import com.anytypeio.anytype.domain.block.interactor.ReplaceBlock
|
||||
import com.anytypeio.anytype.domain.block.interactor.SetObjectType
|
||||
|
@ -403,7 +402,7 @@ open class EditorTestSetup {
|
|||
)
|
||||
|
||||
featureToggles = mock<DefaultFeatureToggles>()
|
||||
addRelationToObject = AddRelationToObject(repo)
|
||||
addRelationToObject = AddRelationToObject(repo, dispatchers)
|
||||
|
||||
interceptFileLimitEvents = InterceptFileLimitEvents(fileLimitsEventChannel, dispatchers)
|
||||
|
||||
|
@ -547,7 +546,6 @@ open class EditorTestSetup {
|
|||
root = root,
|
||||
details = details,
|
||||
blocks = document,
|
||||
relations = relations
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,714 +0,0 @@
|
|||
package com.anytypeio.anytype.features.relations
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.testing.FragmentScenario
|
||||
import androidx.fragment.app.testing.launchFragmentInContainer
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.extensions.dark
|
||||
import com.anytypeio.anytype.core_utils.const.DateConst
|
||||
import com.anytypeio.anytype.core_utils.ext.toTimeSeconds
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.config.Gateway
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
|
||||
import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
||||
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
|
||||
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
|
||||
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
|
||||
import com.anytypeio.anytype.domain.resources.StringResourceProvider
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.editor.Editor
|
||||
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.relations.RelationListViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import com.anytypeio.anytype.test_utils.utils.checkHasText
|
||||
import com.anytypeio.anytype.test_utils.utils.checkHasTextColor
|
||||
import com.anytypeio.anytype.test_utils.utils.checkIsRecyclerSize
|
||||
import com.anytypeio.anytype.test_utils.utils.onItemView
|
||||
import com.anytypeio.anytype.test_utils.utils.rVMatcher
|
||||
import com.anytypeio.anytype.test_utils.utils.resources
|
||||
import com.anytypeio.anytype.ui.relations.ObjectRelationListFragment
|
||||
import com.anytypeio.anytype.utils.CoroutinesTestRule
|
||||
import com.bartoszlipinski.disableanimationsrule.DisableAnimationsRule
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class ObjectRelationListTest {
|
||||
|
||||
@get:Rule
|
||||
val animationsRule = DisableAnimationsRule()
|
||||
|
||||
@get:Rule
|
||||
val coroutineTestRule = CoroutinesTestRule()
|
||||
|
||||
private val spaceId = MockDataFactory.randomUuid()
|
||||
|
||||
@Mock
|
||||
lateinit var gateway: Gateway
|
||||
|
||||
@Mock
|
||||
lateinit var repo: BlockRepository
|
||||
|
||||
@Mock
|
||||
lateinit var dispatcher: Dispatcher<Payload>
|
||||
|
||||
@Mock
|
||||
lateinit var analytics: Analytics
|
||||
|
||||
@Mock
|
||||
lateinit var storeOfRelations: StoreOfRelations
|
||||
|
||||
@Mock
|
||||
lateinit var relationListProvider: RelationListProvider
|
||||
|
||||
@Mock
|
||||
lateinit var addRelationToObject: AddRelationToObject
|
||||
|
||||
@Mock
|
||||
lateinit var lockedStateProvider: LockedStateProvider
|
||||
|
||||
@Mock
|
||||
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
|
||||
private lateinit var updateDetail: UpdateDetail
|
||||
private lateinit var addToFeaturedRelations: AddToFeaturedRelations
|
||||
private lateinit var removeFromFeaturedRelations: RemoveFromFeaturedRelations
|
||||
private lateinit var deleteRelationFromObject: DeleteRelationFromObject
|
||||
|
||||
private val ctx = MockDataFactory.randomUuid()
|
||||
private val storage = Editor.Storage()
|
||||
|
||||
lateinit var urlBuilder: UrlBuilder
|
||||
|
||||
lateinit var fieldParser: FieldParser
|
||||
|
||||
@Mock
|
||||
lateinit var logger: Logger
|
||||
|
||||
@Mock
|
||||
lateinit var dateProvider: DateProvider
|
||||
|
||||
@Mock
|
||||
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp
|
||||
|
||||
@Mock
|
||||
lateinit var stringResourceProvider: StringResourceProvider
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
urlBuilder = UrlBuilder(gateway)
|
||||
updateDetail = UpdateDetail(repo)
|
||||
fieldParser = FieldParserImpl(
|
||||
logger = logger,
|
||||
dateProvider = dateProvider,
|
||||
getDateObjectByTimestamp = getDateObjectByTimestamp,
|
||||
stringResourceProvider = stringResourceProvider
|
||||
)
|
||||
addToFeaturedRelations = AddToFeaturedRelations(repo)
|
||||
removeFromFeaturedRelations = RemoveFromFeaturedRelations(repo)
|
||||
deleteRelationFromObject = DeleteRelationFromObject(repo)
|
||||
TestObjectRelationListFragment.testVmFactory = ObjectRelationListViewModelFactory(
|
||||
vmParams = RelationListViewModel.VmParams(
|
||||
spaceId = SpaceId(spaceId)
|
||||
),
|
||||
lockedStateProvider = lockedStateProvider,
|
||||
relationListProvider = relationListProvider,
|
||||
urlBuilder = urlBuilder,
|
||||
dispatcher = dispatcher,
|
||||
updateDetail = updateDetail,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations,
|
||||
deleteRelationFromObject = deleteRelationFromObject,
|
||||
analytics = analytics,
|
||||
storeOfRelations = storeOfRelations,
|
||||
addRelationToObject = addRelationToObject,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
fieldParser = fieldParser
|
||||
)
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException::class)
|
||||
fun shouldThrowAnExceptionIfArgsNotProvided() {
|
||||
launchFragment(bundleOf())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayOneRelationWithoutValueInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name = "Description"
|
||||
|
||||
val relation = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(
|
||||
listOf(relation)
|
||||
)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText("")
|
||||
checkIsRecyclerSize(2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayOnlyFirstRelationBecauseSecondIsHiddenInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name1 = "Description"
|
||||
val name2 = "Identifier"
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
isHidden = true,
|
||||
name = name1
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(
|
||||
listOf(relation1, relation2)
|
||||
)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText("")
|
||||
checkIsRecyclerSize(2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoRelationsWithoutValueInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name1 = "Description"
|
||||
val name2 = "Comment"
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name1
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(
|
||||
listOf(relation1, relation2)
|
||||
)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText("")
|
||||
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(2, R.id.tvRelationValue).checkHasText("")
|
||||
checkIsRecyclerSize(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoRelationsWithValuesInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name1 = "Description"
|
||||
val name2 = "Comment"
|
||||
val value1 = "A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock."
|
||||
val value2 = "We've never seen that mountain before."
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name1
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.LONG_TEXT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2
|
||||
)
|
||||
|
||||
val relations = listOf(relation1, relation2)
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation1.key to value1,
|
||||
relation2.key to value2,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(
|
||||
bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
)
|
||||
)
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText(value1)
|
||||
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(2, R.id.tvRelationValue).checkHasText(value2)
|
||||
checkIsRecyclerSize(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoObjectRelationsWithNameAndAvatarInitialsInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name1 = "Assignee"
|
||||
val target1: Id = MockDataFactory.randomUuid()
|
||||
val username1 = "Konstantin"
|
||||
|
||||
val name2 = "Created by"
|
||||
val target2: Id = MockDataFactory.randomUuid()
|
||||
val username2 = "Roman"
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.OBJECT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name1
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.OBJECT,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2
|
||||
)
|
||||
|
||||
val relations = listOf(relation1, relation2)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation1.key to target1,
|
||||
relation2.key to target2,
|
||||
)
|
||||
),
|
||||
target1 to Block.Fields(
|
||||
mapOf(
|
||||
Block.Fields.NAME_KEY to username1
|
||||
)
|
||||
),
|
||||
target2 to Block.Fields(
|
||||
mapOf(
|
||||
Block.Fields.NAME_KEY to username2
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
|
||||
onItemView(1, R.id.obj0).check(matches(hasDescendant(withText(username1))))
|
||||
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(2, R.id.obj0).check(matches(hasDescendant(withText(username2))))
|
||||
checkIsRecyclerSize(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoDateRelationsInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val format = SimpleDateFormat(DateConst.DEFAULT_DATE_FORMAT, Locale.getDefault())
|
||||
|
||||
val name1 = "Date of birth"
|
||||
val date1 = System.currentTimeMillis()
|
||||
val date1Screen = format.format(Date(date1))
|
||||
|
||||
val name2 = "Last modified at"
|
||||
val date2 = System.currentTimeMillis()
|
||||
val date2Screen = format.format(Date(date2))
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.DATE,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name1,
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.DATE,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2
|
||||
)
|
||||
|
||||
val relations = listOf(relation1, relation2)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation1.key to date1.toTimeSeconds(),
|
||||
relation2.key to date2.toTimeSeconds(),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText(date1Screen)
|
||||
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(2, R.id.tvRelationValue).checkHasText(date2Screen)
|
||||
checkIsRecyclerSize(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoStatusRelationsInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val color1 = ThemeColor.RED
|
||||
val color2 = ThemeColor.TEAL
|
||||
|
||||
val option1 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "In progress",
|
||||
color = color1.code
|
||||
)
|
||||
|
||||
val option2 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "Done",
|
||||
color = color2.code
|
||||
)
|
||||
|
||||
val name1 = "Status 1"
|
||||
val name2 = "Status 2"
|
||||
|
||||
val relation1 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.STATUS,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name1,
|
||||
selections = listOf(option1)
|
||||
)
|
||||
|
||||
val relation2 = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.STATUS,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name2,
|
||||
selections = listOf(option2)
|
||||
)
|
||||
|
||||
val relations = listOf(relation1, relation2)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation1.key to option1.id,
|
||||
relation2.key to option2.id,
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasText(option1.text)
|
||||
onItemView(1, R.id.tvRelationValue).checkHasTextColor(resources.dark(color1))
|
||||
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
|
||||
onItemView(2, R.id.tvRelationValue).checkHasText(option2.text)
|
||||
onItemView(2, R.id.tvRelationValue).checkHasTextColor(resources.dark(color2))
|
||||
checkIsRecyclerSize(3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayFourTagRelationsInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val color1 = ThemeColor.RED
|
||||
val color2 = ThemeColor.TEAL
|
||||
val color3 = ThemeColor.ICE
|
||||
val color4 = ThemeColor.PURPLE
|
||||
|
||||
val name = "Role"
|
||||
|
||||
val option1 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "Essayist",
|
||||
color = color1.code
|
||||
)
|
||||
|
||||
val option2 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "Journalist",
|
||||
color = color2.code
|
||||
)
|
||||
|
||||
val option3 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "Politik",
|
||||
color = color3.code
|
||||
)
|
||||
|
||||
val option4 = Relation.Option(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
text = "Critic",
|
||||
color = color4.code
|
||||
)
|
||||
|
||||
val relation = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.TAG,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name,
|
||||
selections = listOf(option1, option2, option3, option4)
|
||||
)
|
||||
|
||||
val relations = listOf(relation)
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation.key to listOf(option1.id, option2.id, option3.id, option4.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
|
||||
onItemView(1, R.id.tag0).check(matches((withText(option1.text))))
|
||||
onItemView(1, R.id.tag1).check(matches((withText(option2.text))))
|
||||
onItemView(1, R.id.tag2).check(matches((withText(option3.text))))
|
||||
onItemView(1, R.id.tag3).check(matches((withText(option4.text))))
|
||||
checkIsRecyclerSize(2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldDisplayTwoFileRelationsInsideOtherRelationsSection() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val name = "Attachement"
|
||||
|
||||
val relation = Relation(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = Relation.Format.FILE,
|
||||
source = Relation.Source.values().random(),
|
||||
name = name,
|
||||
selections = emptyList()
|
||||
)
|
||||
|
||||
val relations = listOf(relation)
|
||||
|
||||
val file1 = MockDataFactory.randomUuid()
|
||||
val file2 = MockDataFactory.randomUuid()
|
||||
|
||||
val details = Block.Details(
|
||||
mapOf(
|
||||
ctx to Block.Fields(
|
||||
mapOf(
|
||||
relation.key to listOf(file1, file2)
|
||||
)
|
||||
),
|
||||
file1 to Block.Fields(
|
||||
mapOf(
|
||||
"name" to "Document",
|
||||
"ext" to "pdf",
|
||||
"mime" to "application/pdf"
|
||||
)
|
||||
),
|
||||
file2 to Block.Fields(
|
||||
mapOf(
|
||||
"name" to "Image",
|
||||
"ext" to "jpg",
|
||||
"mime" to "image/jpeg"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
storage.relations.update(relations)
|
||||
storage.details.update(details)
|
||||
}
|
||||
|
||||
launchFragment(bundleOf(
|
||||
ObjectRelationListFragment.ARG_CTX to ctx,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
|
||||
))
|
||||
|
||||
// TESTING
|
||||
|
||||
with(R.id.recycler.rVMatcher()) {
|
||||
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
|
||||
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
|
||||
onItemView(1, R.id.file0).check(matches(hasDescendant(withText("Document"))))
|
||||
onItemView(1, R.id.file1).check(matches(hasDescendant(withText("Image"))))
|
||||
checkIsRecyclerSize(2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchFragment(args: Bundle): FragmentScenario<TestObjectRelationListFragment> {
|
||||
return launchFragmentInContainer(
|
||||
fragmentArgs = args,
|
||||
themeResId = R.style.AppTheme
|
||||
)
|
||||
}
|
||||
}
|
|
@ -360,7 +360,6 @@ abstract class TestObjectSetSetup {
|
|||
root = ctx,
|
||||
details = details,
|
||||
blocks = set,
|
||||
relations = relations
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -383,7 +382,6 @@ abstract class TestObjectSetSetup {
|
|||
root = ctx,
|
||||
details = details,
|
||||
blocks = set,
|
||||
relations = relations,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -116,6 +116,7 @@ import com.anytypeio.anytype.presentation.multiplayer.RequestJoinSpaceViewModel
|
|||
import com.anytypeio.anytype.presentation.multiplayer.ShareSpaceViewModel
|
||||
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
|
||||
import com.anytypeio.anytype.presentation.objects.SelectObjectTypeViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.RelationAddViewModelBase
|
||||
import com.anytypeio.anytype.presentation.relations.RelationListViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.option.CreateOrEditOptionViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.value.`object`.ObjectValueViewModel
|
||||
|
@ -365,7 +366,12 @@ class ComponentManager(
|
|||
editorComponent
|
||||
.get(key = param.ctx, param = param)
|
||||
.objectRelationListComponent()
|
||||
.withVmParams(RelationListViewModel.VmParams(param.space))
|
||||
.withVmParams(
|
||||
RelationListViewModel.VmParams(
|
||||
objectId = param.ctx,
|
||||
spaceId = param.space
|
||||
)
|
||||
)
|
||||
.module(ObjectRelationListModule)
|
||||
.build()
|
||||
}
|
||||
|
@ -374,7 +380,12 @@ class ComponentManager(
|
|||
objectSetComponent
|
||||
.get(key = param.ctx, param = param)
|
||||
.objectRelationListComponent()
|
||||
.withVmParams(RelationListViewModel.VmParams(param.space))
|
||||
.withVmParams(
|
||||
RelationListViewModel.VmParams(
|
||||
objectId = param.ctx,
|
||||
spaceId = param.space
|
||||
)
|
||||
)
|
||||
.module(ObjectRelationListModule)
|
||||
.build()
|
||||
}
|
||||
|
@ -577,6 +588,12 @@ class ComponentManager(
|
|||
editorComponent
|
||||
.get(key = param.ctx, param = param)
|
||||
.relationAddToObjectComponent()
|
||||
.withVmParams(
|
||||
vmParams = RelationAddViewModelBase.VmParams(
|
||||
objectId = param.ctx,
|
||||
space = param.space
|
||||
)
|
||||
)
|
||||
.module(RelationAddToObjectModule)
|
||||
.build()
|
||||
}
|
||||
|
@ -585,6 +602,12 @@ class ComponentManager(
|
|||
objectSetComponent
|
||||
.get(key = param.ctx, param = param)
|
||||
.relationAddToObjectComponent()
|
||||
.withVmParams(
|
||||
vmParams = RelationAddViewModelBase.VmParams(
|
||||
objectId = param.ctx,
|
||||
space = param.space
|
||||
)
|
||||
)
|
||||
.module(RelationAddToObjectModule)
|
||||
.build()
|
||||
}
|
||||
|
@ -593,6 +616,12 @@ class ComponentManager(
|
|||
objectSetComponent
|
||||
.get(key = param.ctx, param = param)
|
||||
.relationAddToDataViewComponent()
|
||||
.withVmParams(
|
||||
vmParams = RelationAddViewModelBase.VmParams(
|
||||
objectId = param.ctx,
|
||||
space = param.space
|
||||
)
|
||||
)
|
||||
.module(RelationAddToDataViewModule)
|
||||
.build()
|
||||
}
|
||||
|
|
|
@ -1010,7 +1010,8 @@ object EditorUseCaseModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideAddRelationToObject(repo: BlockRepository) = AddRelationToObject(repo)
|
||||
fun provideAddRelationToObject(repo: BlockRepository, dispatchers: AppCoroutineDispatchers) =
|
||||
AddRelationToObject(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
|
|
@ -579,7 +579,8 @@ object ObjectSetModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideAddRelationToObject(repo: BlockRepository) = AddRelationToObject(repo)
|
||||
fun provideAddRelationToObject(repo: BlockRepository, dispatchers: AppCoroutineDispatchers)
|
||||
: AddRelationToObject = AddRelationToObject(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
|
|
@ -11,10 +11,10 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
|||
import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
||||
import com.anytypeio.anytype.domain.relations.GetRelations
|
||||
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.relations.RelationAddToDataViewViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.RelationAddToObjectViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.RelationAddViewModelBase
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.DATA_VIEW_PROVIDER_TYPE
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.INTRINSIC_PROVIDER_TYPE
|
||||
|
@ -23,6 +23,7 @@ import com.anytypeio.anytype.presentation.util.Dispatcher
|
|||
import com.anytypeio.anytype.ui.relations.RelationAddToDataViewFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationAddToObjectBlockFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationAddToObjectFragment
|
||||
import dagger.BindsInstance
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
|
@ -35,6 +36,8 @@ interface RelationAddToObjectSubComponent {
|
|||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
fun withVmParams(vmParams: RelationAddViewModelBase.VmParams) : Builder
|
||||
fun module(module: RelationAddToObjectModule): Builder
|
||||
fun build(): RelationAddToObjectSubComponent
|
||||
}
|
||||
|
@ -49,6 +52,7 @@ object RelationAddToObjectModule {
|
|||
@Provides
|
||||
@PerDialog
|
||||
fun provideViewModelFactory(
|
||||
vmParams: RelationAddViewModelBase.VmParams,
|
||||
addRelationToObject: AddRelationToObject,
|
||||
storeOfRelations: StoreOfRelations,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
|
@ -57,9 +61,9 @@ object RelationAddToObjectModule {
|
|||
getRelations: GetRelations,
|
||||
appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
addObjectToWorkspace: AddObjectToWorkspace,
|
||||
spaceManager: SpaceManager,
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
): RelationAddToObjectViewModel.Factory = RelationAddToObjectViewModel.Factory(
|
||||
vmParams = vmParams,
|
||||
storeOfRelations = storeOfRelations,
|
||||
addRelationToObject = addRelationToObject,
|
||||
dispatcher = dispatcher,
|
||||
|
@ -68,7 +72,6 @@ object RelationAddToObjectModule {
|
|||
getRelations = getRelations,
|
||||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
)
|
||||
|
||||
|
@ -95,6 +98,8 @@ interface RelationAddToDataViewSubComponent {
|
|||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
@BindsInstance
|
||||
fun withVmParams(vmParams: RelationAddViewModelBase.VmParams) : Builder
|
||||
fun module(module: RelationAddToDataViewModule): Builder
|
||||
fun build(): RelationAddToDataViewSubComponent
|
||||
}
|
||||
|
@ -109,6 +114,7 @@ object RelationAddToDataViewModule {
|
|||
@Provides
|
||||
@PerDialog
|
||||
fun provideViewModelFactory(
|
||||
vmParams: RelationAddViewModelBase.VmParams,
|
||||
addRelationToDataView: AddRelationToDataView,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
state: MutableStateFlow<ObjectState>,
|
||||
|
@ -118,7 +124,6 @@ object RelationAddToDataViewModule {
|
|||
appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
getRelations: GetRelations,
|
||||
addObjectToWorkspace: AddObjectToWorkspace,
|
||||
spaceManager: SpaceManager,
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
storeOfRelations: StoreOfRelations
|
||||
): RelationAddToDataViewViewModel.Factory = RelationAddToDataViewViewModel.Factory(
|
||||
|
@ -131,9 +136,9 @@ object RelationAddToDataViewModule {
|
|||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
getRelations = getRelations,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
storeOfRelations = storeOfRelations
|
||||
storeOfRelations = storeOfRelations,
|
||||
vmParams = vmParams
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -1069,17 +1069,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
SelectProgrammingLanguageFragment.new(command.target)
|
||||
.showChildFragment()
|
||||
}
|
||||
is Command.OpenObjectRelationScreen.RelationAdd -> {
|
||||
hideKeyboard()
|
||||
ObjectRelationListFragment
|
||||
.new(
|
||||
ctx = command.ctx,
|
||||
space = space,
|
||||
target = command.target,
|
||||
mode = ObjectRelationListFragment.MODE_ADD,
|
||||
)
|
||||
.showChildFragment()
|
||||
}
|
||||
is Command.OpenObjectRelationScreen.RelationList -> {
|
||||
hideKeyboard()
|
||||
findNavController().safeNavigate(
|
||||
|
@ -1090,7 +1079,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
ObjectRelationListFragment.ARG_SPACE to space,
|
||||
ObjectRelationListFragment.ARG_TARGET to command.target,
|
||||
ObjectRelationListFragment.ARG_LOCKED to command.isLocked,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -229,7 +229,6 @@ abstract class ObjectMenuBaseFragment :
|
|||
ObjectRelationListFragment.ARG_SPACE to space,
|
||||
ObjectRelationListFragment.ARG_TARGET to null,
|
||||
ObjectRelationListFragment.ARG_LOCKED to isLocked,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
|
||||
ObjectRelationListFragment.ARG_SET_FLOW to false
|
||||
)
|
||||
)
|
||||
|
@ -243,7 +242,6 @@ abstract class ObjectMenuBaseFragment :
|
|||
ObjectRelationListFragment.ARG_SPACE to space,
|
||||
ObjectRelationListFragment.ARG_TARGET to null,
|
||||
ObjectRelationListFragment.ARG_LOCKED to isLocked,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
|
||||
ObjectRelationListFragment.ARG_SET_FLOW to true
|
||||
)
|
||||
)
|
||||
|
|
|
@ -16,9 +16,7 @@ import com.anytypeio.anytype.core_models.Key
|
|||
import com.anytypeio.anytype.core_models.TimeInMillis
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.features.relations.DocumentRelationAdapter
|
||||
import com.anytypeio.anytype.core_ui.reactive.textChanges
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.argInt
|
||||
import com.anytypeio.anytype.core_utils.ext.argString
|
||||
import com.anytypeio.anytype.core_utils.ext.argStringOrNull
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
|
@ -41,8 +39,6 @@ import com.anytypeio.anytype.ui.editor.OnFragmentInteractionListener
|
|||
import com.anytypeio.anytype.ui.relations.value.ObjectValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.value.TagOrStatusValueFragment
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import timber.log.Timber
|
||||
|
||||
open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelationListBinding>(),
|
||||
|
@ -60,7 +56,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
private val ctx: String get() = argString(ARG_CTX)
|
||||
private val space: String get() = argString(ARG_SPACE)
|
||||
private val target: String? get() = argStringOrNull(ARG_TARGET)
|
||||
private val mode: Int get() = argInt(ARG_MODE)
|
||||
private val isLocked: Boolean get() = arg(ARG_LOCKED)
|
||||
private val isSetFlow: Boolean get() = arg(ARG_SET_FLOW)
|
||||
|
||||
|
@ -214,37 +209,10 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
binding.btnEditOrDone.setText(R.string.edit)
|
||||
}
|
||||
}
|
||||
if (mode == MODE_ADD) {
|
||||
binding.searchBar.root.visible()
|
||||
val queries = searchRelationInput.textChanges()
|
||||
.onStart { emit(searchRelationInput.text.toString()) }
|
||||
val views = vm.views.combine(queries) { views, query ->
|
||||
if (views.isEmpty()) {
|
||||
views
|
||||
} else {
|
||||
views.filter { model ->
|
||||
if (model is RelationListViewModel.Model.Item) {
|
||||
model.view.name.contains(query, true)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += lifecycleScope.subscribe(searchRelationInput.textChanges()) {
|
||||
if (it.isEmpty()) clearSearchText.invisible() else clearSearchText.visible()
|
||||
}
|
||||
jobs += lifecycleScope.subscribe(views) { docRelationAdapter.update(it) }
|
||||
} else {
|
||||
binding.searchBar.root.gone()
|
||||
jobs += lifecycleScope.subscribe(vm.views) { docRelationAdapter.update(it) }
|
||||
}
|
||||
binding.searchBar.root.gone()
|
||||
jobs += lifecycleScope.subscribe(vm.views) { docRelationAdapter.update(it) }
|
||||
super.onStart()
|
||||
if (mode == MODE_LIST) {
|
||||
vm.onStartListMode(ctx)
|
||||
} else {
|
||||
vm.onStartAddMode(ctx)
|
||||
}
|
||||
vm.onStartListMode(ctx)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -325,7 +293,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
ctx: Id,
|
||||
space: Id,
|
||||
target: String?,
|
||||
mode: Int,
|
||||
locked: Boolean = false,
|
||||
isSetFlow: Boolean = false,
|
||||
) = ObjectRelationListFragment().apply {
|
||||
|
@ -333,7 +300,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
ARG_CTX to ctx,
|
||||
ARG_SPACE to space,
|
||||
ARG_TARGET to target,
|
||||
ARG_MODE to mode,
|
||||
ARG_LOCKED to locked,
|
||||
ARG_SET_FLOW to isSetFlow
|
||||
)
|
||||
|
@ -341,11 +307,8 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
|
||||
const val ARG_CTX = "arg.document-relation.ctx"
|
||||
const val ARG_SPACE = "arg.document-relation.space"
|
||||
const val ARG_MODE = "arg.document-relation.mode"
|
||||
const val ARG_TARGET = "arg.document-relation.target"
|
||||
const val ARG_LOCKED = "arg.document-relation.locked"
|
||||
const val MODE_ADD = 1
|
||||
const val MODE_LIST = 2
|
||||
const val ARG_SET_FLOW = "arg.document-relation.set-flow"
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ import com.anytypeio.anytype.R
|
|||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.features.relations.RelationAddAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.relations.RelationAddHeaderAdapter
|
||||
|
|
|
@ -24,8 +24,6 @@ sealed class Event {
|
|||
val root: Id,
|
||||
val details: Block.Details = Block.Details(emptyMap()),
|
||||
val blocks: List<Block>,
|
||||
val relations: List<Relation> = emptyList(),
|
||||
val relationLinks: List<RelationLink> = emptyList(),
|
||||
val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
val dataViewRestrictions: List<DataViewRestrictions> = emptyList()
|
||||
) : Command()
|
||||
|
@ -193,32 +191,11 @@ sealed class Event {
|
|||
val style: Block.Content.Divider.Style
|
||||
) : Command()
|
||||
|
||||
sealed class ObjectRelationLinks : Command() {
|
||||
data class Amend(
|
||||
override val context: String,
|
||||
val id: Id,
|
||||
val relationLinks: List<RelationLink>
|
||||
) : ObjectRelationLinks()
|
||||
|
||||
sealed class ObjectRelation : Command() {
|
||||
data class Remove(
|
||||
override val context: String,
|
||||
val id: Id,
|
||||
val keys: List<Key>
|
||||
) : ObjectRelationLinks()
|
||||
}
|
||||
|
||||
sealed class ObjectRelation : Command() {
|
||||
data class Set(
|
||||
override val context: String,
|
||||
val id: Id,
|
||||
val key: Id,
|
||||
val relations: List<Relation>
|
||||
) : ObjectRelation()
|
||||
|
||||
data class Remove(
|
||||
override val context: String,
|
||||
val id: Id,
|
||||
val key: Id
|
||||
) : ObjectRelation()
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ data class ObjectView(
|
|||
val root: Id,
|
||||
val blocks: List<Block>,
|
||||
val details: Map<Id, Struct>,
|
||||
val relations: List<RelationLink>,
|
||||
val objectRestrictions: List<ObjectRestriction>,
|
||||
val dataViewRestrictions: List<DataViewRestrictions>
|
||||
)
|
|
@ -1,17 +1,9 @@
|
|||
package com.anytypeio.anytype.core_models.ext
|
||||
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
|
||||
fun List<RelationLink>.process(
|
||||
event: Event.Command.ObjectRelationLinks
|
||||
): List<RelationLink> = when (event) {
|
||||
is Event.Command.ObjectRelationLinks.Amend -> amend(event.relationLinks)
|
||||
is Event.Command.ObjectRelationLinks.Remove -> remove(event.keys)
|
||||
}
|
||||
|
||||
fun List<RelationLink>.amend(relationLinks: List<RelationLink>): List<RelationLink> {
|
||||
val map = this.associateBy { it.key }.toMutableMap()
|
||||
relationLinks.forEach { relation ->
|
||||
|
|
|
@ -458,7 +458,7 @@ class BlockDataRepository(
|
|||
|
||||
override suspend fun addRelationToObject(
|
||||
ctx: Id, relation: Id
|
||||
): Payload = remote.addRelationToObject(ctx, relation)
|
||||
): Payload? = remote.addRelationToObject(ctx, relation)
|
||||
|
||||
override suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload {
|
||||
return remote.deleteRelationFromObject(ctx = ctx, relation = relation)
|
||||
|
|
|
@ -189,7 +189,7 @@ interface BlockRemote {
|
|||
|
||||
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
|
||||
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
|
||||
|
||||
suspend fun debugSpace(space: SpaceId): String
|
||||
|
|
|
@ -229,7 +229,7 @@ interface BlockRepository {
|
|||
|
||||
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
|
||||
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
|
||||
|
||||
suspend fun debugSpace(space: SpaceId): String
|
||||
|
|
|
@ -3,18 +3,20 @@ package com.anytypeio.anytype.domain.relations
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
/**
|
||||
* Use-case for adding a relation to an object.
|
||||
*/
|
||||
class AddRelationToObject(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Payload, AddRelationToObject.Params>() {
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<AddRelationToObject.Params, Payload?>(dispatchers.io) {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
repo.addRelationToObject(
|
||||
override suspend fun doWork(params: Params): Payload? {
|
||||
return repo.addRelationToObject(
|
||||
ctx = params.ctx,
|
||||
relation = params.relationKey
|
||||
)
|
||||
|
|
|
@ -413,7 +413,7 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun addRelationToObject(
|
||||
ctx: Id, relation: Key
|
||||
): Payload = middleware.objectRelationAdd(ctx, relation)
|
||||
): Payload? = middleware.objectRelationAdd(ctx, relation)
|
||||
|
||||
override suspend fun deleteRelationFromObject(
|
||||
ctx: Id,
|
||||
|
|
|
@ -1122,7 +1122,7 @@ class Middleware @Inject constructor(
|
|||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun objectRelationAdd(ctx: Id, relation: Key): Payload {
|
||||
fun objectRelationAdd(ctx: Id, relation: Key): Payload? {
|
||||
val request = Rpc.ObjectRelation.Add.Request(
|
||||
contextId = ctx,
|
||||
relationKeys = listOf(relation)
|
||||
|
@ -1130,7 +1130,7 @@ class Middleware @Inject constructor(
|
|||
logRequestIfDebug(request)
|
||||
val (response, time) = measureTimedValue { service.objectRelationAdd(request) }
|
||||
logResponseIfDebug(response, time)
|
||||
return response.event.toPayload()
|
||||
return response.event?.toPayload()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
|
|
@ -237,19 +237,10 @@ fun anytype.Event.Message.toCoreModels(
|
|||
key = event.key?.value_
|
||||
)
|
||||
}
|
||||
objectRelationsAmend != null -> {
|
||||
val event = objectRelationsAmend
|
||||
checkNotNull(event)
|
||||
Event.Command.ObjectRelationLinks.Amend(
|
||||
context = context,
|
||||
id = event.id,
|
||||
relationLinks = event.relationLinks.map { it.toCoreModels() }
|
||||
)
|
||||
}
|
||||
objectRelationsRemove != null -> {
|
||||
val event = objectRelationsRemove
|
||||
checkNotNull(event)
|
||||
Event.Command.ObjectRelationLinks.Remove(
|
||||
Event.Command.ObjectRelation.Remove(
|
||||
context = context,
|
||||
id = event.id,
|
||||
keys = event.relationKeys
|
||||
|
|
|
@ -46,7 +46,6 @@ import com.anytypeio.anytype.core_models.RelationLink
|
|||
import com.anytypeio.anytype.core_models.RelationListWithValueItem
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.SpaceUsage
|
||||
import com.anytypeio.anytype.core_models.TimeInSeconds
|
||||
import com.anytypeio.anytype.core_models.chats.Chat
|
||||
import com.anytypeio.anytype.core_models.history.DiffVersionResponse
|
||||
import com.anytypeio.anytype.core_models.history.ShowVersionResponse
|
||||
|
@ -95,7 +94,6 @@ fun MObjectView.toPayload(): Payload {
|
|||
details.id to details.details.toCoreModel()
|
||||
}
|
||||
),
|
||||
relationLinks = relationLinks.map { it.toCoreModels() },
|
||||
objectRestrictions = restrictions?.object_?.map { it.toCoreModel() }.orEmpty(),
|
||||
dataViewRestrictions = restrictions?.dataview?.map { it.toCoreModel() }.orEmpty()
|
||||
)
|
||||
|
@ -108,7 +106,6 @@ fun MObjectView.toCore(): ObjectView {
|
|||
root = rootId,
|
||||
blocks = blocks.toCoreModels(),
|
||||
details = details.associate { d -> d.id to d.details.orEmpty() },
|
||||
relations = relationLinks.map { it.toCoreModels() },
|
||||
objectRestrictions = restrictions?.object_?.map { it.toCoreModel() }.orEmpty(),
|
||||
dataViewRestrictions = restrictions?.dataview?.map { it.toCoreModel() }.orEmpty(),
|
||||
)
|
||||
|
|
|
@ -2,13 +2,10 @@ package com.anytypeio.anytype
|
|||
|
||||
import anytype.model.Block
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.middleware.interactor.MiddlewareEventChannel
|
||||
import com.anytypeio.anytype.middleware.mappers.MRelationLink
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -315,63 +312,6 @@ class MiddlewareEventChannelTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return amend relation links event`() {
|
||||
|
||||
val context = MockDataFactory.randomUuid()
|
||||
|
||||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
val relationLink1 = MRelationLink(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = anytype.model.RelationFormat.longtext
|
||||
)
|
||||
|
||||
val relationLink2 = MRelationLink(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = anytype.model.RelationFormat.longtext
|
||||
)
|
||||
|
||||
val relationLink3 = MRelationLink(
|
||||
key = MockDataFactory.randomUuid(),
|
||||
format = anytype.model.RelationFormat.longtext
|
||||
)
|
||||
|
||||
val msg = anytype.Event.Object.Relations.Amend(
|
||||
id = id,
|
||||
relationLinks = listOf(relationLink1, relationLink2, relationLink3)
|
||||
)
|
||||
|
||||
val message = anytype.Event.Message(objectRelationsAmend = msg)
|
||||
|
||||
val event = anytype.Event(contextId = context, messages = listOf(message))
|
||||
|
||||
proxy.stub {
|
||||
on { flow() } doReturn flowOf(event)
|
||||
}
|
||||
|
||||
val expected = listOf(
|
||||
Event.Command.ObjectRelationLinks.Amend(
|
||||
context = context,
|
||||
id = id,
|
||||
relationLinks = listOf(
|
||||
RelationLink(key = relationLink1.key, format = RelationFormat.LONG_TEXT),
|
||||
RelationLink(key = relationLink2.key, format = RelationFormat.LONG_TEXT),
|
||||
RelationLink(key = relationLink3.key, format = RelationFormat.LONG_TEXT)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
runBlocking {
|
||||
channel.observeEvents(context = context).collect { events ->
|
||||
assertEquals(
|
||||
expected = expected,
|
||||
actual = events
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return remove relation links event`() {
|
||||
|
||||
|
@ -397,7 +337,7 @@ class MiddlewareEventChannelTest {
|
|||
}
|
||||
|
||||
val expected = listOf(
|
||||
Event.Command.ObjectRelationLinks.Remove(
|
||||
Event.Command.ObjectRelation.Remove(
|
||||
context = context,
|
||||
id = id,
|
||||
keys = listOf(id1, id2, id3)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.anytypeio.anytype.presentation.editor
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Document
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.editor.Editor
|
||||
import com.anytypeio.anytype.domain.editor.Editor.Focus
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Proxy
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Store
|
||||
import com.anytypeio.anytype.presentation.editor.editor.actions.ActionItemType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -101,11 +99,8 @@ interface Editor {
|
|||
val focus: Store<Focus> = Store.Focus()
|
||||
val details: Store.Details = Store.Details()
|
||||
|
||||
@Deprecated("legacy")
|
||||
val relations: Store.Relations = Store.Relations()
|
||||
val textSelection: Store<Editor.TextSelection> = Store.TextSelection()
|
||||
val objectRestrictions: Store.ObjectRestrictions = Store.ObjectRestrictions()
|
||||
val relationLinks: Store.RelationLinks = Store.RelationLinks()
|
||||
}
|
||||
|
||||
class Proxer(
|
||||
|
|
|
@ -599,15 +599,11 @@ class EditorViewModel(
|
|||
when (event) {
|
||||
is Event.Command.ShowObject -> {
|
||||
orchestrator.stores.details.update(event.details)
|
||||
orchestrator.stores.relationLinks.update(event.relationLinks)
|
||||
orchestrator.stores.objectRestrictions.update(event.objectRestrictions)
|
||||
}
|
||||
is Event.Command.Details -> {
|
||||
orchestrator.stores.details.apply { update(current().process(event)) }
|
||||
}
|
||||
is Event.Command.ObjectRelationLinks -> {
|
||||
orchestrator.stores.relationLinks.apply { update(current().process(event)) }
|
||||
}
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
|
@ -792,7 +788,6 @@ class EditorViewModel(
|
|||
anchor = context,
|
||||
indent = INITIAL_INDENT,
|
||||
details = details,
|
||||
relationLinks = orchestrator.stores.relationLinks.current(),
|
||||
restrictions = orchestrator.stores.objectRestrictions.current(),
|
||||
selection = currentSelection()
|
||||
) { onRenderFlagFound -> flags.add(onRenderFlagFound) }
|
||||
|
@ -3994,12 +3989,9 @@ class EditorViewModel(
|
|||
}
|
||||
is ListenerType.Relation.Placeholder -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> dispatch(
|
||||
Command.OpenObjectRelationScreen.RelationAdd(
|
||||
ctx = context,
|
||||
target = clicked.target
|
||||
)
|
||||
)
|
||||
EditorMode.Edit -> {
|
||||
sendToast(NOT_ALLOWED_FOR_RELATION)
|
||||
}
|
||||
else -> onBlockMultiSelectClicked(clicked.target)
|
||||
}
|
||||
}
|
||||
|
@ -5237,13 +5229,11 @@ class EditorViewModel(
|
|||
val objectDetails = details.details[context]?.map ?: emptyMap()
|
||||
val objectWrapper = ObjectWrapper.Basic(objectDetails)
|
||||
val objectType = objectWrapper.getProperType()
|
||||
val relationLinks = orchestrator.stores.relationLinks.current()
|
||||
|
||||
viewModelScope.launch {
|
||||
val objectRelationViews = getObjectRelationsView(
|
||||
ctx = context,
|
||||
objectDetails = objectDetails,
|
||||
relationLinks = relationLinks,
|
||||
details = details,
|
||||
objectWrapper = objectWrapper
|
||||
)
|
||||
|
@ -5251,7 +5241,6 @@ class EditorViewModel(
|
|||
val recommendedRelationViews = getRecommendedRelations(
|
||||
ctx = context,
|
||||
objectDetails = objectDetails,
|
||||
relationLinks = relationLinks,
|
||||
objectTypeStruct = details.details[objectType]?.map,
|
||||
details = details
|
||||
)
|
||||
|
@ -5265,14 +5254,13 @@ class EditorViewModel(
|
|||
private suspend fun getObjectRelationsView(
|
||||
ctx: Id,
|
||||
objectDetails: Map<Key, Any?>,
|
||||
relationLinks: List<RelationLink>,
|
||||
details: Block.Details,
|
||||
objectWrapper: ObjectWrapper.Basic
|
||||
): List<ObjectRelationView> {
|
||||
return getObjectRelations(
|
||||
systemRelations = listOf(),
|
||||
relationLinks = relationLinks,
|
||||
storeOfRelations = storeOfRelations
|
||||
storeOfRelations = storeOfRelations,
|
||||
relationKeys = objectDetails.keys
|
||||
).views(
|
||||
context = ctx,
|
||||
details = details,
|
||||
|
@ -5286,16 +5274,15 @@ class EditorViewModel(
|
|||
private suspend fun getRecommendedRelations(
|
||||
ctx: Id,
|
||||
objectDetails: Map<Key, Any?>,
|
||||
relationLinks: List<RelationLink>,
|
||||
objectTypeStruct: Struct?,
|
||||
details: Block.Details
|
||||
): List<ObjectRelationView> {
|
||||
val objType = objectTypeStruct?.mapToObjectWrapperType()
|
||||
val recommendedRelations = objType?.recommendedRelations ?: emptyList()
|
||||
return getNotIncludedRecommendedRelations(
|
||||
relationLinks = relationLinks,
|
||||
recommendedRelations = recommendedRelations,
|
||||
storeOfRelations = storeOfRelations
|
||||
storeOfRelations = storeOfRelations,
|
||||
relationKeys = objectDetails.keys
|
||||
).views(
|
||||
context = ctx,
|
||||
details = details,
|
||||
|
@ -7409,8 +7396,8 @@ class EditorViewModel(
|
|||
private fun checkRelationIsInObject(
|
||||
view: ObjectRelationView
|
||||
): Boolean {
|
||||
val relationLinks = orchestrator.stores.relationLinks.current()
|
||||
return relationLinks.any { it.key == view.key }
|
||||
val currentObjectDetails = orchestrator.stores.details.getAsObject(vmParams.ctx)
|
||||
return currentObjectDetails?.map?.keys?.any { it == view.key } ?: false
|
||||
}
|
||||
|
||||
private suspend fun proceedWithAddingRelationToObject(
|
||||
|
@ -7422,10 +7409,10 @@ class EditorViewModel(
|
|||
ctx = ctx,
|
||||
relationKey = view.key
|
||||
)
|
||||
addRelationToObject.run(params).process(
|
||||
failure = { Timber.e(it, "Error while adding relation to object") },
|
||||
success = {
|
||||
dispatcher.send(it)
|
||||
addRelationToObject.async(params).fold(
|
||||
onFailure = { e -> Timber.e(e, "Error while adding relation to object") },
|
||||
onSuccess = { payload ->
|
||||
if (payload != null) dispatcher.send(payload)
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
|
|
@ -92,7 +92,6 @@ sealed class Command {
|
|||
val isLocked: Boolean
|
||||
) : OpenObjectRelationScreen()
|
||||
|
||||
data class RelationAdd(val ctx: String, val target: String) : OpenObjectRelationScreen()
|
||||
sealed class Value : OpenObjectRelationScreen() {
|
||||
abstract val isReadOnlyValue: Boolean
|
||||
data class Text(
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.anytypeio.anytype.presentation.editor.render
|
|||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
import com.anytypeio.anytype.domain.editor.Editor
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
@ -29,7 +28,6 @@ interface BlockViewRenderer {
|
|||
anchor: Id,
|
||||
indent: Int,
|
||||
details: Block.Details = Block.Details(emptyMap()),
|
||||
relationLinks: List<RelationLink>,
|
||||
restrictions: List<ObjectRestriction>,
|
||||
selection: Set<Id>,
|
||||
count: Int = 0,
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.anytypeio.anytype.core_models.Key
|
|||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds.BOOKMARK
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.parseThemeTextColor
|
||||
|
@ -65,7 +64,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor: Id,
|
||||
indent: Int,
|
||||
details: Block.Details,
|
||||
relationLinks: List<RelationLink>,
|
||||
restrictions: List<ObjectRestriction>,
|
||||
selection: Set<Id>,
|
||||
count: Int,
|
||||
|
@ -128,7 +126,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -174,7 +171,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -212,7 +208,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -253,7 +248,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -294,7 +288,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -335,7 +328,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -379,7 +371,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -416,7 +407,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -475,7 +465,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -515,7 +504,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -560,7 +548,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent.inc(),
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
onRenderFlag = onRenderFlag,
|
||||
|
@ -682,7 +669,6 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
anchor = block.id,
|
||||
indent = indent,
|
||||
details = details,
|
||||
relationLinks = relationLinks,
|
||||
restrictions = restrictions,
|
||||
selection = selection,
|
||||
count = mCounter,
|
||||
|
|
|
@ -536,7 +536,6 @@ class VersionHistoryViewModel(
|
|||
anchor = vmParams.objectId,
|
||||
indent = INITIAL_INDENT,
|
||||
details = event.details,
|
||||
relationLinks = event.relationLinks,
|
||||
restrictions = event.objectRestrictions,
|
||||
selection = emptySet()
|
||||
).filterNot { it is BlockView.DataView }
|
||||
|
@ -574,7 +573,6 @@ class VersionHistoryViewModel(
|
|||
anchor = vmParams.objectId,
|
||||
indent = INITIAL_INDENT,
|
||||
details = event.details,
|
||||
relationLinks = event.relationLinks,
|
||||
restrictions = event.objectRestrictions,
|
||||
selection = emptySet()
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVViewerRelation
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
|
||||
|
@ -17,7 +16,6 @@ import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
|
|||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.relations.GetRelations
|
||||
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationEvent
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
|
||||
|
@ -31,6 +29,7 @@ import timber.log.Timber
|
|||
|
||||
class RelationAddToDataViewViewModel(
|
||||
relationsProvider: ObjectRelationProvider,
|
||||
val vmParams: VmParams,
|
||||
private val objectState: StateFlow<ObjectState>,
|
||||
private val updateDataViewViewer: UpdateDataViewViewer,
|
||||
private val addRelationToDataView: AddRelationToDataView,
|
||||
|
@ -39,15 +38,14 @@ class RelationAddToDataViewViewModel(
|
|||
private val analytics: Analytics,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val storeOfRelations: StoreOfRelations
|
||||
) : RelationAddViewModelBase(
|
||||
vmParams = vmParams,
|
||||
relationsProvider = relationsProvider,
|
||||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
getRelations = getRelations,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager
|
||||
) {
|
||||
|
||||
fun onRelationSelected(
|
||||
|
@ -78,7 +76,7 @@ class RelationAddToDataViewViewModel(
|
|||
storeOfRelations = storeOfRelations,
|
||||
relationKey = relation,
|
||||
type = screenType,
|
||||
spaceParams = analyticSpaceHelperDelegate.provideParams(spaceManager.get())
|
||||
spaceParams = analyticSpaceHelperDelegate.provideParams(vmParams.space.id)
|
||||
)
|
||||
},
|
||||
failure = {
|
||||
|
@ -110,6 +108,7 @@ class RelationAddToDataViewViewModel(
|
|||
}
|
||||
|
||||
class Factory(
|
||||
private val vmParams: VmParams,
|
||||
private val state: StateFlow<ObjectState>,
|
||||
private val updateDataViewViewer: UpdateDataViewViewer,
|
||||
private val addRelationToDataView: AddRelationToDataView,
|
||||
|
@ -119,13 +118,13 @@ class RelationAddToDataViewViewModel(
|
|||
private val appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
private val getRelations: GetRelations,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val storeOfRelations: StoreOfRelations
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return RelationAddToDataViewViewModel(
|
||||
vmParams = vmParams,
|
||||
addRelationToDataView = addRelationToDataView,
|
||||
dispatcher = dispatcher,
|
||||
updateDataViewViewer = updateDataViewViewer,
|
||||
|
@ -135,7 +134,6 @@ class RelationAddToDataViewViewModel(
|
|||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
getRelations = getRelations,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
storeOfRelations = storeOfRelations
|
||||
) as T
|
||||
|
|
|
@ -8,14 +8,12 @@ import com.anytypeio.anytype.analytics.base.EventsDictionary
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
||||
import com.anytypeio.anytype.domain.relations.GetRelations
|
||||
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationEvent
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
|
||||
|
@ -26,6 +24,7 @@ import timber.log.Timber
|
|||
|
||||
class RelationAddToObjectViewModel(
|
||||
relationsProvider: ObjectRelationProvider,
|
||||
val vmParams: VmParams,
|
||||
private val addRelationToObject: AddRelationToObject,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val analytics: Analytics,
|
||||
|
@ -34,13 +33,12 @@ class RelationAddToObjectViewModel(
|
|||
appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
getRelations: GetRelations,
|
||||
addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val spaceManager: SpaceManager
|
||||
) : RelationAddViewModelBase(
|
||||
vmParams = vmParams,
|
||||
relationsProvider = relationsProvider,
|
||||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
getRelations = getRelations,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager
|
||||
), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
|
||||
|
||||
val commands = MutableSharedFlow<Command>(replay = 0)
|
||||
|
@ -51,26 +49,24 @@ class RelationAddToObjectViewModel(
|
|||
screenType: String
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
addRelationToObject(
|
||||
AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relation
|
||||
)
|
||||
).process(
|
||||
success = {
|
||||
dispatcher.send(it).also {
|
||||
commands.emit(Command.OnRelationAdd(relation = relation))
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
relationKey = relation,
|
||||
type = screenType,
|
||||
spaceParams = provideParams(spaceManager.get())
|
||||
)
|
||||
isDismissed.value = true
|
||||
}
|
||||
val params = AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relation
|
||||
)
|
||||
addRelationToObject.async(params).fold(
|
||||
onSuccess = { payload ->
|
||||
if (payload != null) dispatcher.send(payload)
|
||||
commands.emit(Command.OnRelationAdd(relation = relation))
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
relationKey = relation,
|
||||
type = screenType,
|
||||
spaceParams = provideParams(vmParams.space.id)
|
||||
)
|
||||
isDismissed.value = true
|
||||
},
|
||||
failure = {
|
||||
onFailure = {
|
||||
Timber.e(it, ERROR_MESSAGE)
|
||||
_toasts.emit("$ERROR_MESSAGE: ${it.localizedMessage}")
|
||||
}
|
||||
|
@ -79,6 +75,7 @@ class RelationAddToObjectViewModel(
|
|||
}
|
||||
|
||||
class Factory(
|
||||
private val vmParams: VmParams,
|
||||
private val storeOfRelations: StoreOfRelations,
|
||||
private val addRelationToObject: AddRelationToObject,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
|
@ -87,12 +84,12 @@ class RelationAddToObjectViewModel(
|
|||
private val appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
private val getRelations: GetRelations,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return RelationAddToObjectViewModel(
|
||||
vmParams = vmParams,
|
||||
relationsProvider = relationsProvider,
|
||||
addRelationToObject = addRelationToObject,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -101,7 +98,6 @@ class RelationAddToObjectViewModel(
|
|||
appCoroutineDispatchers = appCoroutineDispatchers,
|
||||
getRelations = getRelations,
|
||||
addObjectToWorkspace = addObjectToWorkspace,
|
||||
spaceManager = spaceManager,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
) as T
|
||||
}
|
||||
|
|
|
@ -7,14 +7,11 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Marketplace.MARKETPLACE_SPACE_ID
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.primitives.RelationKey
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.relations.GetRelations
|
||||
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.model.RelationItemView
|
||||
import com.anytypeio.anytype.presentation.relations.model.RelationView
|
||||
|
@ -32,7 +29,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
|||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -43,10 +39,10 @@ import timber.log.Timber
|
|||
*/
|
||||
abstract class RelationAddViewModelBase(
|
||||
relationsProvider: ObjectRelationProvider,
|
||||
private val vmParams: VmParams,
|
||||
private val getRelations: GetRelations,
|
||||
private val appCoroutineDispatchers: AppCoroutineDispatchers,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val spaceManager: SpaceManager
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val userInput = MutableStateFlow(DEFAULT_INPUT)
|
||||
|
@ -59,11 +55,20 @@ abstract class RelationAddViewModelBase(
|
|||
val isDismissed = MutableStateFlow(false)
|
||||
val results = MutableStateFlow(emptyList<RelationItemView>())
|
||||
|
||||
private val objectRelationKeys = relationsProvider.observeAll().map { relations ->
|
||||
relations.map { r -> r.key }
|
||||
}
|
||||
private val objectRelationKeys = MutableStateFlow<List<Key>>(emptyList())
|
||||
|
||||
init {
|
||||
Timber.d("RelationAddViewModelBase init, objectId: ${vmParams.objectId}")
|
||||
viewModelScope.launch {
|
||||
relationsProvider.observeAll(id = vmParams.objectId)
|
||||
.catch {
|
||||
Timber.e(it, "Error while observing relations")
|
||||
}
|
||||
.collect { relations ->
|
||||
Timber.d("Object all relations: ${relations.size}")
|
||||
objectRelationKeys.value = relations.map { it.key }
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
combine(
|
||||
searchQuery,
|
||||
|
@ -161,7 +166,7 @@ abstract class RelationAddViewModelBase(
|
|||
): List<ObjectWrapper.Relation> {
|
||||
val params = GetRelations.Params(
|
||||
// TODO DROID-2916 Provide space id to vm params
|
||||
space = SpaceId(spaceManager.get()),
|
||||
space = vmParams.space,
|
||||
sorts = defaultObjectSearchSorts(),
|
||||
filters = buildList {
|
||||
addAll(filterMyRelations())
|
||||
|
@ -193,7 +198,7 @@ abstract class RelationAddViewModelBase(
|
|||
addObjectToWorkspace(
|
||||
AddObjectToWorkspace.Params(
|
||||
objects = listOf(relation.id),
|
||||
space = spaceManager.get()
|
||||
space = vmParams.space.id
|
||||
)
|
||||
).proceed(
|
||||
success = {
|
||||
|
@ -236,6 +241,11 @@ abstract class RelationAddViewModelBase(
|
|||
) : Command()
|
||||
}
|
||||
|
||||
data class VmParams(
|
||||
val objectId: Id,
|
||||
val space: SpaceId
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val ERROR_MESSAGE = "Error while adding relation to object"
|
||||
const val DEBOUNCE_DURATION = 300L
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.core_models.*
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
|
||||
|
@ -138,14 +137,14 @@ class RelationCreateFromScratchForObjectViewModel(
|
|||
|
||||
private fun proceedWithAddingRelationToObject(ctx: Id, relation: Key) {
|
||||
viewModelScope.launch {
|
||||
addRelationToObject(
|
||||
AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relation
|
||||
)
|
||||
).process(
|
||||
success = { payload ->
|
||||
dispatcher.send(payload).also { isDismissed.value = true }
|
||||
val params = AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relation
|
||||
)
|
||||
addRelationToObject.async(params).fold(
|
||||
onSuccess = { payload ->
|
||||
if (payload != null) dispatcher.send(payload)
|
||||
isDismissed.value = true
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -153,7 +152,7 @@ class RelationCreateFromScratchForObjectViewModel(
|
|||
spaceParams = provideParams(spaceManager.get())
|
||||
)
|
||||
},
|
||||
failure = {
|
||||
onFailure = {
|
||||
Timber.e(it, ACTION_FAILED_ERROR).also { _toasts.emit(ACTION_FAILED_ERROR) }
|
||||
}
|
||||
)
|
||||
|
@ -244,14 +243,14 @@ class RelationCreateFromScratchForObjectBlockViewModel(
|
|||
|
||||
private fun proceedWithAddingRelationToObject(ctx: Id, relationKey: Id) {
|
||||
viewModelScope.launch {
|
||||
addRelationToObject(
|
||||
AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relationKey
|
||||
)
|
||||
).process(
|
||||
success = { payload ->
|
||||
dispatcher.send(payload).also { commands.emit(Command.OnSuccess(relationKey)) }
|
||||
val params = AddRelationToObject.Params(
|
||||
ctx = ctx,
|
||||
relationKey = relationKey
|
||||
)
|
||||
addRelationToObject.async(params).fold(
|
||||
onSuccess = { payload ->
|
||||
if (payload != null) dispatcher.send(payload)
|
||||
commands.emit(Command.OnSuccess(relationKey))
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -259,7 +258,7 @@ class RelationCreateFromScratchForObjectBlockViewModel(
|
|||
spaceParams = provideParams(spaceManager.get())
|
||||
)
|
||||
},
|
||||
failure = {
|
||||
onFailure = {
|
||||
Timber.e(it, ACTION_FAILED_ERROR).also { _toasts.emit(ACTION_FAILED_ERROR) }
|
||||
}
|
||||
)
|
||||
|
|
|
@ -237,39 +237,38 @@ fun ColumnView.getDateRelationFormat(): String {
|
|||
/**
|
||||
* Retrieves a list of distinct [ObjectWrapper.Relation] relations of Object using the given relation links filtered by system relations.
|
||||
*
|
||||
* @param relationLinks The list of relation links (@see [RelationLink] class) used to identify the relations.
|
||||
* @param relationKeys The list of object details keys
|
||||
* @param systemRelations The list of keys of the system relations. Final list will be filtered by this list.
|
||||
* @param storeOfRelations The store of relations to retrieve the relations from.
|
||||
*
|
||||
* @return A list of distinct [ObjectWrapper.Relation] object relations.
|
||||
*/
|
||||
suspend fun getObjectRelations(
|
||||
relationLinks: List<RelationLink>,
|
||||
relationKeys: Set<Key>,
|
||||
systemRelations: List<Key>,
|
||||
storeOfRelations: StoreOfRelations
|
||||
): List<ObjectWrapper.Relation> {
|
||||
val systemRelationKeys = systemRelations.toSet()
|
||||
val objectRelationKeys = relationLinks.map { it.key }.filterNot { it in systemRelationKeys }
|
||||
val objectRelationKeys = relationKeys.filterNot { it in systemRelationKeys }
|
||||
return storeOfRelations.getByKeys(objectRelationKeys).distinctBy { it.key }
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of filtered [ObjectWrapper.Relation] recommended relations of Object.
|
||||
*
|
||||
* @param relationLinks The list of relation links (@see [RelationLink] class) used to identify the relations.
|
||||
* @param relationKeys The list of object details keys
|
||||
* @param recommendedRelations The list of ids of the recommended relations.
|
||||
* @param storeOfRelations The store of relations to retrieve the relations from.
|
||||
*
|
||||
* @return A list of distinct [ObjectWrapper.Relation] object recommended relations.
|
||||
*/
|
||||
suspend fun getNotIncludedRecommendedRelations(
|
||||
relationLinks: List<RelationLink>,
|
||||
relationKeys: Set<Key>,
|
||||
recommendedRelations: List<Id>,
|
||||
storeOfRelations: StoreOfRelations
|
||||
): List<ObjectWrapper.Relation> {
|
||||
val relationLinkKeys = relationLinks.map { it.key }.toSet()
|
||||
return storeOfRelations.getById(recommendedRelations)
|
||||
.filterNot { recommended -> recommended.key in relationLinkKeys }
|
||||
.filterNot { recommended -> recommended.key in relationKeys }
|
||||
}
|
||||
|
||||
fun ObjectRelationView.getRelationFormat(): RelationFormat = when (this) {
|
||||
|
|
|
@ -13,11 +13,11 @@ import com.anytypeio.anytype.core_models.Key
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.TimeInMillis
|
||||
import com.anytypeio.anytype.core_models.ext.mapToObjectWrapperType
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_utils.diff.DefaultObjectDiffIdentifier
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
|
@ -39,7 +39,6 @@ import kotlinx.coroutines.Job
|
|||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
|
@ -64,7 +63,6 @@ class RelationListViewModel(
|
|||
|
||||
private val jobs = mutableListOf<Job>()
|
||||
|
||||
private val isInAddMode = MutableStateFlow(false)
|
||||
val commands = MutableSharedFlow<Command>(replay = 0)
|
||||
val views = MutableStateFlow<List<Model>>(emptyList())
|
||||
|
||||
|
@ -74,7 +72,6 @@ class RelationListViewModel(
|
|||
|
||||
fun onStartListMode(ctx: Id) {
|
||||
Timber.d("onStartListMode, ctx: $ctx")
|
||||
isInAddMode.value = false
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = relationsScreenShow
|
||||
|
@ -82,17 +79,15 @@ class RelationListViewModel(
|
|||
jobs += viewModelScope.launch {
|
||||
combine(
|
||||
storeOfRelations.trackChanges(),
|
||||
relationListProvider.links,
|
||||
relationListProvider.details
|
||||
) { _, relationLinks, details ->
|
||||
constructViews(ctx, relationLinks, details)
|
||||
) { _, details ->
|
||||
constructViews(ctx, details)
|
||||
}.collect { views.value = it }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun constructViews(
|
||||
ctx: Id,
|
||||
relationLinks: List<RelationLink>,
|
||||
details: Block.Details
|
||||
): List<Model> {
|
||||
|
||||
|
@ -108,7 +103,6 @@ class RelationListViewModel(
|
|||
val objectRelationViews = getObjectRelationsView(
|
||||
ctx = ctx,
|
||||
objectDetails = objectDetails,
|
||||
relationLinks = relationLinks,
|
||||
details = details,
|
||||
objectWrapper = objectWrapper
|
||||
)
|
||||
|
@ -116,7 +110,6 @@ class RelationListViewModel(
|
|||
val recommendedRelationViews = getRecommendedRelations(
|
||||
ctx = ctx,
|
||||
objectDetails = objectDetails,
|
||||
relationLinks = relationLinks,
|
||||
objectTypeWrapper = objectTypeWrapper,
|
||||
details = details
|
||||
)
|
||||
|
@ -127,13 +120,12 @@ class RelationListViewModel(
|
|||
private suspend fun getObjectRelationsView(
|
||||
ctx: Id,
|
||||
objectDetails: Map<Key, Any?>,
|
||||
relationLinks: List<RelationLink>,
|
||||
details: Block.Details,
|
||||
objectWrapper: ObjectWrapper.Basic
|
||||
): List<Model.Item> {
|
||||
return getObjectRelations(
|
||||
systemRelations = listOf(),
|
||||
relationLinks = relationLinks,
|
||||
relationKeys = objectDetails.keys,
|
||||
storeOfRelations = storeOfRelations
|
||||
).views(
|
||||
context = ctx,
|
||||
|
@ -153,12 +145,11 @@ class RelationListViewModel(
|
|||
private suspend fun getRecommendedRelations(
|
||||
ctx: Id,
|
||||
objectDetails: Map<Key, Any?>,
|
||||
relationLinks: List<RelationLink>,
|
||||
objectTypeWrapper: ObjectWrapper.Type,
|
||||
details: Block.Details
|
||||
): List<Model.Item> {
|
||||
return getNotIncludedRecommendedRelations(
|
||||
relationLinks = relationLinks,
|
||||
relationKeys = objectDetails.keys,
|
||||
recommendedRelations = objectTypeWrapper.recommendedRelations,
|
||||
storeOfRelations = storeOfRelations
|
||||
).views(
|
||||
|
@ -197,11 +188,6 @@ class RelationListViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onStartAddMode(ctx: Id) {
|
||||
isInAddMode.value = true
|
||||
getRelations(ctx)
|
||||
}
|
||||
|
||||
fun onStop() {
|
||||
jobs.apply {
|
||||
forEach { it.cancel() }
|
||||
|
@ -212,15 +198,11 @@ class RelationListViewModel(
|
|||
fun onRelationClicked(ctx: Id, target: Id?, view: ObjectRelationView) {
|
||||
Timber.d("onRelationClicked, ctx: $ctx, target: $target, view: $view")
|
||||
viewModelScope.launch {
|
||||
if (isInAddMode.value) {
|
||||
onRelationClickedAddMode(target = target, view = view)
|
||||
if (checkRelationIsInObject(view)) {
|
||||
onRelationClickedListMode(ctx, view)
|
||||
} else {
|
||||
if (checkRelationIsInObject(view)) {
|
||||
proceedWithAddingRelationToObject(ctx, view) {
|
||||
onRelationClickedListMode(ctx, view)
|
||||
} else {
|
||||
proceedWithAddingRelationToObject(ctx, view) {
|
||||
onRelationClickedListMode(ctx, view)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,9 +226,9 @@ class RelationListViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun checkRelationIsInObject(view: ObjectRelationView): Boolean {
|
||||
val relationLinks = relationListProvider.links.stateIn(viewModelScope).value
|
||||
return relationLinks.any { it.key == view.key }
|
||||
private fun checkRelationIsInObject(view: ObjectRelationView): Boolean {
|
||||
val objectRelations = relationListProvider.getDetails().details[vmParams.objectId]?.map?.keys
|
||||
return objectRelations?.any { it == view.key } == true
|
||||
}
|
||||
|
||||
private suspend fun proceedWithAddingRelationToObject(
|
||||
|
@ -258,10 +240,10 @@ class RelationListViewModel(
|
|||
ctx = ctx,
|
||||
relationKey = view.key
|
||||
)
|
||||
addRelationToObject.run(params).process(
|
||||
failure = { Timber.e(it, "Error while adding relation to object") },
|
||||
success = {
|
||||
dispatcher.send(it)
|
||||
addRelationToObject.async(params).fold(
|
||||
onFailure = { Timber.e(it, "Error while adding relation to object") },
|
||||
onSuccess = { payload ->
|
||||
if (payload != null) dispatcher.send(payload)
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationAdd,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -523,21 +505,6 @@ class RelationListViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getRelations(ctx: Id) {
|
||||
viewModelScope.launch {
|
||||
val relations =
|
||||
relationListProvider.getLinks().mapNotNull { storeOfRelations.getByKey(it.key) }
|
||||
val details = relationListProvider.getDetails()
|
||||
val values = details.details[ctx]?.map ?: emptyMap()
|
||||
views.value = relations.views(
|
||||
details = details,
|
||||
values = values,
|
||||
urlBuilder = urlBuilder,
|
||||
fieldParser = fieldParser
|
||||
).map { Model.Item(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun onRelationTextValueChanged(
|
||||
ctx: Id,
|
||||
value: Any?,
|
||||
|
@ -653,6 +620,7 @@ class RelationListViewModel(
|
|||
}
|
||||
|
||||
data class VmParams(
|
||||
val objectId: Id,
|
||||
val spaceId: SpaceId
|
||||
)
|
||||
|
||||
|
|
|
@ -5,47 +5,67 @@ import com.anytypeio.anytype.core_models.Key
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectState
|
||||
import kotlin.collections.mapNotNull
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class DataViewObjectRelationProvider(
|
||||
private val objectState: StateFlow<ObjectState>,
|
||||
private val storeOfRelations: StoreOfRelations
|
||||
) : ObjectRelationProvider {
|
||||
|
||||
override suspend fun get(relation: Key): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getByKey(relation)
|
||||
?: throw IllegalStateException("Could not found relation by key: $relation")
|
||||
}
|
||||
|
||||
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
|
||||
return storeOfRelations.getByKey(relation)
|
||||
}
|
||||
|
||||
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getById(relation)
|
||||
?: throw IllegalStateException("Could not find relation by id: $relation")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return storeOfRelations.trackChanges()
|
||||
.flatMapLatest { _ ->
|
||||
val relation = storeOfRelations.getByKey(relation)
|
||||
if (relation != null) {
|
||||
flowOf(relation)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
|
||||
return objectState.filterIsInstance<ObjectState.DataView>().map { set ->
|
||||
set.dataViewContent.relationLinks.mapNotNull {
|
||||
storeOfRelations.getByKey(it.key)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
|
||||
return combine(
|
||||
storeOfRelations.trackChanges(),
|
||||
objectState
|
||||
) { _, state ->
|
||||
state
|
||||
}.flatMapLatest { state ->
|
||||
when (state) {
|
||||
is ObjectState.DataView.Collection -> {
|
||||
val objectKeys = state.dataViewContent.relationLinks.map { it.key }
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
is ObjectState.DataView.Set -> {
|
||||
val objectKeys = state.dataViewContent.relationLinks.map { it.key }
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return objectState
|
||||
.filterIsInstance<ObjectState.DataView>()
|
||||
.map { it.dataViewContent.relationLinks }
|
||||
.distinctUntilChanged()
|
||||
.mapNotNull { storeOfRelations.getByKey(relation) }
|
||||
}
|
||||
}
|
||||
|
||||
class SetOrCollectionRelationProvider(
|
||||
|
@ -53,43 +73,51 @@ class SetOrCollectionRelationProvider(
|
|||
private val storeOfRelations: StoreOfRelations
|
||||
) : ObjectRelationProvider {
|
||||
|
||||
override suspend fun get(relation: Key): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getByKey(relation)
|
||||
?: throw IllegalStateException("Could not found relation by key: $relation")
|
||||
}
|
||||
|
||||
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
|
||||
return storeOfRelations.getByKey(relation)
|
||||
}
|
||||
|
||||
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getById(relation)
|
||||
?: throw IllegalStateException("Could not find relation by id: $relation")
|
||||
}
|
||||
|
||||
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
|
||||
return objectState.map { set ->
|
||||
when (set) {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
|
||||
return combine(
|
||||
storeOfRelations.trackChanges(),
|
||||
objectState
|
||||
) { _, state ->
|
||||
state
|
||||
}.flatMapLatest { state ->
|
||||
when (state) {
|
||||
is ObjectState.DataView.Collection -> {
|
||||
set.objectRelationLinks.mapNotNull {
|
||||
storeOfRelations.getByKey(it.key)
|
||||
val objectKeys = state.details[id]?.map?.keys.orEmpty()
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
is ObjectState.DataView.Set ->
|
||||
set.objectRelationLinks.mapNotNull {
|
||||
storeOfRelations.getByKey(it.key)
|
||||
is ObjectState.DataView.Set -> {
|
||||
val objectKeys = state.details[id]?.map?.keys.orEmpty()
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
ObjectState.ErrorLayout -> emptyList()
|
||||
ObjectState.Init -> emptyList()
|
||||
}
|
||||
else -> emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return objectState
|
||||
.filterIsInstance<ObjectState.DataView>()
|
||||
.map { it.dataViewContent.relationLinks }
|
||||
.distinctUntilChanged()
|
||||
.mapNotNull { storeOfRelations.getByKey(relation) }
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return storeOfRelations.trackChanges()
|
||||
.flatMapLatest { _ ->
|
||||
val relation = storeOfRelations.getByKey(relation)
|
||||
if (relation != null) {
|
||||
flowOf(relation)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,38 +5,49 @@ import com.anytypeio.anytype.core_models.Key
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.presentation.editor.Editor
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class DefaultObjectRelationProvider(
|
||||
private val storeOfRelations: StoreOfRelations,
|
||||
private val storage: Editor.Storage
|
||||
) : ObjectRelationProvider {
|
||||
|
||||
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getById(relation) ?: throw IllegalStateException("Could not find relation by id: $relation")
|
||||
}
|
||||
|
||||
override suspend fun get(relation: Key): ObjectWrapper.Relation {
|
||||
return storeOfRelations.getByKey(relation) ?: throw IllegalStateException("Could not find relation by key: $relation")
|
||||
}
|
||||
|
||||
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
|
||||
return storeOfRelations.getByKey(relation)
|
||||
}
|
||||
|
||||
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
|
||||
return storage.relationLinks.stream().map { links ->
|
||||
links.mapNotNull { relationLink ->
|
||||
storeOfRelations.getByKey(relationLink.key)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> =
|
||||
combine(
|
||||
storeOfRelations.trackChanges(),
|
||||
storage.details.stream()
|
||||
) { _, details ->
|
||||
details
|
||||
}.flatMapLatest { details ->
|
||||
val objectKeys = details.details[id]?.map?.keys ?: emptyList()
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return observeAll().mapNotNull { relations ->
|
||||
relations.find { it.key == relation }
|
||||
}
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return storeOfRelations.trackChanges()
|
||||
.flatMapLatest { _ ->
|
||||
val relation = storeOfRelations.getByKey(relation)
|
||||
if (relation != null) {
|
||||
flowOf(relation)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,9 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ObjectRelationProvider {
|
||||
suspend fun get(relation: Key): ObjectWrapper.Relation
|
||||
suspend fun getOrNull(relation: Key): ObjectWrapper.Relation?
|
||||
suspend fun getById(relation: Id) : ObjectWrapper.Relation
|
||||
fun observe(relation: Key): Flow<ObjectWrapper.Relation>
|
||||
fun observeAll(): Flow<List<ObjectWrapper.Relation>>
|
||||
suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation>
|
||||
suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>>
|
||||
|
||||
companion object {
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.anytypeio.anytype.presentation.relations.providers
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.presentation.editor.Editor
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectState
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -10,21 +9,16 @@ import kotlinx.coroutines.flow.map
|
|||
|
||||
interface RelationListProvider {
|
||||
|
||||
val links: Flow<List<RelationLink>>
|
||||
val details: Flow<Block.Details>
|
||||
|
||||
fun getLinks() : List<RelationLink>
|
||||
fun getDetails(): Block.Details
|
||||
|
||||
class EditorRelationListProvider(
|
||||
private val storage: Editor.Storage
|
||||
) : RelationListProvider {
|
||||
override val links: Flow<List<RelationLink>>
|
||||
get() = storage.relationLinks.stream()
|
||||
override val details: Flow<Block.Details>
|
||||
get() = storage.details.stream()
|
||||
|
||||
override fun getLinks() = storage.relationLinks.current()
|
||||
override fun getDetails() = storage.details.current()
|
||||
}
|
||||
|
||||
|
@ -32,10 +26,8 @@ interface RelationListProvider {
|
|||
private val objectStates: StateFlow<ObjectState>
|
||||
) : RelationListProvider {
|
||||
|
||||
override val links = objectStates.map { state -> mapLinks(state) }
|
||||
override val details = objectStates.map { state -> mapDetails(state) }
|
||||
|
||||
override fun getLinks(): List<RelationLink> = mapLinks(objectStates.value)
|
||||
override fun getDetails(): Block.Details = mapDetails(objectStates.value)
|
||||
|
||||
private fun mapDetails(state: ObjectState) = when (state) {
|
||||
|
@ -50,10 +42,10 @@ interface RelationListProvider {
|
|||
|
||||
private fun mapLinks(state: ObjectState) = when (state) {
|
||||
is ObjectState.DataView.Collection -> {
|
||||
state.objectRelationLinks
|
||||
state.details.keys
|
||||
}
|
||||
is ObjectState.DataView.Set -> {
|
||||
state.objectRelationLinks
|
||||
state.details.keys
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
|
|||
val prefilled = viewer.prefillNewObjectDetails(
|
||||
dateProvider = dateProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
dataViewRelationLinks = state.objectRelationLinks
|
||||
dataViewRelationLinks = state.dataViewContent.relationLinks
|
||||
)
|
||||
createBookmark(
|
||||
input = input,
|
||||
|
@ -70,7 +70,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
|
|||
val viewer = state.viewerByIdOrFirst(session.currentViewerId.value) ?: return
|
||||
val details = viewer.resolveSetByRelationPrefilledObjectData(
|
||||
objSetByRelation = sourceObject,
|
||||
dataViewRelationLinks = state.objectRelationLinks,
|
||||
dataViewRelationLinks = state.dataViewContent.relationLinks,
|
||||
dateProvider = dateProvider,
|
||||
storeOfRelations = storeOfRelations
|
||||
)
|
||||
|
@ -84,7 +84,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
|
|||
val prefilled = viewer.prefillNewObjectDetails(
|
||||
dateProvider = dateProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
dataViewRelationLinks = state.objectRelationLinks
|
||||
dataViewRelationLinks = state.dataViewContent.relationLinks
|
||||
)
|
||||
createBookmark(
|
||||
input = input,
|
||||
|
|
|
@ -636,7 +636,11 @@ suspend fun DVViewer.resolveSetByRelationPrefilledObjectData(
|
|||
val defaultValue = resolveDefaultValueByFormat(relationFormat)
|
||||
put(objSetByRelation.key, defaultValue)
|
||||
}
|
||||
val prefillNewObjectDetails = prefillNewObjectDetails(storeOfRelations, dateProvider, dataViewRelationLinks)
|
||||
val prefillNewObjectDetails = prefillNewObjectDetails(
|
||||
storeOfRelations = storeOfRelations,
|
||||
dateProvider = dateProvider,
|
||||
dataViewRelationLinks = dataViewRelationLinks
|
||||
)
|
||||
return prefillWithSetOf + prefillNewObjectDetails
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class RelationDateValueViewModel(
|
|||
Timber.d("onStart: ctx:[$ctx], relationKey:[$relationKey], objectId:[$objectId]")
|
||||
jobs += viewModelScope.launch {
|
||||
val pipeline = combine(
|
||||
relations.observe(relationKey),
|
||||
relations.observeRelation(relationKey),
|
||||
values.subscribe(ctx = ctx, target = objectId)
|
||||
) { relation, value ->
|
||||
setupIsRelationNotEditable(isLocked, relation)
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.anytypeio.anytype.core_models.Event.Command
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ext.amend
|
||||
import com.anytypeio.anytype.core_models.ext.remove
|
||||
import com.anytypeio.anytype.core_models.ext.unset
|
||||
import com.anytypeio.anytype.core_utils.ext.replace
|
||||
import com.anytypeio.anytype.presentation.sets.updateFields
|
||||
|
@ -61,12 +60,6 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
is Command.ShowObject -> {
|
||||
handleShowObject(event)
|
||||
}
|
||||
is Command.ObjectRelationLinks.Amend -> {
|
||||
amendObjectRelationLinks(state, event)
|
||||
}
|
||||
is Command.ObjectRelationLinks.Remove -> {
|
||||
removeObjectRelationLinks(state, event)
|
||||
}
|
||||
is Command.DataView.SetView -> {
|
||||
handleSetView(state, event)
|
||||
}
|
||||
|
@ -118,49 +111,6 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
)
|
||||
}
|
||||
|
||||
private fun removeObjectRelationLinks(
|
||||
state: ObjectState,
|
||||
event: Command.ObjectRelationLinks.Remove
|
||||
) = when (state) {
|
||||
is ObjectState.DataView.Collection -> {
|
||||
state.copy(
|
||||
objectRelationLinks = state.objectRelationLinks.remove(
|
||||
event.keys
|
||||
)
|
||||
)
|
||||
}
|
||||
is ObjectState.DataView.Set -> {
|
||||
state.copy(
|
||||
objectRelationLinks = state.objectRelationLinks.remove(
|
||||
event.keys
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
}
|
||||
|
||||
private fun amendObjectRelationLinks(
|
||||
state: ObjectState,
|
||||
event: Command.ObjectRelationLinks.Amend
|
||||
) = when (state) {
|
||||
is ObjectState.DataView.Collection -> {
|
||||
state.copy(
|
||||
objectRelationLinks = state.objectRelationLinks.amend(
|
||||
event.relationLinks
|
||||
)
|
||||
)
|
||||
}
|
||||
is ObjectState.DataView.Set -> {
|
||||
state.copy(
|
||||
objectRelationLinks = state.objectRelationLinks.amend(
|
||||
event.relationLinks
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
}
|
||||
|
||||
|
||||
//region EVENTS
|
||||
/**
|
||||
* @see Command.ShowObject
|
||||
|
@ -171,17 +121,13 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
root = event.root,
|
||||
blocks = event.blocks,
|
||||
details = event.details.details,
|
||||
objectRestrictions = event.objectRestrictions,
|
||||
dataViewRestrictions = event.dataViewRestrictions,
|
||||
objectRelationLinks = event.relationLinks
|
||||
dataViewRestrictions = event.dataViewRestrictions
|
||||
)
|
||||
ObjectType.Layout.SET.code -> ObjectState.DataView.Set(
|
||||
root = event.root,
|
||||
blocks = event.blocks,
|
||||
details = event.details.details,
|
||||
objectRestrictions = event.objectRestrictions,
|
||||
dataViewRestrictions = event.dataViewRestrictions,
|
||||
objectRelationLinks = event.relationLinks
|
||||
dataViewRestrictions = event.dataViewRestrictions
|
||||
)
|
||||
else -> {
|
||||
Timber.e("Wrong layout type: $layout")
|
||||
|
@ -368,8 +314,7 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
blocks = blocks,
|
||||
details = state.details,
|
||||
objectRestrictions = state.objectRestrictions,
|
||||
dataViewRestrictions = state.dataViewRestrictions,
|
||||
objectRelationLinks = state.objectRelationLinks
|
||||
dataViewRestrictions = state.dataViewRestrictions
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.anytypeio.anytype.core_models.DVViewer
|
|||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.RelationLink
|
||||
import com.anytypeio.anytype.core_models.restrictions.DataViewRestrictions
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
|
||||
|
@ -22,8 +21,6 @@ sealed class ObjectState {
|
|||
abstract val objectRestrictions: List<ObjectRestriction>
|
||||
abstract val dataViewRestrictions: List<DataViewRestrictions>
|
||||
|
||||
abstract val objectRelationLinks: List<RelationLink>
|
||||
|
||||
abstract val dataViewContent: DV
|
||||
abstract val dataViewBlock: Block
|
||||
abstract val viewers: List<DVViewer>
|
||||
|
@ -34,7 +31,6 @@ sealed class ObjectState {
|
|||
override val details: Map<Id, Block.Fields> = emptyMap(),
|
||||
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
|
||||
override val objectRelationLinks: List<RelationLink> = emptyList(),
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
|
@ -49,7 +45,6 @@ sealed class ObjectState {
|
|||
override val details: Map<Id, Block.Fields> = emptyMap(),
|
||||
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
|
||||
override val objectRelationLinks: List<RelationLink> = emptyList()
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
|
|
|
@ -101,7 +101,6 @@ class TemplateBlankViewModel(
|
|||
anchor = page.first().id,
|
||||
indent = EditorViewModel.INITIAL_INDENT,
|
||||
details = customDetails,
|
||||
relationLinks = emptyList(),
|
||||
restrictions = emptyList(),
|
||||
selection = emptySet()
|
||||
)
|
||||
|
|
|
@ -82,7 +82,6 @@ class DefaultBlockViewRendererTest {
|
|||
anchor = anchor,
|
||||
indent = indent,
|
||||
details = details,
|
||||
relationLinks = emptyList(),
|
||||
restrictions = restrictions,
|
||||
selection = emptySet(),
|
||||
parentScheme = schema
|
||||
|
|
|
@ -3605,7 +3605,6 @@ open class EditorViewModelTest {
|
|||
context = root,
|
||||
root = root,
|
||||
details = details,
|
||||
relations = relations,
|
||||
blocks = document,
|
||||
objectRestrictions = objectRestrictions
|
||||
)
|
||||
|
@ -3818,7 +3817,7 @@ open class EditorViewModelTest {
|
|||
val memory = Editor.Memory(
|
||||
selections = SelectionStateHolder.Default()
|
||||
)
|
||||
addRelationToObject = AddRelationToObject(repo)
|
||||
addRelationToObject = AddRelationToObject(repo, dispatchers)
|
||||
objectToSet = ConvertObjectToSet(repo, dispatchers)
|
||||
updateDetail = UpdateDetail(repo)
|
||||
setDocCoverImage = SetDocCoverImage(repo)
|
||||
|
|
|
@ -845,7 +845,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
|
@ -1004,7 +1003,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
|
@ -1291,7 +1289,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
|
@ -1450,7 +1447,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
|
|
|
@ -561,8 +561,6 @@ open class EditorPresentationTestSetup {
|
|||
context = root,
|
||||
root = root,
|
||||
details = details,
|
||||
relations = relations,
|
||||
relationLinks = relationLinks,
|
||||
blocks = document,
|
||||
objectRestrictions = objectRestrictions
|
||||
)
|
||||
|
|
|
@ -61,7 +61,6 @@ class TableBlockRendererTest {
|
|||
focus = focus,
|
||||
indent = indent,
|
||||
details = details,
|
||||
relationLinks = emptyList(),
|
||||
restrictions = restrictions,
|
||||
selection = selections
|
||||
)
|
||||
|
|
|
@ -300,6 +300,9 @@ class RelationAddViewModelBaseTest {
|
|||
repo = repo,
|
||||
dispatchers = appCoroutineDispatchers
|
||||
),
|
||||
spaceManager = spaceManager
|
||||
vmParams = VmParams(
|
||||
objectId = MockDataFactory.randomUuid(),
|
||||
space = SpaceId(spaceId)
|
||||
)
|
||||
) {}
|
||||
}
|
|
@ -42,9 +42,9 @@ class RelationExtensionsTest {
|
|||
|
||||
// When
|
||||
val result = getNotIncludedRecommendedRelations(
|
||||
relationLinks = relationLinks,
|
||||
recommendedRelations = recommendedRelations,
|
||||
storeOfRelations = storeOfRelations
|
||||
storeOfRelations = storeOfRelations,
|
||||
relationKeys = relationLinks.map { it.key }.toSet()
|
||||
)
|
||||
|
||||
// Then
|
||||
|
|
|
@ -22,27 +22,19 @@ internal class FakeObjectRelationProvider : ObjectRelationProvider {
|
|||
|
||||
constructor(relation: ObjectWrapper.Relation = StubRelationObject()) : this(listOf(relation))
|
||||
|
||||
override suspend fun get(relation: Key): ObjectWrapper.Relation {
|
||||
return relations.first { it.key == relation }
|
||||
}
|
||||
|
||||
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
|
||||
return relations.find { it.key == relation }
|
||||
}
|
||||
|
||||
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
|
||||
return relations.first { it.id == relation }
|
||||
}
|
||||
|
||||
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return flow {
|
||||
emit(get(relation))
|
||||
}
|
||||
}
|
||||
|
||||
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
|
||||
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
|
||||
return flow {
|
||||
emit(relations)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
|
||||
return flow {
|
||||
emit(this@FakeObjectRelationProvider.relation)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -358,7 +358,6 @@ open class ObjectSetViewModelTestSetup {
|
|||
root = root,
|
||||
blocks = doc,
|
||||
details = details,
|
||||
relations = relations,
|
||||
dataViewRestrictions = dataViewRestrictions
|
||||
)
|
||||
) + additionalEvents
|
||||
|
|
|
@ -80,14 +80,12 @@ fun StubObjectView(
|
|||
root: Id,
|
||||
blocks: List<Block> = emptyList(),
|
||||
details: Map<Id, Struct> = emptyMap(),
|
||||
relations: List<RelationLink> = emptyList(),
|
||||
objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
dataViewRestrictions: List<DataViewRestrictions> = emptyList()
|
||||
): ObjectView = ObjectView(
|
||||
root = root,
|
||||
blocks = blocks,
|
||||
details = details,
|
||||
relations = relations,
|
||||
objectRestrictions = objectRestrictions,
|
||||
dataViewRestrictions = dataViewRestrictions
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue