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

DROID-166 Objects | Deleted object types (#2761)

* DROID-166 legacy

* DROID-166 move from objectType to storeOfObjectTypes

* DROID-166 legacy

* DROID-166 openDashboard useCase refactoring

* DROID-166 deprecated objectType model refactoring

* DROID-166 fix tests

* DROID-166 only change type for deleted types

* DROID-166 render deleted type

* DROID-166 code style

* DROID-166 set, deleted source

* DROID-166 ci

* DROID-166 ci off
This commit is contained in:
Konstantin Ivanov 2022-12-19 17:07:30 +01:00 committed by GitHub
parent 6f4687d169
commit a0e0e7362a
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 665 additions and 390 deletions

View file

@ -360,7 +360,8 @@ open class EditorTestSetup {
urlBuilder = urlBuilder,
toggleStateHolder = ToggleStateHolder.Default(),
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
),
orchestrator = Orchestrator(
createBlock = createBlock,

View file

@ -439,8 +439,7 @@ class DisplayRelationObjectValueTest {
"iconEmoji" to "👤"
)
)
),
objectTypes = listOf(objectType1, objectType2)
)
)
// TESTING
@ -570,8 +569,7 @@ class DisplayRelationObjectValueTest {
"iconEmoji" to "👤"
)
)
),
objectTypes = listOf()
)
)
// TESTING
@ -689,8 +687,7 @@ class DisplayRelationObjectValueTest {
Block.Fields.TYPE_KEY to objectType2.url
)
)
),
objectTypes = listOf(objectType1, objectType2)
)
)
// TESTING

View file

