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

DROID-326 Sets | Enhancement | Unblocking relations for Sets or Collections (#3012)

This commit is contained in:
Evgenii Kozlov 2023-03-15 15:23:57 +01:00 committed by GitHub
parent 7d686b98ea
commit 1ca1f32ebe
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 534 additions and 479 deletions

View file

@ -59,9 +59,9 @@ import com.anytypeio.anytype.domain.icon.DocumentEmojiIconProvider
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
@ -93,7 +93,6 @@ import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.editor.editor.Interactor
import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
import com.anytypeio.anytype.presentation.editor.editor.Proxy
import com.anytypeio.anytype.presentation.editor.editor.pattern.DefaultPatternMatcher
@ -435,7 +434,6 @@ open class EditorTestSetup {
interceptThreadStatus = interceptThreadStatus,
analytics = analytics,
dispatcher = Dispatcher.Default(),
detailModificationManager = InternalDetailModificationManager(stores.details),
updateDetail = updateDetail,
searchObjects = getSearchObjects,
getDefaultPageType = getDefaultPageType,

View file

@ -27,11 +27,11 @@ import com.anytypeio.anytype.emojifier.data.Emoji
import com.anytypeio.anytype.emojifier.data.EmojiProvider
import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester
import com.anytypeio.anytype.emojifier.suggest.model.EmojiModel
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModelFactory
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.anytypeio.anytype.test_utils.utils.TestUtils.withRecyclerView
import kotlin.test.assertEquals
import org.hamcrest.CoreMatchers.not
import org.junit.Before
import org.junit.Test
@ -43,15 +43,11 @@ import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verifyBlocking
import kotlin.test.assertEquals
@RunWith(AndroidJUnit4::class)
@LargeTest
class DocumentEmojiPickerFragmentTest {
@Mock
lateinit var detailModificationManager: DetailModificationManager
@Mock
lateinit var suggester: EmojiSuggester

View file

@ -16,10 +16,10 @@ import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.StubRelationOptionObject
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.ObjectStore
@ -111,7 +111,8 @@ class AddRelationStatusValueTest {
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(
db = db
db = db,
objectState = state
),
dispatcher = dispatcher,
optionsProvider = AddOptionsRelationProvider(),

View file

@ -15,10 +15,10 @@ import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.StubRelationOptionObject
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.ObjectStore
@ -108,7 +108,7 @@ class AddRelationTagValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
createRelationOption = createRelationOption,
dispatcher = dispatcher,
optionsProvider = AddOptionsRelationProvider(),

View file

@ -72,7 +72,7 @@ class DisplayObjectRelationTextValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
reloadObject = reloadObject,
analytics = analytics
)

View file

@ -13,9 +13,9 @@ 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.Payload
import com.anytypeio.anytype.domain.`object`.ReloadObject
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.`object`.ReloadObject
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.ObjectStore
@ -79,7 +79,7 @@ class DisplayRelationNumberValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
reloadObject = reloadObject,
analytics = analytics
)

View file

@ -17,10 +17,10 @@ import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
@ -102,7 +102,7 @@ class DisplayRelationObjectValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
details = object : ObjectDetailProvider {
override fun provide(): Map<Id, Block.Fields> =
state.value.dataViewState()?.details.orEmpty()

View file

@ -19,10 +19,10 @@ 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_ui.extensions.dark
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
@ -104,7 +104,8 @@ class DisplayRelationStatusValueTest {
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(
db = db
db = db,
objectState = state
),
details = object : ObjectDetailProvider {
override fun provide(): Map<Id, Block.Fields> =

View file

@ -19,10 +19,10 @@ 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_ui.extensions.dark
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
@ -103,7 +103,7 @@ class DisplayRelationTagValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
details = object : ObjectDetailProvider {
override fun provide(): Map<Id, Block.Fields> =
state.value.dataViewState()?.details.orEmpty()

View file

@ -14,10 +14,10 @@ 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_ui.extensions.dark
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
@ -105,7 +105,7 @@ class EditRelationTagValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db),
values = DataViewObjectValueProvider(db = db, objectState = state),
details = object : ObjectDetailProvider {
override fun provide(): Map<Id, Block.Fields> =
state.value.dataViewState()?.details.orEmpty()
@ -253,7 +253,7 @@ class EditRelationTagValueTest {
launchFragment(
bundleOf(
RelationValueBaseFragment.CTX_KEY to ctx,
RelationValueBaseFragment.DATAVIEW_KEY to dv.id,
RelationValueBaseFragment.DV_KEY to dv.id,
RelationValueBaseFragment.VIEWER_KEY to viewer.id,
RelationValueBaseFragment.RELATION_KEY to relationKey,
RelationValueBaseFragment.TARGET_KEY to target,

View file

@ -30,6 +30,7 @@ import com.anytypeio.anytype.test_utils.MockDataFactory
import com.anytypeio.anytype.ui.relations.RelationDateValueFragment
import com.anytypeio.anytype.utils.CoroutinesTestRule
import com.bartoszlipinski.disableanimationsrule.DisableAnimationsRule
import java.util.*
import kotlinx.coroutines.flow.MutableStateFlow
import org.hamcrest.CoreMatchers.not
import org.junit.Before
@ -37,7 +38,6 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
import java.util.*
@RunWith(AndroidJUnit4::class)
@LargeTest
@ -64,7 +64,7 @@ class ObjectRelationDateValueTest {
objectState = state,
storeOfRelations = storeOfRelations
),
values = DataViewObjectValueProvider(db = db)
values = DataViewObjectValueProvider(db = db, objectState = state)
)
}

View file

@ -28,7 +28,6 @@ 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.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
@ -72,9 +71,6 @@ class ObjectRelationListTest {
@Mock
lateinit var dispatcher: Dispatcher<Payload>
@Mock
lateinit var detailModificationManager: DetailModificationManager
@Mock
lateinit var analytics: Analytics
@ -110,7 +106,6 @@ class ObjectRelationListTest {
relationListProvider = relationListProvider,
urlBuilder = urlBuilder,
dispatcher = dispatcher,
detailModificationManager = detailModificationManager,
updateDetail = updateDetail,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations,

View file

@ -380,6 +380,14 @@ class ComponentManager(
.build()
}
val dataViewRelationListComponent = DependentComponentMap { id ->
objectSetComponent
.get(id)
.objectRelationListComponent()
.module(ObjectRelationListModule)
.build()
}
val relationTextValueDVComponent = DependentComponentMap { ctx ->
objectSetComponent
.get(ctx)

View file

@ -53,8 +53,8 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.DuplicateObject
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
@ -101,9 +101,7 @@ import com.anytypeio.anytype.presentation.editor.DocumentExternalEventReducer
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Interactor
import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
import com.anytypeio.anytype.presentation.editor.editor.pattern.DefaultPatternMatcher
import com.anytypeio.anytype.presentation.editor.editor.table.DefaultEditorTableDelegate
@ -243,7 +241,6 @@ object EditorSessionModule {
analytics: Analytics,
dispatcher: Dispatcher<Payload>,
delegator: Delegator<Action>,
detailModificationManager: DetailModificationManager,
updateDetail: UpdateDetail,
searchObjects: SearchObjects,
getDefaultPageType: GetDefaultPageType,
@ -278,7 +275,6 @@ object EditorSessionModule {
analytics = analytics,
dispatcher = dispatcher,
delegator = delegator,
detailModificationManager = detailModificationManager,
updateDetail = updateDetail,
searchObjects = searchObjects,
getDefaultPageType = getDefaultPageType,
@ -910,15 +906,6 @@ object EditorUseCaseModule {
@PerScreen
fun provideDelegator(): Delegator<Action> = Delegator.Default()
@JvmStatic
@Provides
@PerScreen
fun provideDetailManager(
storage: Editor.Storage
): DetailModificationManager = InternalDetailModificationManager(
store = storage.details
)
@JvmStatic
@Provides
@PerScreen

View file

@ -10,7 +10,6 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
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.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
@ -44,7 +43,6 @@ object ObjectRelationListModule {
urlBuilder: UrlBuilder,
dispatcher: Dispatcher<Payload>,
updateDetail: UpdateDetail,
detailModificationManager: DetailModificationManager,
addToFeaturedRelations: AddToFeaturedRelations,
removeFromFeaturedRelations: RemoveFromFeaturedRelations,
deleteRelationFromObject: DeleteRelationFromObject,
@ -57,7 +55,6 @@ object ObjectRelationListModule {
urlBuilder = urlBuilder,
dispatcher = dispatcher,
updateDetail = updateDetail,
detailModificationManager = detailModificationManager,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations,
deleteRelationFromObject = deleteRelationFromObject,

View file

@ -13,8 +13,6 @@ import com.anytypeio.anytype.di.feature.sets.ModifyFilterSubComponent
import com.anytypeio.anytype.di.feature.sets.SelectFilterRelationSubComponent
import com.anytypeio.anytype.di.feature.sets.viewer.ViewerCardSizeSelectSubcomponent
import com.anytypeio.anytype.di.feature.sets.viewer.ViewerImagePreviewSelectSubcomponent
import com.anytypeio.anytype.domain.`object`.DuplicateObject
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.interactor.UpdateText
@ -30,6 +28,8 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.DuplicateObject
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
@ -54,11 +54,13 @@ import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectValueProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
import com.anytypeio.anytype.presentation.sets.ObjectSetPaginator
import com.anytypeio.anytype.presentation.sets.ObjectSetSession
@ -75,8 +77,8 @@ import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
import kotlinx.coroutines.Dispatchers
import javax.inject.Named
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@Subcomponent(modules = [ObjectSetModule::class])
@ -116,6 +118,8 @@ interface ObjectSetSubComponent {
fun objectSetIconPickerComponent(): ObjectSetIconPickerComponent.Builder
fun objectSetCoverComponent(): SelectCoverObjectSetSubComponent.Builder
fun objectUnsplashComponent(): UnsplashSubComponent.Builder
fun objectRelationListComponent(): ObjectRelationListComponent.Builder
}
@Module(
@ -354,9 +358,11 @@ object ObjectSetModule {
@JvmStatic
@Provides
@PerScreen
fun provideDataViewObjectValueProvider(
db: ObjectSetDatabase
fun dataViewObjectValueProvider(
db: ObjectSetDatabase,
objectState: MutableStateFlow<ObjectState>,
): ObjectValueProvider = DataViewObjectValueProvider(
objectState = objectState,
db = db
)
@ -507,6 +513,20 @@ object ObjectSetModule {
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun lockedStateProvider() : LockedStateProvider = LockedStateProvider.DataViewLockedStateProvider
@JvmStatic
@Provides
@PerScreen
fun dataViewRelationListProvider(
objectStateFlow: MutableStateFlow<ObjectState>
) : RelationListProvider = RelationListProvider.DataViewRelationListProvider(
objectStates = objectStateFlow
)
@Module
interface Bindings {

View file

@ -12,7 +12,6 @@ import com.anytypeio.anytype.domain.cover.SetDocCoverGradient
import com.anytypeio.anytype.domain.cover.SetDocCoverImage
import com.anytypeio.anytype.presentation.editor.cover.SelectCoverObjectSetViewModel
import com.anytypeio.anytype.presentation.editor.cover.SelectCoverObjectViewModel
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectFragment
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
@ -65,7 +64,6 @@ object SelectCoverObjectModule {
setCoverGradient: SetDocCoverGradient,
removeCover: RemoveDocCover,
dispatcher: Dispatcher<Payload>,
details: DetailModificationManager,
getCoverGradientCollection: GetCoverGradientCollection,
analytics: Analytics
): SelectCoverObjectViewModel.Factory = SelectCoverObjectViewModel.Factory(
@ -74,7 +72,6 @@ object SelectCoverObjectModule {
setCoverGradient = setCoverGradient,
removeCover = removeCover,
dispatcher = dispatcher,
details = details,
getCoverGradientCollection = getCoverGradientCollection,
analytics = analytics
)

View file

@ -120,7 +120,7 @@ abstract class ObjectMenuBaseFragment :
ObjectMenuViewModelBase.Command.OpenSetCover -> openSetCover()
ObjectMenuViewModelBase.Command.OpenSetIcons -> openSetIcons()
ObjectMenuViewModelBase.Command.OpenSetLayout -> toast(COMING_SOON_MSG)
ObjectMenuViewModelBase.Command.OpenSetRelations -> toast(COMING_SOON_MSG)
ObjectMenuViewModelBase.Command.OpenSetRelations -> openDataViewRelations()
ObjectMenuViewModelBase.Command.OpenLinkToChooser -> openLinkChooser()
is ObjectMenuViewModelBase.Command.OpenSnackbar -> openSnackbar(command)
is ObjectMenuViewModelBase.Command.ShareDebugTree -> shareFile(command.uri)
@ -155,7 +155,21 @@ abstract class ObjectMenuBaseFragment :
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_TARGET to null,
ObjectRelationListFragment.ARG_LOCKED to isLocked,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
ObjectRelationListFragment.ARG_DATA_VIEW_FLOW to false
)
)
}
private fun openDataViewRelations() {
findNavController().navigate(
R.id.objectRelationListScreen,
bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_TARGET to null,
ObjectRelationListFragment.ARG_LOCKED to isLocked,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
ObjectRelationListFragment.ARG_DATA_VIEW_FLOW to true
)
)
}

View file

@ -53,6 +53,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
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 isDataViewFLow: Boolean get() = arg(ARG_DATA_VIEW_FLOW)
private val docRelationAdapter by lazy {
DocumentRelationAdapter(
@ -116,7 +117,11 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
ctx = ctx,
relationKey = command.relationKey,
objectId = command.target,
isLocked = command.isLocked
isLocked = command.isLocked,
flow = if (isDataViewFLow)
RelationTextValueFragment.FLOW_DATAVIEW
else
RelationTextValueFragment.FLOW_DEFAULT
)
fr.showChildFragment()
}
@ -129,14 +134,27 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
fr.showChildFragment()
}
is Command.EditRelationValue -> {
val fr = RelationValueFragment.new(
ctx = ctx,
target = command.target,
relationKey = command.relationKey,
targetObjectTypes = command.targetObjectTypes,
isLocked = command.isLocked
)
fr.showChildFragment()
if (isDataViewFLow) {
val fr = RelationValueDVFragment().apply {
arguments = bundleOf(
RelationValueBaseFragment.CTX_KEY to command.ctx,
RelationValueBaseFragment.TARGET_KEY to command.target,
RelationValueBaseFragment.RELATION_KEY to command.relationKey,
RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes,
RelationValueBaseFragment.IS_LOCKED_KEY to false
)
}
fr.showChildFragment()
} else {
val fr = RelationValueFragment.new(
ctx = ctx,
target = command.target,
relationKey = command.relationKey,
targetObjectTypes = command.targetObjectTypes,
isLocked = command.isLocked
)
fr.showChildFragment()
}
}
is Command.SetRelationKey -> {
withParent<OnFragmentInteractionListener> {
@ -148,14 +166,27 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
dismiss()
}
is Command.EditStatusRelationValue -> {
val fr = RelationStatusValueFragment.new(
ctx = ctx,
target = command.target,
relationKey = command.relationKey,
targetObjectTypes = command.targetObjectTypes,
isLocked = command.isLocked
)
fr.showChildFragment()
if (isDataViewFLow) {
val fr = RelationValueDVFragment().apply {
arguments = bundleOf(
RelationValueBaseFragment.CTX_KEY to command.ctx,
RelationValueBaseFragment.TARGET_KEY to command.target,
RelationValueBaseFragment.RELATION_KEY to command.relationKey,
RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes,
RelationValueBaseFragment.IS_LOCKED_KEY to false
)
}
fr.showChildFragment()
} else {
val fr = RelationStatusValueFragment.new(
ctx = ctx,
target = command.target,
relationKey = command.relationKey,
targetObjectTypes = command.targetObjectTypes,
isLocked = command.isLocked
)
fr.showChildFragment()
}
}
}
}
@ -240,11 +271,19 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
}
override fun injectDependencies() {
componentManager().objectRelationListComponent.get(ctx).inject(this)
if (isDataViewFLow) {
componentManager().dataViewRelationListComponent.get(ctx).inject(this)
} else {
componentManager().objectRelationListComponent.get(ctx).inject(this)
}
}
override fun releaseDependencies() {
componentManager().objectRelationListComponent.release(ctx)
if (isDataViewFLow) {
componentManager().dataViewRelationListComponent.release(ctx)
} else {
componentManager().objectRelationListComponent.release(ctx)
}
}
override fun inflateBinding(
@ -259,13 +298,15 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
ctx: String,
target: String?,
mode: Int,
locked: Boolean = false
locked: Boolean = false,
isDataViewFlow: Boolean = false,
) = ObjectRelationListFragment().apply {
arguments = bundleOf(
ARG_CTX to ctx,
ARG_TARGET to target,
ARG_MODE to mode,
ARG_LOCKED to locked
ARG_LOCKED to locked,
ARG_DATA_VIEW_FLOW to isDataViewFlow
)
}
@ -275,5 +316,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
const val ARG_LOCKED = "arg.document-relation.locked"
const val MODE_ADD = 1
const val MODE_LIST = 2
const val ARG_DATA_VIEW_FLOW = "arg.document-relation.data-view-flow"
}
}

View file

@ -9,7 +9,12 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_utils.ext.*
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.subscribe
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_utils.ext.withParent
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
import com.anytypeio.anytype.databinding.FragmentRelationDateValueBinding
import com.anytypeio.anytype.di.common.componentManager
@ -53,7 +58,7 @@ open class RelationDateValueFragment : BaseBottomSheetFragment<FragmentRelationD
jobs += lifecycleScope.subscribe(vm.views) { observeState(it) }
jobs += lifecycleScope.subscribe(vm.commands) { observeCommands(it) }
super.onStart()
vm.onStart(objectId = objectId, relationKey = relationKey)
vm.onStart(ctx = ctx, objectId = objectId, relationKey = relationKey)
}
override fun onStop() {

View file

@ -73,6 +73,7 @@ class RelationStatusValueFragment :
proceed(btnAddValue.clicks()) { vm.onAddValueClicked(isLocked) }
proceed(btnClear.clicks()) {
vm.onRemoveStatusFromObjectClicked(
ctx = ctx,
target = target,
relationKey = relationKey,
)

View file

@ -33,6 +33,7 @@ import com.anytypeio.anytype.presentation.sets.RelationTextValueViewModel
import com.anytypeio.anytype.presentation.sets.RelationValueAction
import com.google.android.material.bottomsheet.BottomSheetBehavior
import javax.inject.Inject
import timber.log.Timber
import com.google.android.material.R.id.design_bottom_sheet as BOTTOM_SHEET_ID
open class RelationTextValueFragment :
@ -135,7 +136,9 @@ open class RelationTextValueFragment :
name = name, value = value
)
} else {
Timber.d("object id: $objectId, context: $ctx")
vm.onStart(
ctx = ctx,
relationKey = relationKey,
recordId = objectId,
isLocked = isLocked,
@ -209,7 +212,6 @@ open class RelationTextValueFragment :
)
companion object {
fun new(
ctx: Id,
relationKey: Key,

View file

@ -62,7 +62,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
protected val ctx get() = argString(CTX_KEY)
protected val relationKey get() = argString(RELATION_KEY)
protected val target get() = argString(TARGET_KEY)
protected val dataview get() = argString(DATAVIEW_KEY)
protected val dv get() = argString(DV_KEY)
protected val viewer get() = argString(VIEWER_KEY)
protected val types get() = arg<List<String>>(TARGET_TYPES_KEY)
protected val isLocked get() = arg<Boolean>(IS_LOCKED_KEY)
@ -114,6 +114,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
onStatusClicked = onStatusClickedCallback,
onRemoveStatusClicked = { status ->
vm.onRemoveStatusFromObjectClicked(
ctx = ctx,
target = target,
relationKey = relationKey,
status = status.id
@ -121,6 +122,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
},
onRemoveTagClicked = { tag ->
vm.onRemoveTagFromObjectClicked(
ctx = ctx,
target = target,
relationKey = relationKey,
tag = tag.id
@ -142,6 +144,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
},
onRemoveObjectClicked = { obj ->
vm.onRemoveObjectFromObjectClicked(
ctx = ctx,
target = target,
relationKey = relationKey,
objectId = obj
@ -150,6 +153,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
onFileClicked = { o -> vm.onFileClicked(o.id) },
onRemoveFileClicked = { file ->
vm.onRemoveFileFromObjectClicked(
ctx = ctx,
target = target,
relationKey = relationKey,
fileId = file
@ -170,8 +174,9 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
jobs += lifecycleScope.subscribe(vm.copyFileStatus) { command -> onCopyFileCommand(command) }
super.onStart()
vm.onStart(
ctx = ctx,
relationKey = relationKey,
objectId = target
objectId = target,
)
}
@ -442,7 +447,7 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragme
const val IS_LOCKED_KEY = "arg.edit-cell-tag.locked"
const val RELATION_KEY = "arg.edit-cell-tag.relation.key"
const val TARGET_KEY = "arg.edit-cell-tag.target"
const val DATAVIEW_KEY = "arg.edit-cell-tag.dataview"
const val DV_KEY = "arg.edit-cell-tag.dataview"
const val VIEWER_KEY = "arg.edit-cell-tag.viewer"
const val TARGET_TYPES_KEY = "arg.relation-value.target-types"
}

View file

@ -28,7 +28,6 @@ import com.anytypeio.anytype.ui.relations.add.AddFileRelationFragment
import com.anytypeio.anytype.ui.relations.add.AddObjectRelationFragment
import com.anytypeio.anytype.ui.relations.add.AddOptionsRelationDVFragment
import javax.inject.Inject
import timber.log.Timber
open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationValueBinding>(),
FileActionsFragment.FileActionReceiver,
@ -82,6 +81,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationV
ids: List<Id>
) {
vm.onAddObjectsOrFilesValueToRecord(
ctx = ctx,
record = objectId,
relationKey = relationKey,
ids = ids
@ -90,6 +90,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationV
override fun onFileValueChanged(ctx: Id, objectId: Id, relationKey: Key, ids: List<Id>) {
vm.onAddObjectsOrFilesValueToRecord(
ctx = ctx,
record = objectId,
relationKey = relationKey,
ids = ids
@ -130,9 +131,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationV
val fr = AddOptionsRelationDVFragment.new(
ctx = ctx,
target = target,
relationKey = relationKey,
dataview = dataview,
viewer = viewer
relationKey = relationKey
)
fr.showChildFragment()
}

View file

@ -79,7 +79,11 @@ class AddFileRelationFragment :
vm.onFilterTextChanged(it.toString())
}
super.onStart()
vm.onStart(objectId = objectId, relationKey = relationKey)
vm.onStart(
ctx = ctx,
objectId = objectId,
relationKey = relationKey
)
}
override fun onStop() {

View file

@ -117,7 +117,12 @@ class AddObjectRelationFragment : BaseDialogFragment<FragmentRelationObjectValue
}
super.onStart()
setupAppearance()
vm.onStart(objectId = objectId, relationKey = relationKey, targetTypes = types)
vm.onStart(
ctx = ctx,
objectId = objectId,
relationKey = relationKey,
targetTypes = types
)
}
override fun onStop() {

View file

@ -25,6 +25,7 @@ open class AddOptionsRelationDVFragment : BaseAddOptionsRelationFragment() {
override fun onCreateOptionClicked(name: String) {
vm.onCreateDataViewRelationOptionClicked(
ctx = ctx,
relationKey = relationKey,
name = name,
target = target
@ -33,6 +34,7 @@ open class AddOptionsRelationDVFragment : BaseAddOptionsRelationFragment() {
override fun onAddButtonClicked() {
vm.onAddSelectedValuesToDataViewClicked(
ctx = ctx,
target = target,
relationKey = relationKey
)
@ -50,16 +52,12 @@ open class AddOptionsRelationDVFragment : BaseAddOptionsRelationFragment() {
fun new(
ctx: Id,
target: Id,
relationKey: Key,
dataview: Id,
viewer: Id
relationKey: Key
) = AddOptionsRelationDVFragment().apply {
arguments = bundleOf(
CTX_KEY to ctx,
TARGET_KEY to target,
RELATION_KEY to relationKey,
DATAVIEW_KEY to dataview,
VIEWER_KEY to viewer
RELATION_KEY to relationKey
)
}
}

View file

@ -25,6 +25,7 @@ class AddOptionsRelationFragment : BaseAddOptionsRelationFragment() {
override fun onCreateOptionClicked(name: String) {
vm.onCreateObjectRelationOptionClicked(
ctx = ctx,
relationKey = relationKey,
obj = target,
name = name
@ -33,6 +34,7 @@ class AddOptionsRelationFragment : BaseAddOptionsRelationFragment() {
override fun onAddButtonClicked() {
vm.onAddSelectedValuesToObjectClicked(
ctx = ctx,
obj = target,
relationKey = relationKey
)

View file

@ -177,6 +177,7 @@ abstract class BaseAddOptionsRelationFragment : BaseDialogFragment<AddOptionRela
super.onStart()
setupAppearance()
vm.onStart(
ctx = ctx,
target = target,
relationKey = relationKey
)

View file

@ -13,7 +13,6 @@ import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
import android.view.inputmethod.EditorInfo.IME_ACTION_GO
import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
@ -93,10 +92,10 @@ import com.anytypeio.anytype.ui.sets.modals.ObjectSetSettingsFragment
import com.anytypeio.anytype.ui.sets.modals.SetObjectCreateRecordFragmentBase
import com.anytypeio.anytype.ui.sets.modals.sort.ViewerSortFragment
import com.bumptech.glide.Glide
import javax.inject.Inject
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
open class ObjectSetFragment :
NavigationFragment<FragmentObjectSetBinding>(R.layout.fragment_object_set),
@ -720,7 +719,7 @@ open class ObjectSetFragment :
bundleOf(
RelationValueBaseFragment.CTX_KEY to command.ctx,
RelationValueBaseFragment.TARGET_KEY to command.target,
RelationValueBaseFragment.DATAVIEW_KEY to command.dataview,
RelationValueBaseFragment.DV_KEY to command.dataview,
RelationValueBaseFragment.RELATION_KEY to command.relationKey,
RelationValueBaseFragment.VIEWER_KEY to command.viewer,
RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes,

View file

@ -9,10 +9,12 @@ import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
*/
sealed class ObjectWrapper {
abstract val map: Struct
/**
* @property map [map] map with raw data containing relations.
*/
data class Basic(val map: Map<String, Any?>) : ObjectWrapper() {
data class Basic(override val map: Struct) : ObjectWrapper() {
private val default = map.withDefault { null }
@ -36,19 +38,9 @@ sealed class ObjectWrapper {
val isArchived: Boolean? by default
val isDeleted: Boolean? by default
val type: List<Id>
get() = when (val value = map[Relations.TYPE]) {
is Id -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
val setOf: List<Id>
get() = when (val value = map[Relations.SET_OF]) {
is Id -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
val type: List<Id> get() = getValues(Relations.TYPE)
val setOf: List<Id> get() = getValues(Relations.SET_OF)
val links: List<Id> get() = getValues(Relations.LINKS)
val layout: ObjectType.Layout?
get() = when (val value = map[Relations.LAYOUT]) {
@ -58,13 +50,6 @@ sealed class ObjectWrapper {
else -> null
}
val links: List<Id>
get() = when (val value = map[Relations.LINKS]) {
is Id -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
val id: Id by default
val done: Boolean? by default
@ -75,14 +60,6 @@ sealed class ObjectWrapper {
val fileMimeType: String? by default
inline fun <reified T> getValue(relation: Id): T? {
val value = map.getOrDefault(relation, null)
return if (value is T)
value
else
null
}
val description: String? by default
val url: String? by default
@ -129,7 +106,7 @@ sealed class ObjectWrapper {
/**
* Wrapper for bookmark objects
*/
data class Bookmark(val map: Map<String, Any?>) : ObjectWrapper() {
data class Bookmark(override val map: Struct) : ObjectWrapper() {
private val default = map.withDefault { null }
val name: String? by default
val description: String? by default
@ -144,7 +121,7 @@ sealed class ObjectWrapper {
/**
* Wrapper for object types
*/
data class Type(val map: Map<String, Any?>) : ObjectWrapper() {
data class Type(override val map: Struct) : ObjectWrapper() {
private val default = map.withDefault { null }
val id: Id by default
val name: String? by default
@ -165,7 +142,7 @@ sealed class ObjectWrapper {
}
}
data class Relation(val map: Struct) : ObjectWrapper() {
data class Relation(override val map: Struct) : ObjectWrapper() {
private val default = map.withDefault { null }
@ -208,24 +185,14 @@ sealed class ObjectWrapper {
else -> emptyList()
}
val relationFormatObjectTypes
get() = when (val value = map[RELATION_FORMAT_OBJECT_TYPES]) {
is Id -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
val relationFormatObjectTypes get() = getValues<Id>(RELATION_FORMAT_OBJECT_TYPES)
val type: List<Id>
get() = when (val value = map[Relations.TYPE]) {
is Id -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
val type: List<Id> get() = getValues(Relations.TYPE)
val isValid get() = map.containsKey(Relations.RELATION_KEY) && map.containsKey(Relations.ID)
}
data class Option(val map: Struct) {
data class Option(override val map: Struct) : ObjectWrapper() {
private val default = map.withDefault { null }
private val relationOptionColor : String? by default
@ -233,4 +200,20 @@ sealed class ObjectWrapper {
val name: String? by default
val color: String = relationOptionColor.orEmpty()
}
inline fun <reified T> getValue(relation: Key): T? {
val value = map.getOrDefault(relation, null)
return if (value is T)
value
else
null
}
inline fun <reified T> getValues(relation: Key): List<T> {
return when (val value = map.getOrDefault(relation, emptyList<T>())) {
is T -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
}
}

View file

@ -49,6 +49,9 @@ object Relations {
const val NUMBER_DEFAULT_VALUE = "0"
const val RELATION_NAME_EMPTY = "Untitled"
const val FILE_EXT = "fileExt"
const val FILE_MIME_TYPE = "fileMimeType"
val systemRelationKeys = listOf(
"id",
"name",

View file

@ -0,0 +1,4 @@
package com.anytypeio.anytype.core_models.inline
@JvmInline
value class Ctx(private val ctx: String)

12
docs/screens.md Normal file
View file

@ -0,0 +1,12 @@
### Object (aka Editor)
[Main]
### Set or Collection
[Main]
- [ObjectSetMenuFragment] showing menu for a Set or Collection
- [ObjectRelationListFragment] displaying list of given object's relations
- [RelationTextValueFragment]
// TODO

View file

@ -10,14 +10,14 @@ class UpdateDetail(private val repo: BlockRepository): BaseUseCase<Payload, Upda
override suspend fun run(params: Params) = safe {
repo.setObjectDetail(
ctx = params.ctx,
ctx = params.target,
key = params.key,
value = params.value
)
}
data class Params(
val ctx: Id,
val target: Id,
val key: String,
val value: Any?
)

View file

@ -67,8 +67,8 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.icon.SetImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
@ -90,7 +90,6 @@ import com.anytypeio.anytype.presentation.common.SupportCommand
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Interactor
import com.anytypeio.anytype.presentation.editor.Editor.Restore
import com.anytypeio.anytype.presentation.editor.editor.Command
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Intent
import com.anytypeio.anytype.presentation.editor.editor.Intent.Media
import com.anytypeio.anytype.presentation.editor.editor.KeyPressedEvent
@ -255,7 +254,6 @@ class EditorViewModel(
private val analytics: Analytics,
private val dispatcher: Dispatcher<Payload>,
private val delegator: Delegator<Action>,
private val detailModificationManager: DetailModificationManager,
private val updateDetail: UpdateDetail,
private val searchObjects: SearchObjects,
private val getDefaultPageType: GetDefaultPageType,
@ -372,7 +370,6 @@ class EditorViewModel(
startHandlingTextChanges()
startProcessingFocusChanges()
startProcessingControlPanelViewState()
startProcessingInternalDetailModifications()
startObservingPayload()
startObservingErrors()
processRendering()
@ -462,10 +459,6 @@ class EditorViewModel(
)
}
private fun startProcessingInternalDetailModifications() {
detailModificationManager.modifications.onEach { refresh() }.launchIn(viewModelScope)
}
private fun startProcessingFocusChanges() {
viewModelScope.launch {
orchestrator.stores.focus.stream().collect { focus ->
@ -4171,7 +4164,7 @@ class EditorViewModel(
viewModelScope.launch {
updateDetail(
UpdateDetail.Params(
ctx = ctx,
target = ctx,
key = key,
value = value
)

View file

@ -7,8 +7,6 @@ import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.block.interactor.RemoveLinkMark
import com.anytypeio.anytype.domain.block.interactor.UpdateLinkMarks
import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet
@ -19,12 +17,14 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObjectAsMentionOrLink
import com.anytypeio.anytype.domain.page.CreateBlockLinkWithObject
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.page.CreateObjectAsMentionOrLink
import com.anytypeio.anytype.domain.page.OpenPage
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
@ -34,7 +34,6 @@ import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.presentation.common.Action
import com.anytypeio.anytype.presentation.common.Delegator
import com.anytypeio.anytype.presentation.common.StateReducer
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
import com.anytypeio.anytype.presentation.editor.editor.table.EditorTableDelegate
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
@ -59,7 +58,6 @@ open class EditorViewModelFactory(
private val analytics: Analytics,
private val dispatcher: Dispatcher<Payload>,
private val delegator: Delegator<Action>,
private val detailModificationManager: DetailModificationManager,
private val updateDetail: UpdateDetail,
private val searchObjects: SearchObjects,
private val getDefaultPageType: GetDefaultPageType,
@ -98,7 +96,6 @@ open class EditorViewModelFactory(
analytics = analytics,
dispatcher = dispatcher,
delegator = delegator,
detailModificationManager = detailModificationManager,
updateDetail = updateDetail,
searchObjects = searchObjects,
getDefaultPageType = getDefaultPageType,

View file

@ -12,8 +12,6 @@ import com.anytypeio.anytype.domain.cover.SetDocCoverColor
import com.anytypeio.anytype.domain.cover.SetDocCoverGradient
import com.anytypeio.anytype.domain.cover.SetDocCoverImage
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRemoveCoverEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSetCoverEvent
import com.anytypeio.anytype.presentation.util.Dispatcher
@ -137,7 +135,6 @@ abstract class SelectCoverViewModel(
success = {
sendAnalyticsSetCoverEvent(analytics)
dispatcher.send(it)
onDetailsColor(ctx, color)
isDismissed.emit(true)
}
)
@ -159,15 +156,11 @@ abstract class SelectCoverViewModel(
success = {
sendAnalyticsSetCoverEvent(analytics)
dispatcher.send(it)
onDetailsGradient(ctx, gradient)
isDismissed.emit(true)
}
)
}
}
abstract fun onDetailsColor(ctx: Id, color: CoverColor)
abstract fun onDetailsGradient(ctx: Id, gradient: String)
}
class SelectCoverObjectViewModel(
@ -176,7 +169,6 @@ class SelectCoverObjectViewModel(
private val setCoverGradient: SetDocCoverGradient,
private val removeCover: RemoveDocCover,
private val dispatcher: Dispatcher<Payload>,
private val details: DetailModificationManager,
private val getCoverGradientCollection: GetCoverGradientCollection,
private val analytics: Analytics
) : SelectCoverViewModel(
@ -189,31 +181,12 @@ class SelectCoverObjectViewModel(
analytics = analytics
) {
override fun onDetailsColor(ctx: Id, color: CoverColor) {
viewModelScope.launch {
details.setDocCoverColor(
target = ctx,
color = color.code
)
}
}
override fun onDetailsGradient(ctx: Id, gradient: String) {
viewModelScope.launch {
details.setDocCoverGradient(
target = ctx,
gradient = gradient
)
}
}
class Factory(
private val setCoverImage: SetDocCoverImage,
private val setCoverColor: SetDocCoverColor,
private val setCoverGradient: SetDocCoverGradient,
private val removeCover: RemoveDocCover,
private val dispatcher: Dispatcher<Payload>,
private val details: DetailModificationManager,
private val getCoverGradientCollection: GetCoverGradientCollection,
private val analytics: Analytics
) : ViewModelProvider.Factory {
@ -226,7 +199,6 @@ class SelectCoverObjectViewModel(
setCoverGradient = setCoverGradient,
removeCover = removeCover,
dispatcher = dispatcher,
details = details,
getCoverGradientCollection = getCoverGradientCollection,
analytics = analytics
) as T
@ -252,9 +224,6 @@ class SelectCoverObjectSetViewModel(
analytics = analytics
) {
override fun onDetailsColor(ctx: Id, color: CoverColor) {}
override fun onDetailsGradient(ctx: Id, gradient: String) {}
class Factory(
private val setCoverImage: SetDocCoverImage,
private val setCoverColor: SetDocCoverColor,

View file

@ -1,185 +0,0 @@
package com.anytypeio.anytype.presentation.editor.editor
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.CoverType
import com.anytypeio.anytype.core_models.Hash
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_utils.const.DetailsKeys
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
interface DetailModificationManager {
val modifications: SharedFlow<List<Modification>>
suspend fun setEmojiIcon(target: Id, unicode: String)
suspend fun setImageIcon(target: Id, hash: Hash)
suspend fun removeIcon(target: Id)
suspend fun setDocCoverColor(target: Id, color: String)
suspend fun setDocCoverGradient(target: Id, gradient: String)
suspend fun setDocCoverImage(target: Id, hash: Hash)
suspend fun removeDocCover(target: Id)
suspend fun updateRelationValue(target: Id, key: String, value: Any?)
}
class InternalDetailModificationManager(private val store: Store.Details) : DetailModificationManager {
private val details: Block.Details get() = store.current()
private val _modifications = MutableSharedFlow<List<Modification>>()
override val modifications: SharedFlow<List<Modification>> = _modifications
override suspend fun setEmojiIcon(target: Id, unicode: String) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.ICON_EMOJI, unicode)
set(DetailsKeys.ICON_IMAGE, null)
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(ICON_UPDATED))
}
override suspend fun setImageIcon(target: Id, hash: Hash) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.ICON_EMOJI, null)
set(DetailsKeys.ICON_IMAGE, hash)
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(ICON_UPDATED))
}
override suspend fun removeIcon(target: Id) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.ICON_EMOJI, null)
set(DetailsKeys.ICON_IMAGE, null)
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(ICON_CLEARED))
}
override suspend fun setDocCoverColor(target: Id, color: String) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.COVER_ID, color)
set(DetailsKeys.COVER_TYPE, CoverType.COLOR.code.toDouble())
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(COVER_CHANGED))
}
override suspend fun setDocCoverGradient(target: Id, gradient: String) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.COVER_ID, gradient)
set(DetailsKeys.COVER_TYPE, CoverType.GRADIENT.code.toDouble())
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(COVER_CHANGED))
}
override suspend fun setDocCoverImage(target: Id, hash: Hash) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.COVER_ID, hash)
set(DetailsKeys.COVER_TYPE, CoverType.UPLOADED_IMAGE.code.toDouble())
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(COVER_CHANGED))
}
override suspend fun removeDocCover(target: Id) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(DetailsKeys.COVER_ID, null)
set(DetailsKeys.COVER_TYPE, CoverType.NONE.code.toDouble())
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(COVER_CLEARED))
}
override suspend fun updateRelationValue(target: Id, key: String, value: Any?) {
val detail = details.details[target] ?: return
val updated = detail.copy(
map = detail.map.toMutableMap().apply {
set(key, value)
}
)
store.update(
Block.Details(
details.details.toMutableMap().apply {
set(target, updated)
}
)
)
_modifications.emit(listOf(RELATION_VALUE_CHANGED))
}
companion object {
const val ICON_UPDATED = 1
const val ICON_CLEARED = 2
const val COVER_CHANGED = 3
const val COVER_CLEARED = 4
const val RELATION_VALUE_CHANGED = 5
}
}
typealias Modification = Int

View file

@ -13,4 +13,8 @@ interface LockedStateProvider {
return doc?.fields?.isLocked ?: false
}
}
object DataViewLockedStateProvider : LockedStateProvider {
// Sets or Collections can't be locked currently.
override fun isLocked(ctx: Id): Boolean = false
}
}

View file

@ -10,7 +10,6 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
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.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
import com.anytypeio.anytype.presentation.util.Dispatcher
@ -21,7 +20,6 @@ class ObjectRelationListViewModelFactory(
private val urlBuilder: UrlBuilder,
private val dispatcher: Dispatcher<Payload>,
private val updateDetail: UpdateDetail,
private val detailModificationManager: DetailModificationManager,
private val addToFeaturedRelations: AddToFeaturedRelations,
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
private val deleteRelationFromObject: DeleteRelationFromObject,
@ -37,7 +35,6 @@ class ObjectRelationListViewModelFactory(
urlBuilder = urlBuilder,
dispatcher = dispatcher,
updateDetail = updateDetail,
detailModificationManager = detailModificationManager,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations,
deleteRelationFromObject = deleteRelationFromObject,

View file

@ -20,7 +20,6 @@ import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationDeleteEvent
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationValueEvent
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
@ -41,7 +40,6 @@ class RelationListViewModel(
private val urlBuilder: UrlBuilder,
private val dispatcher: Dispatcher<Payload>,
private val updateDetail: UpdateDetail,
private val detailModificationManager: DetailModificationManager,
private val addToFeaturedRelations: AddToFeaturedRelations,
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
private val deleteRelationFromObject: DeleteRelationFromObject,
@ -135,7 +133,7 @@ class RelationListViewModel(
view: ObjectRelationView,
ctx: Id
) {
val relationKey = view.key ?: return
val relationKey = view.key
viewModelScope.launch {
if (view.featured) {
viewModelScope.launch {
@ -317,7 +315,7 @@ class RelationListViewModel(
check(view is ObjectRelationView.Checkbox)
updateDetail(
UpdateDetail.Params(
ctx = ctx,
target = ctx,
key = view.key,
value = !view.isChecked
)
@ -352,18 +350,13 @@ class RelationListViewModel(
viewModelScope.launch {
updateDetail(
UpdateDetail.Params(
ctx = ctx,
target = ctx,
key = relationKey,
value = value
)
).process(
success = { payload ->
if (payload.events.isNotEmpty()) dispatcher.send(payload)
detailModificationManager.updateRelationValue(
target = ctx,
key = relationKey,
value = value
)
sendAnalyticsRelationValueEvent(analytics)
},
failure = { Timber.e(it, "Error while updating relation values") }

View file

@ -45,12 +45,16 @@ class AddFileRelationViewModel(
val commands = MutableSharedFlow<FileValueAddCommand>(0)
val viewsFiltered: StateFlow<FileValueAddView> = _viewsFiltered
fun onStart(relationKey: Key, objectId: String) {
fun onStart(
ctx: Id,
relationKey: Key,
objectId: String
) {
processingViewsSelectionsAndFilter()
jobs += viewModelScope.launch {
val pipeline = combine(
relations.observe(relationKey),
values.subscribe(objectId)
values.subscribe(ctx = ctx, target = objectId)
) { relation, value ->
when (val ids = value[relation.key]) {
is List<*> -> {

View file

@ -47,13 +47,18 @@ class AddObjectRelationViewModel(
val commands = MutableSharedFlow<ObjectValueAddCommand>(0)
val viewsFiltered: StateFlow<ObjectValueAddView> = _viewsFiltered
fun onStart(relationKey: Key, objectId: String, targetTypes: List<Id>) {
fun onStart(
ctx: Id,
relationKey: Key,
objectId: String,
targetTypes: List<Id>
) {
Timber.d("key: $relationKey, object: ${objectId}, types: $targetTypes")
processingViewsSelectionsAndFilter()
jobs += viewModelScope.launch {
val pipeline = combine(
relations.observe(relationKey),
values.subscribe(objectId)
values.subscribe(ctx = ctx, target = objectId)
) { relation, value ->
when (val ids = value[relation.key]) {
is List<*> -> {

View file

@ -42,6 +42,7 @@ class AddOptionsRelationDVViewModel(
) {
fun onCreateDataViewRelationOptionClicked(
ctx: Id,
relationKey: Key,
target: Id,
name: String
@ -59,6 +60,7 @@ class AddOptionsRelationDVViewModel(
when (relations.get(relation = relationKey).format) {
RelationFormat.TAG -> {
proceedWithAddingTagToObject(
ctx = ctx,
target = target,
relationKey = relationKey,
tags = listOf(option.id)
@ -92,6 +94,7 @@ class AddOptionsRelationDVViewModel(
}
fun onAddSelectedValuesToDataViewClicked(
ctx: Id,
target: Id,
relationKey: Key
) {
@ -102,6 +105,7 @@ class AddOptionsRelationDVViewModel(
null
}
proceedWithAddingTagToObject(
ctx = ctx,
relationKey = relationKey,
tags = tags,
target = target

View file

@ -52,6 +52,7 @@ class AddOptionsRelationViewModel(
)
fun onAddSelectedValuesToObjectClicked(
ctx: Id,
obj: Id,
relationKey: Key,
) {
@ -62,6 +63,7 @@ class AddOptionsRelationViewModel(
null
}
proceedWithAddingTagToObject(
ctx = ctx,
target = obj,
relationKey = relationKey,
tags = tags
@ -69,6 +71,7 @@ class AddOptionsRelationViewModel(
}
fun onCreateObjectRelationOptionClicked(
ctx: Id,
relationKey: Key,
name: String,
obj: Id
@ -85,6 +88,7 @@ class AddOptionsRelationViewModel(
when (val format = relations.get(relationKey).format) {
RelationFormat.TAG -> {
proceedWithAddingTagToObject(
ctx = ctx,
relationKey = relationKey,
target = obj,
tags = listOf(option.id)

View file

@ -93,11 +93,15 @@ abstract class BaseAddOptionsRelationViewModel(
}
}
fun onStart(target: Id, relationKey: Key) {
fun onStart(
ctx: Id,
target: Id,
relationKey: Key
) {
jobs += viewModelScope.launch {
combine(
relations.observe(relationKey),
values.subscribe(target)
values.subscribe(ctx = ctx, target = target)
) { relation, record ->
if (relation.format == Relation.Format.STATUS) {
isAddButtonVisible.value = false
@ -134,10 +138,10 @@ abstract class BaseAddOptionsRelationViewModel(
options: List<ObjectWrapper.Option>
) {
allRelationOptions.value = optionsProvider.provideOptions(
options = options,
relation = relation,
record = record,
relationKey = relationKey
options = options,
relation = relation,
record = record,
relationKey = relationKey
)
}
@ -161,13 +165,14 @@ abstract class BaseAddOptionsRelationViewModel(
}
fun proceedWithAddingTagToObject(
ctx: Id,
target: Id,
relationKey: Key,
tags: List<Id>
) {
Timber.d("Relations | Adding tag to object with id: $target")
viewModelScope.launch {
val obj = values.get(target = target)
val obj = values.get(target = target, ctx = ctx)
val result = mutableListOf<Id>()
val value = obj[relationKey]
if (value is List<*>) {
@ -178,7 +183,7 @@ abstract class BaseAddOptionsRelationViewModel(
result.addAll(tags)
setObjectDetail(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = result
)
@ -202,7 +207,7 @@ abstract class BaseAddOptionsRelationViewModel(
viewModelScope.launch {
setObjectDetail(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = listOf(status)
)

View file

@ -1,15 +1,51 @@
package com.anytypeio.anytype.presentation.relations.providers
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
import com.anytypeio.anytype.presentation.sets.state.ObjectState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
class DataViewObjectValueProvider(
private val db: ObjectSetDatabase,
private val objectState: StateFlow<ObjectState>
) : ObjectValueProvider {
override suspend fun get(target: Id): Map<String, Any?> {
return db.store.get(target)?.map ?: emptyMap()
override suspend fun get(ctx: Id, target: Id): Struct {
return if (ctx == target)
parseIntrinsicObjectValues(
state = objectState.value,
target = target
)
else
db.store.get(target)?.map ?: emptyMap()
}
override suspend fun subscribe(target: Id) = db.observe(target).map { it.map }
override suspend fun subscribe(ctx: Id, target: Id): Flow<Struct> {
return if (ctx == target)
objectState.map { state ->
parseIntrinsicObjectValues(
state = state,
target = target
)
}
else
db.observe(target).map { it.map }
}
/**
* Providing values for relations of a Set of objects or a Collection of objects.
* Set or Collection are both considered here as Objects, contrary to objects from database query.
* Objects corresponding to data view query should be taken from [db].
*/
private fun parseIntrinsicObjectValues(
state: ObjectState,
target: Id
) : Struct = when (state) {
is ObjectState.DataView.Collection -> state.details[target]?.map ?: emptyMap()
is ObjectState.DataView.Set -> state.details[target]?.map ?: emptyMap()
is ObjectState.ErrorLayout -> emptyMap()
is ObjectState.Init -> emptyMap()
}
}

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.relations.providers
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.presentation.editor.editor.Store
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@ -9,11 +10,11 @@ import kotlinx.coroutines.flow.map
class DefaultObjectValueProvider(
private val details: Store.Details
) : ObjectValueProvider {
override suspend fun get(target: Id): Map<String, Any?> {
override suspend fun get(ctx: Id, target: Id): Struct {
return details.current().details.getOrDefault(target, Block.Fields.empty()).map
}
override suspend fun subscribe(target: Id): Flow<Map<String, Any?>> {
override suspend fun subscribe(ctx: Id, target: Id): Flow<Struct> {
return details.stream().map { details ->
details.details.getOrDefault(target, Block.Fields.empty()).map
}

View file

@ -1,9 +1,10 @@
package com.anytypeio.anytype.presentation.relations.providers
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Struct
import kotlinx.coroutines.flow.Flow
interface ObjectValueProvider {
suspend fun get(target: Id): Map<String, Any?>
suspend fun subscribe(target: Id) : Flow<Map<String, Any?>>
suspend fun get(ctx: Id, target: Id): Struct
suspend fun subscribe(ctx: Id, target: Id) : Flow<Struct>
}

View file

@ -2,8 +2,12 @@ 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.core_models.ext.content
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.sets.state.ObjectState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
interface RelationListProvider {
@ -24,4 +28,35 @@ interface RelationListProvider {
override fun getLinks() = storage.relationLinks.current()
override fun getDetails() = storage.details.current()
}
class DataViewRelationListProvider(
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) {
is ObjectState.DataView.Collection -> {
Block.Details(state.details)
}
is ObjectState.DataView.Set -> {
Block.Details(state.details)
}
else -> Block.Details(emptyMap())
}
private fun mapLinks(state: ObjectState) = when (state) {
is ObjectState.DataView.Collection -> {
state.dataViewBlock.content<Block.Content.DataView>().relationLinks
}
is ObjectState.DataView.Set -> {
state.dataViewBlock.content<Block.Content.DataView>().relationLinks
}
else -> emptyList()
}
}
}

View file

@ -6,7 +6,6 @@ import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVSortType
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Marketplace.MARKETPLACE_ID
import com.anytypeio.anytype.core_models.MarketplaceObjectTypeIds
import com.anytypeio.anytype.core_models.ObjectTypeIds
@ -468,7 +467,9 @@ object ObjectSearchConstants {
Relations.RELATION_OPTION_COLOR,
Relations.COVER_TYPE,
Relations.COVER_ID,
Relations.PAGE_COVER
Relations.PAGE_COVER,
Relations.FILE_EXT,
Relations.FILE_MIME_TYPE
)
//endregion

View file

@ -20,7 +20,7 @@ class ObjectSetRecordViewModel(
viewModelScope.launch {
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = Relations.NAME,
value = input
)
@ -38,7 +38,7 @@ class ObjectSetRecordViewModel(
} else {
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = Relations.NAME,
value = input
)

View file

@ -522,7 +522,7 @@ class ObjectSetViewModel(
viewModelScope.launch {
setObjectDetails(
UpdateDetail.Params(
ctx = context,
target = context,
key = Relations.NAME,
value = txt
)
@ -632,7 +632,7 @@ class ObjectSetViewModel(
is CellView.Checkbox -> {
setObjectDetails(
UpdateDetail.Params(
ctx = cell.id,
target = cell.id,
key = cell.relationKey,
value = !cell.isChecked
)
@ -689,7 +689,7 @@ class ObjectSetViewModel(
if (obj != null) {
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = Relations.DONE,
value = !(obj.done ?: false)
)
@ -717,7 +717,7 @@ class ObjectSetViewModel(
viewModelScope.launch {
setObjectDetails(
UpdateDetail.Params(
ctx = objectId,
target = objectId,
key = relationKey,
value = value
)

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.sets
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_utils.const.DateConst.DEFAULT_DATE_FORMAT
import com.anytypeio.anytype.core_utils.ext.cancel
@ -14,6 +15,7 @@ import com.anytypeio.anytype.core_utils.ext.isSameDay
import com.anytypeio.anytype.presentation.relations.DateParser
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
import java.util.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@ -21,7 +23,6 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import java.util.*
class RelationDateValueViewModel(
private val relations: ObjectRelationProvider,
@ -34,11 +35,15 @@ class RelationDateValueViewModel(
private val jobs = mutableListOf<Job>()
fun onStart(relationKey: Key, objectId: String) {
fun onStart(
ctx: Id,
relationKey: Key,
objectId: String
) {
jobs += viewModelScope.launch {
val pipeline = combine(
relations.observe(relationKey),
values.subscribe(objectId)
values.subscribe(ctx = ctx, target = objectId)
) { relation, value ->
setName(relation.name)
setDate(timeInSeconds = DateParser.parse(value[relationKey]))

View file

@ -58,6 +58,7 @@ class RelationTextValueViewModel(
}
fun onStart(
ctx: Id,
relationKey: Key,
recordId: String,
isLocked: Boolean = false
@ -65,7 +66,7 @@ class RelationTextValueViewModel(
jobs += viewModelScope.launch {
val pipeline = combine(
relations.observe(relationKey),
values.subscribe(recordId)
values.subscribe(ctx = ctx, target = recordId)
) { relation, values ->
val obj = ObjectWrapper.Basic(values)
val value = values[relationKey]?.toString()

View file

@ -66,14 +66,20 @@ abstract class RelationValueBaseViewModel(
val commands = MutableSharedFlow<ObjectRelationValueCommand>(replay = 0)
val isLoading = MutableStateFlow(false)
fun onStart(objectId: Id, relationKey: Key) {
fun onStart(
ctx: Id,
objectId: Id,
relationKey: Key
) {
Timber.d("onStart")
jobs += viewModelScope.launch {
combine(
relations.observe(relationKey),
values.subscribe(objectId)
values.subscribe(ctx = ctx, target = objectId)
) { relation, record ->
initViewState(
ctx = ctx,
target = objectId,
relation = relation,
record = record,
relationKey = relationKey
@ -88,7 +94,9 @@ abstract class RelationValueBaseViewModel(
}
private suspend fun initViewState(
ctx: Id,
relation: ObjectWrapper.Relation,
target: Id,
record: Map<String, Any?>,
relationKey: Key
) {
@ -106,6 +114,8 @@ abstract class RelationValueBaseViewModel(
}
items.addAll(
parseTagRelationValues(
ctx = ctx,
target = target,
ids = ids,
isRemovable = isRemovable,
relationKey = relationKey
@ -121,6 +131,8 @@ abstract class RelationValueBaseViewModel(
}
items.addAll(
parseStatusRelationValues(
ctx = ctx,
target = target,
ids = ids,
relationKey = relationKey
)
@ -130,9 +142,16 @@ abstract class RelationValueBaseViewModel(
val isRemovable = isEditing.value
relationFormat = Relation.Format.OBJECT
val value = record.getOrDefault(relationKey, null)
// TODO remove code duplication below
if (value is List<*>) {
value.typeOf<Id>().forEach { id ->
val wrapper = resolveWrapperForObject(id)
val wrapper = if (ctx == target) {
ObjectWrapper.Basic(
details.provide()[id]?.map ?: emptyMap()
)
} else {
resolveWrapperForObject(ctx = ctx, target = id)
}
val type = wrapper.type.firstOrNull()
val objectType = type?.let { storeOfObjectTypes.get(it) }
if (wrapper.isDeleted == true) {
@ -161,7 +180,13 @@ abstract class RelationValueBaseViewModel(
}
}
} else if (value is Id) {
val wrapper = resolveWrapperForObject(value)
val wrapper = if (ctx == target) {
ObjectWrapper.Basic(
details.provide()[value]?.map ?: emptyMap()
)
} else {
resolveWrapperForObject(ctx = ctx, target = value)
}
val type = wrapper.type.firstOrNull()
val objectType = type?.let { storeOfObjectTypes.get(it) }
if (wrapper.isDeleted == true) {
@ -202,14 +227,20 @@ abstract class RelationValueBaseViewModel(
}
}
ids.forEach { id ->
val detail = details.provide()[id]
val wrapper = if (ctx == target) {
ObjectWrapper.Basic(
details.provide()[id]?.map ?: emptyMap()
)
} else {
resolveWrapperForObject(ctx = ctx, target = id)
}
items.add(
RelationValueView.File(
id = id,
name = detail?.name.orEmpty(),
mime = detail?.fileMimeType.orEmpty(),
ext = detail?.fileExt.orEmpty(),
image = detail?.iconImage,
name = wrapper.name.orEmpty(),
mime = wrapper.fileMimeType.orEmpty(),
ext = wrapper.fileExt.orEmpty(),
image = wrapper.iconImage,
removable = isRemovable
)
)
@ -229,21 +260,37 @@ abstract class RelationValueBaseViewModel(
name.value = relation.name.orEmpty()
}
/**
* [ctx] operational context
* [target] targeted object
* [ids] status options ids
*/
abstract suspend fun parseStatusRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
relationKey: Key
): List<RelationValueView.Option.Status>
/**
* [ctx] operational context
* [target] targeted object
* [ids] tags options ids
*/
abstract suspend fun parseTagRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
isRemovable: Boolean,
relationKey: Key
): List<RelationValueView.Option.Tag>
open suspend fun resolveWrapperForObject(id: Id): ObjectWrapper.Basic {
val detail = details.provide()[id]
open suspend fun resolveWrapperForObject(
ctx: Id, target: Id
): ObjectWrapper.Basic {
val detail = details.provide()[target]
if (detail == null || detail.map.isEmpty()) {
Timber.w("Could not found data for object: $id")
Timber.w("Could not found data for object: $target")
}
return ObjectWrapper.Basic(detail?.map ?: emptyMap())
}
@ -294,16 +341,17 @@ abstract class RelationValueBaseViewModel(
}
fun onRemoveTagFromObjectClicked(
ctx: Id,
target: Id,
relationKey: Key,
tag: Id
) {
viewModelScope.launch {
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
val remaining = obj[relationKey].filterIdsById(tag)
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = remaining
)
@ -318,6 +366,7 @@ abstract class RelationValueBaseViewModel(
}
fun onRemoveStatusFromObjectClicked(
ctx: Id,
target: Id,
relationKey: Key,
status: Id? = null
@ -326,11 +375,11 @@ abstract class RelationValueBaseViewModel(
val statusId = status ?: ((views.value.first {
it is RelationValueView.Option.Status
}) as? RelationValueView.Option.Status)?.id ?: return@launch
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
val remaining = obj[relationKey].filterIdsById(statusId)
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = remaining
)
@ -345,16 +394,17 @@ abstract class RelationValueBaseViewModel(
}
fun onRemoveObjectFromObjectClicked(
ctx: Id,
target: Id,
relationKey: Key,
objectId: Id
) {
viewModelScope.launch {
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
val remaining = obj[relationKey].filterIdsById(objectId)
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = remaining
)
@ -369,16 +419,17 @@ abstract class RelationValueBaseViewModel(
}
fun onRemoveFileFromObjectClicked(
ctx: Id,
target: Id,
relationKey: Key,
fileId: Id
) {
viewModelScope.launch {
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
val remaining = obj[relationKey].filterIdsById(fileId)
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = remaining
)
@ -400,7 +451,7 @@ abstract class RelationValueBaseViewModel(
viewModelScope.launch {
setObjectDetails(
UpdateDetail.Params(
ctx = target,
target = target,
key = relationKey,
value = order
)
@ -473,7 +524,7 @@ abstract class RelationValueBaseViewModel(
) {
viewModelScope.launch {
isLoading.emit(true)
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
addFileToObject(
params = AddFileToObject.Params(
ctx = target,
@ -569,11 +620,13 @@ class RelationValueDVViewModel(
) {
override suspend fun parseStatusRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
relationKey: Key
) = buildList {
ids.forEach { id ->
val option = values.get(id)
val option = values.get(ctx = ctx, target = id)
if (option.isNotEmpty()) {
val wrapper = ObjectWrapper.Option(option)
add(
@ -590,12 +643,20 @@ class RelationValueDVViewModel(
}
override suspend fun parseTagRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
isRemovable: Boolean,
relationKey: Key
) = buildList {
ids.forEach { id ->
val option = values.get(id)
val option = if (ctx == target)
details.provide()[id]?.map ?: emptyMap()
else
values.get(
ctx = ctx,
target = id
)
if (option.isNotEmpty()) {
val wrapper = ObjectWrapper.Option(option)
add(
@ -615,29 +676,36 @@ class RelationValueDVViewModel(
}
fun onAddObjectsOrFilesValueToRecord(
ctx: Id,
record: Id,
relationKey: Key,
ids: List<Id>
) {
viewModelScope.launch {
val rec = values.get(record)
val rec = if (ctx == record)
details.provide()[record]?.map ?: emptyMap()
else
values.get(ctx = ctx, target = record)
val value = rec[relationKey].addIds(ids)
setObjectDetails(
UpdateDetail.Params(
ctx = record,
target = record,
key = relationKey,
value = value
)
).process(
failure = { Timber.e(it, "Error while add objects or files value to record") },
success = { Timber.d("Successfully add objects or files value to record") }
success = { dispatcher.send(it) }
)
}
}
override suspend fun resolveWrapperForObject(id: Id): ObjectWrapper.Basic {
override suspend fun resolveWrapperForObject(
ctx: Id,
target: Id
): ObjectWrapper.Basic {
// For sets, we need to take values from db / store, and not from details.
return ObjectWrapper.Basic(values.get(target = id))
return ObjectWrapper.Basic(values.get(ctx = ctx, target = target))
}
class Factory(
@ -693,6 +761,8 @@ class RelationValueViewModel(
) {
override suspend fun parseStatusRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
relationKey: Key
) = buildList {
@ -714,6 +784,8 @@ class RelationValueViewModel(
}
override suspend fun parseTagRelationValues(
ctx: Id,
target: Id,
ids: List<Id>,
isRemovable: Boolean,
relationKey: Key
@ -745,11 +817,11 @@ class RelationValueViewModel(
ids: List<Id>
) {
viewModelScope.launch {
val obj = values.get(target)
val obj = values.get(ctx = ctx, target = target)
val remaining = obj[relationKey].addIds(ids)
updateDetail(
UpdateDetail.Params(
ctx = ctx,
target = ctx,
key = relationKey,
value = remaining
)

View file

@ -82,10 +82,21 @@ suspend fun List<ColumnView>.buildGridRow(
)
}
ColumnView.Format.FILE -> {
val files = obj.map.buildFileViews(
relationKey = column.key,
details = details
)
val files = buildList {
obj.getValues<Id>(column.key).forEach { id ->
val wrapper = store.get(id)
if (wrapper != null) {
add(
FileView(
id = id,
name = wrapper.name.orEmpty(),
mime = wrapper.fileMimeType.orEmpty(),
ext = wrapper.fileExt.orEmpty()
)
)
}
}
}
CellView.File(
id = obj.id,
relationKey = column.key,

View file

@ -60,8 +60,8 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
@ -96,7 +96,6 @@ import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions
import com.anytypeio.anytype.presentation.editor.editor.Command
import com.anytypeio.anytype.presentation.editor.editor.Interactor
import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager
import com.anytypeio.anytype.presentation.editor.editor.Markup
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
import com.anytypeio.anytype.presentation.editor.editor.ViewState
@ -4024,7 +4023,6 @@ open class EditorViewModelTest {
analytics = analytics,
dispatcher = Dispatcher.Default(),
delegator = delegator,
detailModificationManager = InternalDetailModificationManager(storage.details),
updateDetail = updateDetail,
searchObjects = searchObjects,
getDefaultPageType = getDefaultPageType,

View file

@ -48,9 +48,9 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
@ -435,7 +435,6 @@ open class EditorPresentationTestSetup {
analytics = analytics,
dispatcher = dispatcher,
delegator = delegator,
detailModificationManager = InternalDetailModificationManager(storage.details),
updateDetail = updateDetail,
searchObjects = searchObjects,
getDefaultPageType = getDefaultPageType,

View file

@ -7,8 +7,8 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.StubRelationObject
import com.anytypeio.anytype.core_models.StubRelationOptionObject
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.presentation.relations.RelationValueView.Option.Tag
import com.anytypeio.anytype.presentation.relations.add.AddOptionsRelationProvider
@ -19,6 +19,7 @@ import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvid
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
@ -29,7 +30,6 @@ import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import kotlin.test.assertEquals
@ExperimentalCoroutinesApi
class BaseAddOptionsRelationViewModelTest {
@ -42,15 +42,17 @@ class BaseAddOptionsRelationViewModelTest {
private val relation = StubRelationObject(
format = Relation.Format.TAG
)
private val relationId = relation.key
private val relationKey = relation.key
private val targetId = "stubTargetId"
private val relationsProvider = FakeObjectRelationProvider()
private val valuesProvider = FakeObjectValueProvider(
mapOf(
targetId to mapOf(relationId to listOf(selectedOption.id))
targetId to mapOf(relationKey to listOf(selectedOption.id))
)
)
private val ctx = MockDataFactory.randomUuid()
@Mock
lateinit var setObjectDetails: UpdateDetail
@ -91,7 +93,11 @@ class BaseAddOptionsRelationViewModelTest {
// TESTING
viewModel.ui.test {
viewModel.onStart(targetId, relationId)
viewModel.onStart(
ctx = ctx,
target = targetId,
relationKey = relationKey
)
// first item is emmit in constructor
val actual = listOf(awaitItem(), awaitItem())[1]
assertEquals(
@ -122,7 +128,11 @@ class BaseAddOptionsRelationViewModelTest {
// TESTING
viewModel.ui.test {
viewModel.onStart(targetId, relationId)
viewModel.onStart(
ctx = ctx,
target = targetId,
relationKey = relationKey
)
val query = MockDataFactory.randomString() + notSelectedOption.name.orEmpty()
viewModel.onFilterInputChanged(query)
// first item is emmit in constructor, second - at onStart
@ -157,7 +167,11 @@ class BaseAddOptionsRelationViewModelTest {
// TESTING
viewModel.ui.test {
viewModel.onStart(targetId, relationId)
viewModel.onStart(
ctx = ctx,
target = targetId,
relationKey = relationKey
)
val query = notSelectedOption.name.orEmpty().substring(1)
viewModel.onFilterInputChanged(query)
@ -194,7 +208,11 @@ class BaseAddOptionsRelationViewModelTest {
// TESTING
viewModel.ui.test {
viewModel.onStart(targetId, relationId)
viewModel.onStart(
ctx = ctx,
target = targetId,
relationKey = relationKey
)
// first item is emmit in constructor, second - at onStart
val actual = listOf(awaitItem(), awaitItem())[1]
assertEquals(
@ -231,7 +249,11 @@ class BaseAddOptionsRelationViewModelTest {
// TESTING
viewModel.ui.test {
viewModel.onStart(targetId, relationId)
viewModel.onStart(
ctx = ctx,
target = targetId,
relationKey = relationKey
)
val actual = listOf(awaitItem(), awaitItem())[1]
assertEquals(

View file

@ -8,8 +8,12 @@ internal class FakeObjectValueProvider(
var values: Map<Id, Map<String, Any?>> = emptyMap()
) : ObjectValueProvider {
override suspend fun get(target: Id): Map<String, Any?> = values[target] ?: emptyMap()
override suspend fun get(ctx: Id, target: Id): Map<String, Any?> = values[target] ?: emptyMap()
override suspend fun subscribe(target: Id): Flow<Map<String, Any?>> =
flow { emit(get(target)) }
override suspend fun subscribe(ctx: Id, target: Id): Flow<Map<String, Any?>> =
flow {
emit(
get(ctx = ctx, target = target)
)
}
}

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlin.test.assertEquals
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
@ -20,7 +21,6 @@ import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verifyBlocking
import org.mockito.kotlin.verifyNoInteractions
import kotlin.test.assertEquals
class ObjectSetRecordViewModelTest {
@ -50,7 +50,7 @@ class ObjectSetRecordViewModelTest {
val input = MockDataFactory.randomString()
val params = UpdateDetail.Params(
ctx = obj.id,
target = obj.id,
key = Relations.NAME,
value = input
)
@ -77,7 +77,7 @@ class ObjectSetRecordViewModelTest {
val input = MockDataFactory.randomString()
val params = UpdateDetail.Params(
ctx = obj.id,
target = obj.id,
key = Relations.NAME,
value = input
)
@ -114,7 +114,7 @@ class ObjectSetRecordViewModelTest {
val emptyInput = ""
val params = UpdateDetail.Params(
ctx = obj.id,
target = obj.id,
key = Relations.NAME,
value = emptyInput
)