@ -172,11 +172,11 @@ object HomeDashboardModule {
@PerScreen
fun provideEventConverter(
builder: UrlBuilder,
objectTypesProvider: ObjectTypesProvider
storeOfObjectTypes: StoreOfObjectTypes
): HomeDashboardEventConverter {
return HomeDashboardEventConverter.DefaultConverter(
builder = builder,
objectTypesProvider = objectTypesProvider
storeOfObjectTypes = storeOfObjectTypes
)
}

View file

@ -4,7 +4,6 @@ import android.content.Context
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.ObjectType
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
@ -116,7 +115,6 @@ import com.anytypeio.anytype.presentation.relations.providers.DefaultObjectRelat
import com.anytypeio.anytype.presentation.relations.providers.DefaultObjectValueProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectTypeProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
import com.anytypeio.anytype.presentation.util.DefaultCopyFileToCacheDirectory
@ -322,12 +320,14 @@ object EditorSessionModule {
urlBuilder: UrlBuilder,
toggleStateHolder: ToggleStateHolder,
coverImageHashProvider: CoverImageHashProvider,
storeOfRelations: StoreOfRelations
storeOfRelations: StoreOfRelations,
storeOfObjectTypes: StoreOfObjectTypes
): DefaultBlockViewRenderer = DefaultBlockViewRenderer(
urlBuilder = urlBuilder,
toggleStateHolder = toggleStateHolder,
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
)
@JvmStatic
@ -841,15 +841,6 @@ object EditorUseCaseModule {
storage: Editor.Storage
): ObjectValueProvider = DefaultObjectValueProvider(storage.details)
@JvmStatic
@Provides
@PerScreen
fun provideObjectTypeProvider(
storage: Editor.Storage
): ObjectTypeProvider = object : ObjectTypeProvider {
override fun provide(): List<ObjectType> = storage.objectTypes.current()
}
@JvmStatic
@Provides
@PerScreen

View file

@ -3,7 +3,6 @@ package com.anytypeio.anytype.di.feature
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.ObjectType
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.feature.cover.UnsplashSubComponent
@ -56,7 +55,6 @@ import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectRela
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.ObjectTypeProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
import com.anytypeio.anytype.presentation.sets.ObjectSet
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -320,15 +318,6 @@ object ObjectSetModule {
db = db
)
@JvmStatic
@Provides
@PerScreen
fun provideObjectTypeProvider(
state: StateFlow<ObjectSet>,
): ObjectTypeProvider = object : ObjectTypeProvider {
override fun provide(): List<ObjectType> = state.value.objectTypes
}
@JvmStatic
@Provides
@PerScreen

View file

@ -10,13 +10,18 @@ class ObjectTypePopupMenu(
view: View,
onChangeTypeClicked: () -> Unit,
onOpenSetClicked: () -> Unit,
allowChangingObjectType: Boolean = false
allowChangingObjectType: Boolean = false,
allowOnlyChangingType: Boolean = false
) : PopupMenu(context, view) {
init {
if (allowChangingObjectType) {
menuInflater.inflate(R.menu.menu_object_type, menu)
if (allowOnlyChangingType) {
menuInflater.inflate(R.menu.menu_object_type_only, menu)
} else {
menuInflater.inflate(R.menu.menu_object_type_change_disabled, menu)
if (allowChangingObjectType) {
menuInflater.inflate(R.menu.menu_object_type, menu)
} else {
menuInflater.inflate(R.menu.menu_object_type_change_disabled, menu)
}
}
setOnMenuItemClickListener { item ->
when(item.itemId) {

View file

@ -219,7 +219,7 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
ids.add(placeholder.id)
}
}
is DocumentRelationView.ObjectType -> {
is DocumentRelationView.ObjectType.Base -> {
val view = TextView(context).apply {
id = generateViewId()
if (relation.name.isEmpty()) {
@ -251,7 +251,7 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
addView(view)
ids.add(view.id)
}
is DocumentRelationView.Source -> {
is DocumentRelationView.Source.Base -> {
if (relation.sources.isEmpty()) {
inflateEmptySourcePlaceholderTextView(
click = click,
@ -273,6 +273,37 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
}
}
}
is DocumentRelationView.Source.Deleted -> {
inflateDeletedSourceTextView(
click = click,
ids = ids
)
}
is DocumentRelationView.ObjectType.Deleted -> {
val view = TextView(context).apply {
id = generateViewId()
text = context.resources.getString(R.string.deleted_type)
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
setTextColor(context.getColor(R.color.palette_dark_red))
setTextSize(TypedValue.COMPLEX_UNIT_PX, defaultTextSize)
}
view.setOnClickListener {
val popup = ObjectTypePopupMenu(
context = context,
view = it,
onChangeTypeClicked = {
click(ListenerType.Relation.ChangeObjectType(type = relation.relationId))
},
onOpenSetClicked = {},
allowOnlyChangingType = true
)
popup.show()
}
addView(view)
ids.add(view.id)
}
}
if (index != item.relations.lastIndex) {
@ -306,7 +337,7 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
}
private fun inflateDefaultSourceTextView(
relation: DocumentRelationView.Source,
relation: DocumentRelationView.Source.Base,
click: (ListenerType.Relation) -> Unit,
ids: MutableList<Int>
) {
@ -345,7 +376,7 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
}
private fun inflateSourceByRelationTextView(
relation: DocumentRelationView.Source,
relation: DocumentRelationView.Source.Base,
click: (ListenerType.Relation) -> Unit,
ids: MutableList<Int>
) {
@ -378,6 +409,28 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
ids.add(view.id)
}
private fun inflateDeletedSourceTextView(
click: (ListenerType.Relation) -> Unit,
ids: MutableList<Int>
) {
val view = ObjectIconTextWidget(context).apply {
id = generateViewId()
setTextColor(context.color(R.color.palette_dark_red))
setTextSize(context.dimen(R.dimen.featured_relations_text_size))
setup(
name = context.getString(R.string.deleted_type),
icon = ObjectIcon.None
)
}
view.setOnClickListener {
click(
ListenerType.Relation.SetSource(sources = listOf())
)
}
addView(view)
ids.add(view.id)
}
private fun getPlaceholderHint(relation: DocumentRelationView.Default): String {
return when (relation.format) {
Relation.Format.SHORT_TEXT -> resources.getString(R.string.enter_text)

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/change_type"
android:title="@string/change_type" />
</menu>

View file

@ -188,6 +188,7 @@
<string name="add_block_option_icon">Add block option icon</string>
<string name="bookmark_error_menu_button">Bookmark error menu button</string>
<string name="bookmark_error">Something went wrong, try again</string>
<string name="deleted_type">Deleted type</string>
<string name="menu_item_bold">Bold</string>
<string name="menu_item_italic">Italic</string>

View file

@ -2,8 +2,7 @@ package com.anytypeio.anytype.domain.dashboard.interactor
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
@ -16,37 +15,14 @@ class OpenDashboard(
private val repo: BlockRepository,
private val auth: AuthRepository,
private val provider: ConfigStorage
) : BaseUseCase<Payload, OpenDashboard.Param?>() {
) : ResultInteractor<Unit, Payload>() {
override suspend fun run(params: Param?) = try {
if (params != null)
repo.openDashboard(
contextId = params.contextId,
id = params.id
).let {
Either.Right(it).also {
auth.clearLastOpenedObject()
}
}
else {
provider.get().let { config ->
repo.openDashboard(
contextId = config.home,
id = config.home
).let {
Either.Right(it).also {
auth.clearLastOpenedObject()
}
}
}
}
} catch (t: Throwable) {
Either.Left(t)
override suspend fun doWork(params: Unit): Payload {
val config = provider.get()
val payload = repo.openDashboard(
contextId = config.home,
id = config.home
)
return payload.also { auth.clearLastOpenedObject() }
}
/**
* @property id dashboard id
* @property contextId contextId id
*/
class Param(val contextId: String, val id: String)
}

View file

@ -49,21 +49,6 @@ class OpenDashboardTest {
)
}
@Test
fun `should open a dashboard based on the given params if these are present`() = runTest {
val params = OpenDashboard.Param(
contextId = MockDataFactory.randomUuid(),
id = MockDataFactory.randomUuid()
)
usecase.run(params)
verify(configStorage, never()).get()
verify(repo, times(1)).openDashboard(contextId = params.contextId, id = params.id)
verifyNoMoreInteractions(repo)
}
@Test
fun `should open a home dashboard if there are no params`() = runBlockingTest {
@ -73,7 +58,7 @@ class OpenDashboardTest {
onBlocking { get() } doReturn config
}
usecase.run(null)
usecase.run(Unit)
verify(configStorage, times(1)).get()
verify(repo, times(1)).openDashboard(

View file

@ -1,10 +0,0 @@
package com.anytypeio.anytype.presentation.dashboard
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.presentation.editor.editor.Store
interface Dashboard {
data class Storage(
val oTypes: Store.State<List<ObjectType>> = Store.State(emptyList())
)
}

View file

@ -1,10 +0,0 @@
package com.anytypeio.anytype.presentation.dashboard
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Url
data class DashboardProfileView(
val id: Id,
val name: String,
val image: Url?
)

View file

@ -4,18 +4,19 @@ import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.SmartBlockType
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import timber.log.Timber
interface HomeDashboardEventConverter {
fun convert(event: Event): HomeDashboardStateMachine.Event?
suspend fun convert(event: Event): HomeDashboardStateMachine.Event?
class DefaultConverter(
private val builder: UrlBuilder,
private val objectTypesProvider: ObjectTypesProvider
private val storeOfObjectTypes: StoreOfObjectTypes
) : HomeDashboardEventConverter {
override fun convert(event: Event) = when (event) {
override suspend fun convert(event: Event) = when (event) {
is Event.Command.UpdateStructure -> HomeDashboardStateMachine.Event.OnStructureUpdated(
event.children
)
@ -31,7 +32,7 @@ interface HomeDashboardEventConverter {
context = event.context,
details = event.details,
builder = builder,
objectTypes = objectTypesProvider.get()
objectTypes = storeOfObjectTypes.getAll()
)
}
else -> {

View file

@ -2,7 +2,7 @@ package com.anytypeio.anytype.presentation.dashboard
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.ObjectWrapper
import com.anytypeio.anytype.core_models.ext.amend
import com.anytypeio.anytype.core_models.ext.getChildrenIdsList
import com.anytypeio.anytype.core_models.ext.set
@ -62,7 +62,7 @@ sealed class HomeDashboardStateMachine {
val error: String?,
val blocks: List<DashboardView> = emptyList(),
val childrenIdsList: List<String> = emptyList(),
val objectTypes: List<ObjectType> = emptyList(),
val objectTypes: List<ObjectWrapper.Type> = emptyList(),
val details: Block.Details = Block.Details()
) : HomeDashboardStateMachine() {
companion object {
@ -83,7 +83,7 @@ sealed class HomeDashboardStateMachine {
val blocks: List<Block>,
val details: Block.Details,
val builder: UrlBuilder,
val objectTypes: List<ObjectType>
val objectTypes: List<ObjectWrapper.Type>
) : Event()
data class OnDetailsUpdated(
@ -254,7 +254,7 @@ sealed class HomeDashboardStateMachine {
}
}
fun State.findOTypeById(types: List<String>): ObjectType? {
fun State.findOTypeById(types: List<String>): ObjectWrapper.Type? {
val target = types.firstOrNull()
return objectTypes.find { oType -> oType.url == target }
return objectTypes.find { oType -> oType.id == target }
}

View file

@ -167,7 +167,7 @@ class HomeDashboardViewModel(
.launchIn(viewModelScope)
}
private fun processEvents(events: List<Event>) =
private suspend fun processEvents(events: List<Event>) =
events.mapNotNull { convert(it) }.let { result -> machine.onEvents(result) }
private fun proceedWithGettingConfig() {
@ -227,12 +227,12 @@ class HomeDashboardViewModel(
viewModelScope.launch {
val startTime = System.currentTimeMillis()
var middleTime = 0L
openDashboard(params = null).either(
fnR = { payload ->
openDashboard.execute(Unit).fold(
onSuccess = { payload ->
middleTime = System.currentTimeMillis()
processEvents(payload.events)
},
fnL = { Timber.e(it, "Error while opening home dashboard") }
onFailure = { Timber.e(it, "Error while opening home dashboard") }
)
viewModelScope.sendEvent(
analytics = analytics,

View file

@ -703,8 +703,7 @@ class EditorViewModel(
details = details,
relationLinks = orchestrator.stores.relationLinks.current(),
restrictions = orchestrator.stores.objectRestrictions.current(),
selection = currentSelection(),
objectTypes = orchestrator.stores.objectTypes.current()
selection = currentSelection()
) { onRenderFlagFound -> flags.add(onRenderFlagFound) }
if (flags.isNotEmpty()) {
doc.fillTableOfContents()

View file

@ -149,8 +149,7 @@ class ArchiveViewModel(
details = details,
relationLinks = emptyList(),
restrictions = emptyList(),
selection = emptySet(),
objectTypes = emptyList(),
selection = emptySet()
)
}
.map { views -> views.filterNot { it is BlockView.LinkToObject } }

View file

@ -39,6 +39,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_DELETED
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_LINK_LOADING
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_OBJECT_TYPE_DELETED
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PARAGRAPH
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE_ERROR
@ -51,6 +52,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_OBJECT
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_PLACEHOLDER
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_SOURCE
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_SOURCE_DELETED
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_STATUS
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_TAGS
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_TABLE
@ -1275,8 +1277,10 @@ sealed class BlockView : ViewType {
is DocumentRelationView.Tags -> HOLDER_RELATION_TAGS
is DocumentRelationView.Object -> HOLDER_RELATION_OBJECT
is DocumentRelationView.File -> HOLDER_RELATION_FILE
is DocumentRelationView.ObjectType -> HOLDER_OBJECT_TYPE
is DocumentRelationView.Source -> HOLDER_RELATION_SOURCE
is DocumentRelationView.ObjectType.Base -> HOLDER_OBJECT_TYPE
is DocumentRelationView.Source.Base -> HOLDER_RELATION_SOURCE
is DocumentRelationView.Source.Deleted -> HOLDER_RELATION_SOURCE_DELETED
is DocumentRelationView.ObjectType.Deleted -> HOLDER_OBJECT_TYPE_DELETED
}
}
}

View file

@ -57,10 +57,12 @@ object Types {
const val HOLDER_RELATION_FILE = 44
const val HOLDER_RELATION_CHECKBOX = 45
const val HOLDER_RELATION_SOURCE = 58
const val HOLDER_RELATION_SOURCE_DELETED = 159
const val HOLDER_DESCRIPTION = 46
const val HOLDER_FEATURED_RELATION = 47
const val HOLDER_OBJECT_TYPE = 48
const val HOLDER_OBJECT_TYPE_DELETED = 149
const val HOLDER_UNSUPPORTED = 49
const val HOLDER_LATEX = 51

View file

@ -1,11 +1,9 @@
package com.anytypeio.anytype.presentation.editor.editor.slash
import com.anytypeio.anytype.core_models.Url
import com.anytypeio.anytype.core_utils.const.SlashConst
import com.anytypeio.anytype.core_utils.const.SlashConst.SLASH_OTHER_TOC_ABBREVIATION
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
import com.anytypeio.anytype.core_models.ObjectType.Layout as ObjectTypeLayout
sealed class SlashWidgetState {
data class UpdateItems(

View file

@ -4,10 +4,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.analytics.base.EventsPropertiesKey
import com.anytypeio.anytype.analytics.base.sendEvent
import com.anytypeio.anytype.analytics.props.Props
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.Payload
@ -21,7 +17,6 @@ import com.anytypeio.anytype.presentation.mapper.toView
import com.anytypeio.anytype.presentation.objects.ObjectLayoutView
import com.anytypeio.anytype.presentation.util.Dispatcher
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

View file

@ -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.ObjectType
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.domain.editor.Editor
@ -32,7 +31,6 @@ interface BlockViewRenderer {
restrictions: List<ObjectRestriction>,
selection: Set<Id>,
count: Int = 0,
objectTypes: List<ObjectType>,
parentScheme: NestedDecorationData = emptyList(),
onRenderFlag: (RenderFlag) -> Unit = {},
): List<BlockView>

View file

@ -17,6 +17,7 @@ import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.domain.editor.Editor.Cursor
import com.anytypeio.anytype.domain.editor.Editor.Focus
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.presentation.BuildConfig.NESTED_DECORATION_ENABLED
import com.anytypeio.anytype.presentation.editor.Editor
@ -37,6 +38,7 @@ import com.anytypeio.anytype.presentation.relations.BasicObjectCoverWrapper
import com.anytypeio.anytype.presentation.relations.BlockFieldsCoverWrapper
import com.anytypeio.anytype.presentation.relations.DocumentRelationView
import com.anytypeio.anytype.presentation.relations.getCover
import com.anytypeio.anytype.presentation.relations.objectTypeRelation
import com.anytypeio.anytype.presentation.relations.view
import timber.log.Timber
import javax.inject.Inject
@ -46,7 +48,8 @@ class DefaultBlockViewRenderer @Inject constructor(
private val urlBuilder: UrlBuilder,
private val toggleStateHolder: ToggleStateHolder,
private val coverImageHashProvider: CoverImageHashProvider,
private val storeOfRelations: StoreOfRelations
private val storeOfRelations: StoreOfRelations,
private val storeOfObjectTypes: StoreOfObjectTypes
) : BlockViewRenderer, ToggleStateHolder by toggleStateHolder {
override suspend fun Map<Id, List<Block>>.render(
@ -60,7 +63,6 @@ class DefaultBlockViewRenderer @Inject constructor(
restrictions: List<ObjectRestriction>,
selection: Set<Id>,
count: Int,
objectTypes: List<ObjectType>,
parentScheme: NestedDecorationData,
onRenderFlag: (BlockViewRenderer.RenderFlag) -> Unit,
): List<BlockView> {
@ -135,7 +137,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -181,7 +182,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -220,8 +220,7 @@ class DefaultBlockViewRenderer @Inject constructor(
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme,
objectTypes = objectTypes
parentScheme = blockDecorationScheme
)
)
}
@ -260,7 +259,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -301,7 +299,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -342,7 +339,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -390,7 +386,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = if (NESTED_DECORATION_ENABLED)
(normalized + current)
@ -430,7 +425,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -483,7 +477,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -523,7 +516,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -568,7 +560,6 @@ class DefaultBlockViewRenderer @Inject constructor(
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
parentScheme = blockDecorationScheme
)
@ -636,7 +627,6 @@ class DefaultBlockViewRenderer @Inject constructor(
mode = mode,
selection = selection,
isPreviousBlockMedia = isPreviousBlockMedia,
objectTypes = objectTypes,
parentSchema = parentScheme
)
result.add(link)
@ -690,7 +680,6 @@ class DefaultBlockViewRenderer @Inject constructor(
restrictions = restrictions,
selection = selection,
count = mCounter,
objectTypes = objectTypes,
onRenderFlag = onRenderFlag,
)
)
@ -1566,7 +1555,7 @@ class DefaultBlockViewRenderer @Inject constructor(
}
}
private fun toLinks(
private suspend fun toLinks(
block: Block,
content: Content.Link,
indent: Int,
@ -1574,7 +1563,6 @@ class DefaultBlockViewRenderer @Inject constructor(
mode: EditorMode,
selection: Set<Id>,
isPreviousBlockMedia: Boolean,
objectTypes: List<ObjectType>,
parentSchema: NestedDecorationData
): BlockView.LinkToObject {
if (obj.isEmpty()) {
@ -1612,14 +1600,13 @@ class DefaultBlockViewRenderer @Inject constructor(
mode = mode,
selection = selection,
isPreviousBlockMedia = isPreviousBlockMedia,
objectTypes = objectTypes,
parentSchema = parentSchema
)
}
}
}
private fun link(
private suspend fun link(
mode: Editor.Mode,
block: Block,
content: Content.Link,
@ -1627,7 +1614,6 @@ class DefaultBlockViewRenderer @Inject constructor(
obj: ObjectWrapper.Basic,
selection: Set<Id>,
isPreviousBlockMedia: Boolean,
objectTypes: List<ObjectType>,
parentSchema: NestedDecorationData
): BlockView.LinkToObject.Default {
val factory = LinkAppearanceFactory(content, obj.layout)
@ -1653,7 +1639,7 @@ class DefaultBlockViewRenderer @Inject constructor(
val objectTypeName = if (inEditorAppearance.showType) {
val typeUrl = obj.type.firstOrNull()
objectTypes.find { it.url == typeUrl }?.name
if (typeUrl != null) storeOfObjectTypes.get(typeUrl)?.name else null
} else {
null
}
@ -2106,12 +2092,10 @@ class DefaultBlockViewRenderer @Inject constructor(
Relations.TYPE -> {
val objectTypeId = details.details[ctx]?.type?.firstOrNull()
if (objectTypeId != null) {
DocumentRelationView.ObjectType(
relationId = objectTypeId,
details.objectTypeRelation(
relationKey = key,
name = details.details[objectTypeId]?.name.orEmpty(),
isFeatured = true,
type = objectTypeId
objectTypeId = objectTypeId
)
} else {
null

View file

@ -1,7 +1,6 @@
package com.anytypeio.anytype.presentation.extension
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.dashboard.DashboardView
@ -30,7 +29,7 @@ fun List<DashboardView>.updateDetails(
target: String,
details: Block.Fields,
builder: UrlBuilder,
objectTypes: List<ObjectType>
objectTypes: List<ObjectWrapper.Type>
): List<DashboardView> {
return mapNotNull { view ->
when (view) {
@ -63,7 +62,7 @@ fun List<DashboardView>.updateDetails(
),
layout = obj.layout,
type = obj.type.firstOrNull(),
typeName = objectTypes.find { it.url == obj.type.firstOrNull() }?.name
typeName = objectTypes.find { it.id == obj.type.firstOrNull() }?.name
)
} else {
view

View file

@ -5,7 +5,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.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.SmartBlockType
import com.anytypeio.anytype.domain.base.Resultat

View file

@ -65,17 +65,27 @@ sealed class DocumentRelationView : DefaultObjectDiffIdentifier {
val objects: List<ObjectView>
) : DocumentRelationView()
data class Source(
override val relationId: Id,
override val relationKey: Key,
override val name: String,
override val value: String? = null,
override val isFeatured: Boolean = false,
val sources: List<ObjectView>
) : DocumentRelationView() {
val isSourceByRelation : Boolean get() = sources.any { s ->
s is ObjectView.Default && s.isRelation
sealed class Source : DocumentRelationView() {
data class Base(
override val relationId: Id,
override val relationKey: Key,
override val name: String,
override val value: String? = null,
override val isFeatured: Boolean = false,
val sources: List<ObjectView>
) : Source() {
val isSourceByRelation : Boolean get() = sources.any { s ->
s is ObjectView.Default && s.isRelation
}
}
data class Deleted(
override val relationId: Id,
override val relationKey: Key,
override val name: String,
override val value: String? = null,
override val isFeatured: Boolean = false
) : Source()
}
data class File(
@ -87,16 +97,22 @@ sealed class DocumentRelationView : DefaultObjectDiffIdentifier {
val files: List<FileView>
) : DocumentRelationView()
/**
* @property [type] object type id
* @property [relationId] id of the relation
*/
data class ObjectType(
override val relationId: Id,
override val relationKey: Key,
override val name: String,
override val value: String? = null,
override val isFeatured: Boolean = false,
val type: Id
) : DocumentRelationView()
sealed class ObjectType : DocumentRelationView() {
data class Base(
override val relationId: Id,
override val relationKey: Key,
override val name: String,
override val value: String? = null,
override val isFeatured: Boolean = false,
val type: Id
) : ObjectType()
data class Deleted(
override val relationId: Id,
override val relationKey: Key,
override val name: String = "",
override val value: String? = null,
override val isFeatured: Boolean = false,
) : ObjectType()
}
}

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.relations
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_utils.const.DateConst
@ -208,6 +209,34 @@ fun tagRelation(
)
}
fun Block.Details.objectTypeRelation(
relationKey: Key,
isFeatured: Boolean,
objectTypeId: Id
): DocumentRelationView {
val typeDetails = details[objectTypeId]?.map
val objectType = if (typeDetails != null) {
ObjectWrapper.Type(typeDetails)
} else {
null
}
return if (objectType == null || objectType.isDeleted == true) {
DocumentRelationView.ObjectType.Deleted(
relationId = objectTypeId,
relationKey = relationKey,
isFeatured = isFeatured
)
} else {
DocumentRelationView.ObjectType.Base(
relationId = objectTypeId,
relationKey = relationKey,
name = details[objectTypeId]?.name.orEmpty(),
isFeatured = isFeatured,
type = objectTypeId
)
}
}
object StatusParser {
fun parse(value: Any?): Id? {
val result: Id? = when (value) {

View file

@ -1,7 +0,0 @@
package com.anytypeio.anytype.presentation.relations.providers
import com.anytypeio.anytype.core_models.ObjectType
interface ObjectTypeProvider {
fun provide() : List<ObjectType>
}

View file

@ -4,8 +4,6 @@ import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.DV
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.restrictions.DataViewRestrictions
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
@ -13,8 +11,6 @@ import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
data class ObjectSet(
val blocks: List<Block> = emptyList(),
val details: Map<Id, Block.Fields> = emptyMap(),
val objectTypes: List<ObjectType> = emptyList(),
val relations: List<Relation> = emptyList(),
val objectRestrictions: List<ObjectRestriction> = emptyList(),
val restrictions: List<DataViewRestrictions> = emptyList()
) {

View file

@ -14,6 +14,7 @@ import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.getProperName
import com.anytypeio.anytype.presentation.relations.DocumentRelationView
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig.ID_KEY
import com.anytypeio.anytype.presentation.relations.objectTypeRelation
import com.anytypeio.anytype.presentation.relations.view
import com.anytypeio.anytype.presentation.sets.model.ObjectView
import com.anytypeio.anytype.presentation.sets.model.SimpleRelationView
@ -57,12 +58,10 @@ private fun mapFeaturedRelations(
Relations.TYPE -> {
val objectTypeId = details.details[ctx]?.type?.firstOrNull()
if (objectTypeId != null) {
DocumentRelationView.ObjectType(
relationId = details.details[ctx]?.id.orEmpty(),
details.objectTypeRelation(
relationKey = key,
name = details.details[objectTypeId]?.name.orEmpty(),
isFeatured = true,
type = objectTypeId
objectTypeId = objectTypeId
)
} else {
null
@ -71,21 +70,45 @@ private fun mapFeaturedRelations(
Relations.SET_OF -> {
val objectSet = ObjectWrapper.Basic(details.details[ctx]?.map.orEmpty())
val sources = mutableListOf<ObjectView>()
objectSet.setOf.forEach { sourceId ->
val wrapper = ObjectWrapper.Basic(details.details[sourceId]?.map.orEmpty())
val source = objectSet.setOf.firstOrNull()
if (source != null) {
val wrapper = ObjectWrapper.Basic(details.details[source]?.map.orEmpty())
if (!wrapper.isEmpty()) {
sources.add(
wrapper.toObjectView(urlBuilder = urlBuilder)
if (wrapper.isDeleted == true) {
DocumentRelationView.Source.Deleted(
relationId = details.details[ctx]?.id.orEmpty(),
relationKey = key,
name = Relations.RELATION_NAME_EMPTY,
isFeatured = true
)
} else {
sources.add(wrapper.toObjectView(urlBuilder = urlBuilder))
DocumentRelationView.Source.Base(
relationId = details.details[ctx]?.id.orEmpty(),
relationKey = key,
name = Relations.RELATION_NAME_EMPTY,
isFeatured = true,
sources = sources
)
}
} else {
DocumentRelationView.Source.Base(
relationId = details.details[ctx]?.id.orEmpty(),
relationKey = key,
name = Relations.RELATION_NAME_EMPTY,
isFeatured = true,
sources = sources
)
}
} else {
DocumentRelationView.Source.Base(
relationId = details.details[ctx]?.id.orEmpty(),
relationKey = key,
name = Relations.RELATION_NAME_EMPTY,
isFeatured = true,
sources = sources
)
}
DocumentRelationView.Source(
relationId = details.details[ctx]?.id.orEmpty(),
relationKey = key,
name = Relations.RELATION_NAME_EMPTY,
isFeatured = true,
sources = sources
)
}
else -> {
val relation = relations.firstOrNull { it.key == key }

View file

@ -59,9 +59,7 @@ class ObjectSetReducer {
state.copy(
blocks = event.blocks,
details = state.details.updateFields(event.details.details),
objectTypes = event.objectTypes,
restrictions = event.dataViewRestrictions,
relations = event.relations,
objectRestrictions = event.objectRestrictions
)
}

View file

@ -53,8 +53,7 @@ class TemplateViewModel(
details = event.details,
relationLinks = event.relationLinks,
restrictions = event.objectRestrictions,
selection = emptySet(),
objectTypes = event.objectTypes
selection = emptySet()
)
}
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
import com.anytypeio.anytype.domain.auth.interactor.GetProfile
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.block.interactor.Move
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.DebugSettings
@ -128,7 +129,7 @@ open class DashboardTestSetup {
interceptEvents = interceptEvents,
eventConverter = HomeDashboardEventConverter.DefaultConverter(
builder = builder,
objectTypesProvider = objectTypesProvider
storeOfObjectTypes = storeOfObjectTypes
),
getDebugSettings = getDebugSettings,
analytics = analytics,
@ -178,7 +179,7 @@ open class DashboardTestSetup {
)
) {
openDashboard.stub {
onBlocking { invoke(params = null) } doReturn Either.Right(payload)
onBlocking { execute(params = Unit) } doReturn Resultat.success(payload)
}
}

View file

@ -59,6 +59,7 @@ import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoInteractions
import kotlin.test.assertContains
import kotlin.test.assertEquals
class HomeDashboardViewModelTest {
@ -142,7 +143,7 @@ class HomeDashboardViewModelTest {
interceptEvents = interceptEvents,
eventConverter = HomeDashboardEventConverter.DefaultConverter(
builder = builder,
objectTypesProvider = objectTypesProvider
storeOfObjectTypes = storeOfObjectTypes
),
getDebugSettings = getDebugSettings,
analytics = analytics,
@ -317,15 +318,17 @@ class HomeDashboardViewModelTest {
)
)
vm.state.test().assertValue(
HomeDashboardStateMachine.State(
isLoading = false,
isInitialzed = true,
blocks = views,
childrenIdsList = listOf(dashboard).getChildrenIdsList(dashboard.id),
error = null
)
val expected = HomeDashboardStateMachine.State(
isLoading = false,
isInitialzed = true,
blocks = views,
childrenIdsList = listOf(dashboard).getChildrenIdsList(dashboard.id),
error = null
)
val actual = vm.state.test().value()
assertEquals(expected = expected, actual = actual)
coroutineTestRule.advanceTime(200L)
}
@Test
@ -344,7 +347,7 @@ class HomeDashboardViewModelTest {
vm.onViewCreated()
runBlockingTest {
verify(openDashboard, times(1)).invoke(eq(null))
verify(openDashboard, times(1)).execute(eq(Unit))
}
}
@ -408,7 +411,7 @@ class HomeDashboardViewModelTest {
)
) {
openDashboard.stub {
onBlocking { invoke(params = null) } doReturn Either.Right(payload)
onBlocking { execute(params = Unit) } doReturn Resultat.success(payload)
}
}

View file

@ -21,6 +21,7 @@ import com.anytypeio.anytype.core_utils.const.DetailsKeys
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.editor.Editor
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.emojifier.data.DefaultDocumentEmojiIconProvider
@ -75,7 +76,6 @@ class DefaultBlockViewRendererTest {
relationLinks = emptyList(),
restrictions = restrictions,
selection = emptySet(),
objectTypes = emptyList(),
parentScheme = schema
)
}
@ -103,6 +103,7 @@ class DefaultBlockViewRendererTest {
private var storeOfRelations: StoreOfRelations = DefaultStoreOfRelations()
private val storeOfObjectTypes = DefaultStoreOfObjectTypes()
@Before
fun setup() {
@ -111,7 +112,8 @@ class DefaultBlockViewRendererTest {
urlBuilder = UrlBuilder(gateway),
toggleStateHolder = toggleStateHolder,
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
)
}

View file

@ -3955,7 +3955,8 @@ open class EditorViewModelTest {
urlBuilder = urlBuilder,
toggleStateHolder = ToggleStateHolder.Default(),
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
),
orchestrator = Orchestrator(
createBlock = createBlock,

View file

@ -146,7 +146,7 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType(
DocumentRelationView.ObjectType.Base(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,
@ -405,7 +405,388 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
}
@Test
fun `should not render text featured relation when appropriate relation is not present`() = runTest {
fun `should not render text featured relation when appropriate relation is not present`() =
runTest {
val title = MockTypicalDocumentFactory.title
val header = MockTypicalDocumentFactory.header
val block = MockTypicalDocumentFactory.a
val featuredBlock = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.FeaturedRelations
)
val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart(SmartBlockType.PAGE),
children = listOf(header.id, featuredBlock.id, block.id)
)
val doc = listOf(page, header, title, block, featuredBlock)
val objectTypeId = MockDataFactory.randomString()
val objectTypeName = "Movie"
val objectTypeDescription = MockDataFactory.randomString()
val r1 = MockTypicalDocumentFactory.relationObject("Ad")
val r2 = MockTypicalDocumentFactory.relationObject("De")
val r3 = MockTypicalDocumentFactory.relationObject("HJ")
val relationObjectType = StubRelationObject(
key = Block.Fields.TYPE_KEY,
name = "Object Type",
format = Relation.Format.OBJECT
)
val value1 = MockDataFactory.randomString()
val value2 = MockDataFactory.randomString()
val value3 = MockDataFactory.randomString()
val objectFields = Block.Fields(
mapOf(
r1.key to value1,
r2.key to value2,
r3.key to value3,
relationObjectType.key to objectTypeId,
Relations.FEATURED_RELATIONS to listOf(relationObjectType.key, r3.key)
)
)
val objectTypeFields = Block.Fields(
mapOf(
Relations.NAME to objectTypeName,
Relations.DESCRIPTION to objectTypeDescription
)
)
val customDetails = Block.Details(
mapOf(
root to objectFields,
objectTypeId to objectTypeFields
)
)
stubInterceptEvents()
stubSearchObjects()
stubOpenDocument(
document = doc,
details = customDetails,
relations = emptyList()
)
storeOfRelations.merge(
listOf(r1, r2, relationObjectType)
)
val vm = buildViewModel()
vm.onStart(root)
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
isFocused = false,
text = title.content<Block.Content.Text>().text,
emoji = null
),
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType.Base(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,
isFeatured = true,
type = objectTypeId
)
)
),
BlockView.Text.Numbered(
isFocused = false,
id = block.id,
marks = emptyList(),
background = block.parseThemeBackgroundColor(),
text = block.content<Block.Content.Text>().text,
alignment = block.content<Block.Content.Text>().align?.toView(),
number = 1,
decorations = if (BuildConfig.NESTED_DECORATION_ENABLED) {
listOf(
BlockView.Decoration(
background = block.parseThemeBackgroundColor()
)
)
} else {
emptyList()
}
)
)
assertEquals(
expected = ViewState.Success(expected),
actual = vm.state.value
)
}
@Test
fun `should not render relation in featured relations if corresponding relation is hidden`() =
runTest {
val title = MockTypicalDocumentFactory.title
val header = MockTypicalDocumentFactory.header
val block = MockTypicalDocumentFactory.a
val r1 = MockTypicalDocumentFactory.relationObject(name = "Ad", isHidden = false)
val r2 = MockTypicalDocumentFactory.relationObject(name = "De", isHidden = true)
val r3 = MockTypicalDocumentFactory.relationObject(name = "HJ", isHidden = true)
val featuredBlock = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.FeaturedRelations
)
val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart(SmartBlockType.PAGE),
children = listOf(header.id, featuredBlock.id, block.id)
)
val doc = listOf(page, header, title, block, featuredBlock)
val objectTypeId = MockDataFactory.randomString()
val objectTypeName = MockDataFactory.randomString()
val objectTypeDescription = MockDataFactory.randomString()
val relationObjectType = StubObjectType(
id = objectTypeId,
name = "Object Type"
)
val value1 = MockDataFactory.randomString()
val value2 = MockDataFactory.randomString()
val value3 = MockDataFactory.randomString()
val objectFields = Block.Fields(
mapOf(
r1.key to value1,
r2.key to value2,
r3.key to value3,
Relations.TYPE to objectTypeId,
Relations.FEATURED_RELATIONS to listOf(Relations.TYPE, r1.key, r2.key, r3.key)
)
)
val objectTypeFields = Block.Fields(
mapOf(
Relations.NAME to objectTypeName,
Relations.DESCRIPTION to objectTypeDescription
)
)
val customDetails = Block.Details(
mapOf(
root to objectFields,
objectTypeId to objectTypeFields
)
)
stubInterceptEvents()
stubInterceptThreadStatus()
stubSearchObjects()
stubOpenDocument(
document = doc,
details = customDetails,
relations = emptyList()
)
storeOfRelations.merge(
listOf(r1, r2, r3)
)
storeOfObjectTypes.merge(
listOf(relationObjectType)
)
val vm = buildViewModel()
vm.onStart(root)
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
isFocused = false,
text = title.content<Block.Content.Text>().text,
emoji = null
),
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType.Base(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,
isFeatured = true,
type = objectTypeId
),
DocumentRelationView.Default(
relationId = r1.id,
relationKey = r1.key,
name = r1.name.orEmpty(),
value = value1,
isFeatured = true,
format = Relation.Format.SHORT_TEXT
)
)
),
BlockView.Text.Numbered(
isFocused = false,
id = block.id,
marks = emptyList(),
background = block.parseThemeBackgroundColor(),
text = block.content<Block.Content.Text>().text,
alignment = block.content<Block.Content.Text>().align?.toView(),
number = 1,
decorations = if (BuildConfig.NESTED_DECORATION_ENABLED) {
listOf(
BlockView.Decoration(
background = block.parseThemeBackgroundColor()
)
)
} else {
emptyList()
}
)
)
assertEquals(
expected = ViewState.Success(expected),
actual = vm.state.value
)
}
@Test
fun `should render deleted object type as featured relation when type is not present in details`() =
runTest {
val title = MockTypicalDocumentFactory.title
val header = MockTypicalDocumentFactory.header
val block = MockTypicalDocumentFactory.a
val featuredBlock = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.FeaturedRelations
)
val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart(SmartBlockType.PAGE),
children = listOf(header.id, featuredBlock.id, block.id)
)
val doc = listOf(page, header, title, block, featuredBlock)
val objectTypeId = MockDataFactory.randomString()
val r1 = MockTypicalDocumentFactory.relationObject("Ad")
val r2 = MockTypicalDocumentFactory.relationObject("De")
val r3 = MockTypicalDocumentFactory.relationObject("HJ")
val relationObjectType = StubObjectType(
id = objectTypeId
)
val value1 = MockDataFactory.randomString()
val value2 = MockDataFactory.randomString()
val value3 = MockDataFactory.randomString()
val objectFields = Block.Fields(
mapOf(
r1.key to value1,
r2.key to value2,
r3.key to value3,
Relations.TYPE to objectTypeId,
Relations.FEATURED_RELATIONS to listOf(Relations.TYPE, r3.key)
)
)
val customDetails = Block.Details(mapOf(root to objectFields))
stubInterceptEvents()
stubInterceptThreadStatus()
stubSearchObjects()
stubOpenDocument(
document = doc,
details = customDetails,
relations = emptyList()
)
storeOfRelations.merge(
listOf(r1, r2, r3)
)
storeOfObjectTypes.merge(
types = listOf(relationObjectType)
)
val vm = buildViewModel()
vm.onStart(root)
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
isFocused = false,
text = title.content<Block.Content.Text>().text,
emoji = null
),
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType.Deleted(
relationId = objectTypeId,
relationKey = Relations.TYPE,
isFeatured = true
),
DocumentRelationView.Default(
relationId = r3.id,
relationKey = r3.key,
name = r3.name.orEmpty(),
value = value3,
isFeatured = true,
format = Relation.Format.SHORT_TEXT
)
)
),
BlockView.Text.Numbered(
isFocused = false,
id = block.id,
marks = emptyList(),
background = block.parseThemeBackgroundColor(),
text = block.content<Block.Content.Text>().text,
alignment = block.content<Block.Content.Text>().align?.toView(),
number = 1,
decorations = if (BuildConfig.NESTED_DECORATION_ENABLED) {
listOf(
BlockView.Decoration(
background = block.parseThemeBackgroundColor()
)
)
} else {
emptyList()
}
)
)
assertEquals(
expected = ViewState.Success(expected),
actual = vm.state.value
)
}
@Test
fun `should render deleted object type as featured relation when flag is deleted`() = runTest {
val title = MockTypicalDocumentFactory.title
val header = MockTypicalDocumentFactory.header
@ -427,168 +808,37 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
val doc = listOf(page, header, title, block, featuredBlock)
val objectTypeId = MockDataFactory.randomString()
val objectTypeName = "Movie"
val objectTypeDescription = MockDataFactory.randomString()
val r1 = MockTypicalDocumentFactory.relationObject("Ad")
val r2 = MockTypicalDocumentFactory.relationObject("De")
val r3 = MockTypicalDocumentFactory.relationObject("HJ")
val relationObjectType = StubRelationObject(
key = Block.Fields.TYPE_KEY,
name = "Object Type",
format = Relation.Format.OBJECT
)
val value1 = MockDataFactory.randomString()
val value2 = MockDataFactory.randomString()
val value3 = MockDataFactory.randomString()
val objectFields = Block.Fields(
mapOf(
r1.key to value1,
r2.key to value2,
r3.key to value3,
relationObjectType.key to objectTypeId,
Relations.FEATURED_RELATIONS to listOf(relationObjectType.key, r3.key)
)
)
val objectTypeFields = Block.Fields(
mapOf(
Relations.NAME to objectTypeName,
Relations.DESCRIPTION to objectTypeDescription
)
)
val customDetails = Block.Details(
mapOf(
root to objectFields,
objectTypeId to objectTypeFields
)
)
stubInterceptEvents()
stubSearchObjects()
stubOpenDocument(
document = doc,
details = customDetails,
relations = emptyList()
)
storeOfRelations.merge(
listOf(r1, r2, relationObjectType)
)
val vm = buildViewModel()
vm.onStart(root)
val expected = listOf(
BlockView.Title.Basic(
id = title.id,
isFocused = false,
text = title.content<Block.Content.Text>().text,
emoji = null
),
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,
isFeatured = true,
type = objectTypeId
)
)
),
BlockView.Text.Numbered(
isFocused = false,
id = block.id,
marks = emptyList(),
background = block.parseThemeBackgroundColor(),
text = block.content<Block.Content.Text>().text,
alignment = block.content<Block.Content.Text>().align?.toView(),
number = 1,
decorations = if (BuildConfig.NESTED_DECORATION_ENABLED) {
listOf(
BlockView.Decoration(
background = block.parseThemeBackgroundColor()
)
)
} else {
emptyList()
}
)
)
assertEquals(
expected = ViewState.Success(expected),
actual = vm.state.value
)
}
@Test
fun `should not render relation in featured relations if corresponding relation is hidden`() = runTest {
val title = MockTypicalDocumentFactory.title
val header = MockTypicalDocumentFactory.header
val block = MockTypicalDocumentFactory.a
val r1 = MockTypicalDocumentFactory.relationObject(name = "Ad", isHidden = false)
val r2 = MockTypicalDocumentFactory.relationObject(name = "De", isHidden = true)
val r3 = MockTypicalDocumentFactory.relationObject(name = "HJ", isHidden = true)
val featuredBlock = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.FeaturedRelations
)
val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart(SmartBlockType.PAGE),
children = listOf(header.id, featuredBlock.id, block.id)
)
val doc = listOf(page, header, title, block, featuredBlock)
val objectTypeId = MockDataFactory.randomString()
val objectTypeName = MockDataFactory.randomString()
val objectTypeDescription = MockDataFactory.randomString()
val relationObjectType = StubObjectType(
id = objectTypeId,
name = "Object Type"
id = objectTypeId
)
val value1 = MockDataFactory.randomString()
val value2 = MockDataFactory.randomString()
val value3 = MockDataFactory.randomString()
val objectFields = Block.Fields(
mapOf(
r1.key to value1,
r2.key to value2,
r3.key to value3,
Relations.TYPE to objectTypeId,
Relations.FEATURED_RELATIONS to listOf(Relations.TYPE, r1.key, r2.key, r3.key)
Relations.FEATURED_RELATIONS to listOf(Relations.TYPE, r3.key)
)
)
val objectTypeFields = Block.Fields(
mapOf(
Relations.NAME to objectTypeName,
Relations.DESCRIPTION to objectTypeDescription
)
)
val customDetails = Block.Details(
mapOf(
root to objectFields,
objectTypeId to objectTypeFields
Relations.IS_DELETED to true
)
)
val customDetails =
Block.Details(mapOf(root to objectFields, objectTypeId to objectTypeFields))
stubInterceptEvents()
stubInterceptThreadStatus()
stubSearchObjects()
@ -603,7 +853,7 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
)
storeOfObjectTypes.merge(
listOf(relationObjectType)
types = listOf(relationObjectType)
)
val vm = buildViewModel()
@ -620,18 +870,16 @@ class EditorFeaturedRelationsTest : EditorPresentationTestSetup() {
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType(
DocumentRelationView.ObjectType.Deleted(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,
isFeatured = true,
type = objectTypeId
isFeatured = true
),
DocumentRelationView.Default(
relationId = r1.id,
relationKey = r1.key,
name = r1.name.orEmpty(),
value = value1,
relationId = r3.id,
relationKey = r3.key,
name = r3.name.orEmpty(),
value = value3,
isFeatured = true,
format = Relation.Format.SHORT_TEXT
)

View file

@ -145,7 +145,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType(
DocumentRelationView.ObjectType.Base(
relationId = objectType.id,
relationKey = Relations.TYPE,
name = objectTypeName,
@ -261,7 +261,7 @@ class EditorNoteLayoutTest : EditorPresentationTestSetup() {
BlockView.FeaturedRelation(
id = featuredBlock.id,
relations = listOf(
DocumentRelationView.ObjectType(
DocumentRelationView.ObjectType.Base(
relationId = objectTypeId,
relationKey = Relations.TYPE,
name = objectTypeName,

View file

@ -410,7 +410,8 @@ open class EditorPresentationTestSetup {
urlBuilder = urlBuilder,
toggleStateHolder = ToggleStateHolder.Default(),
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
),
orchestrator = orchestrator,
analytics = analytics,

View file

@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.editor.Editor
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
@ -60,8 +61,7 @@ class TableBlockRendererTest {
details = details,
relationLinks = emptyList(),
restrictions = restrictions,
selection = selections,
objectTypes = listOf()
selection = selections
)
}
@ -88,6 +88,8 @@ class TableBlockRendererTest {
private var storeOfRelations = DefaultStoreOfRelations()
private val storeOfObjectTypes = DefaultStoreOfObjectTypes()
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
@ -95,7 +97,8 @@ class TableBlockRendererTest {
urlBuilder = UrlBuilder(gateway),
toggleStateHolder = toggleStateHolder,
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
)
}