Skip to content

Commit

Permalink
DROID-3039 Editor | Show types widget only for an empty title (#1936)
Browse files Browse the repository at this point in the history
  • Loading branch information
konstantiniiv authored Dec 18, 2024
1 parent 9cbe168 commit b0c79c5
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.TimeInSeconds
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Event.SAM.*
import com.anytypeio.anytype.presentation.editor.editor.Intent.Clipboard.*
import com.anytypeio.anytype.presentation.editor.editor.ext.isAllowedToShowTypesWidget
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnDatePickerDismiss
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnDateSelected
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnTodayClick
Expand Down Expand Up @@ -7606,9 +7607,15 @@ class EditorViewModel(
}
}
containsFlag -> {
val restrictions = orchestrator.stores.objectRestrictions.current()
if (restrictions.none { it == ObjectRestriction.TYPE_CHANGE } && isUserEditor) {
if (blocks.isAllowedToShowTypesWidget(
objectRestrictions = orchestrator.stores.objectRestrictions.current(),
isOwnerOrEditor = permission.value?.isOwnerOrEditor() == true,
objectLayout = orchestrator.stores.details.current().details[context]?.layout?.toInt()
)
) {
setTypesWidgetVisibility(true)
} else {
Timber.d("Object doesn't allow to show types widget, skip")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.anytypeio.anytype.presentation.editor.editor.ext

import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Block.Content
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.MAX_SNIPPET_SIZE
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.ext.replaceRangeWithWord
import com.anytypeio.anytype.core_models.ext.title
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.BuildConfig
import com.anytypeio.anytype.presentation.editor.editor.Markup
Expand Down Expand Up @@ -88,3 +92,17 @@ private fun Map<Id, Block.Fields>.getProperObjectName(id: Id?): String? {
}
}

fun List<Block>.isAllowedToShowTypesWidget(
objectRestrictions: List<ObjectRestriction>,
isOwnerOrEditor: Boolean,
objectLayout: Int?
): Boolean {
if (objectRestrictions.any { it == ObjectRestriction.TYPE_CHANGE }) return false
if (!isOwnerOrEditor) return false
return if (objectLayout == ObjectType.Layout.NOTE.code) {
return true
} else {
return title()?.content<Content.Text>()?.text?.isEmpty() == true
}
}

Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package com.anytypeio.anytype.presentation.editor.editor

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import app.cash.turbine.test
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.StubHeader
import com.anytypeio.anytype.core_models.StubObjectType
import com.anytypeio.anytype.core_models.StubSmartBlock
import com.anytypeio.anytype.core_models.StubTitle
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -231,4 +235,103 @@ class EditorInternalFlagsTest : EditorPresentationTestSetup() {

coroutineTestRule.advanceTime(100)
}

@Test
fun `should doesn't show type widget when flag is present and title is not empty`() = runTest {
val title = StubTitle(text = "Some text")
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id))
val document = listOf(page, header, title)
stubInterceptEvents()

val detailsList = Block.Details(
details = mapOf(
root to Block.Fields(
mapOf(
Relations.TYPE to ObjectTypeIds.PAGE,
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
Relations.INTERNAL_FLAGS to listOf(
InternalFlags.ShouldSelectType.code.toDouble(),
)
)
)
)
)
stubOpenDocument(document = document, details = detailsList)
stubGetObjectTypes(types = emptyList())
stubGetDefaultObjectType()
stubFileLimitEvents()
stubSetInternalFlags()

val vm = buildViewModel()
advanceUntilIdle()

vm.typesWidgetState.test{
val first = awaitItem()
assertEquals(EditorViewModel.TypesWidgetState(
items = emptyList(),
visible = false,
expanded = false
), first)
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
ensureAllEventsConsumed()
}
}

@Test
fun `should show type widget when flag is present and title is empty`() = runTest {
val title = StubTitle(text = "")
val header = StubHeader(children = listOf(title.id))
val page = StubSmartBlock(id = root, children = listOf(header.id))
val document = listOf(page, header, title)
stubInterceptEvents()

val detailsList = Block.Details(
details = mapOf(
root to Block.Fields(
mapOf(
Relations.TYPE to ObjectTypeIds.PAGE,
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
Relations.INTERNAL_FLAGS to listOf(
InternalFlags.ShouldSelectType.code.toDouble(),
)
)
)
)
)
stubOpenDocument(document = document, details = detailsList)
stubGetObjectTypes(types = emptyList())
stubGetDefaultObjectType()
stubFileLimitEvents()
stubSetInternalFlags()
stubGetObjectTypes(listOf(StubObjectType(id = ObjectTypeIds.PAGE)))

val vm = buildViewModel()
advanceUntilIdle()

vm.typesWidgetState.test{
val first = awaitItem()
assertEquals(EditorViewModel.TypesWidgetState(
items = listOf(),
visible = false,
expanded = false
), first)
vm.onStart(id = root, space = defaultSpace)
advanceUntilIdle()
val second = awaitItem()
assertEquals(EditorViewModel.TypesWidgetState(
items = listOf(),
visible = true,
expanded = false
), second)
val third = awaitItem()
assertEquals(EditorViewModel.TypesWidgetState(
items = listOf(EditorViewModel.TypesWidgetItem.Search),
visible = true,
expanded = false
), third)
ensureAllEventsConsumed()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ class EditorObjectTypeChangeWidgetTest : EditorPresentationTestSetup() {
)
)

val title = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = "",
marks = emptyList(),
style = Block.Content.Text.Style.TITLE
)
)

val featuredBlock = Block(
id = "featuredRelations",
fields = Block.Fields.empty(),
Expand All @@ -76,17 +87,17 @@ class EditorObjectTypeChangeWidgetTest : EditorPresentationTestSetup() {
type = Block.Content.Layout.Type.HEADER
),
fields = Block.Fields.empty(),
children = listOf(featuredBlock.id)
children = listOf(title.id, featuredBlock.id)
)

val page = Block(
id = root,
fields = Block.Fields(emptyMap()),
content = Block.Content.Smart,
children = listOf(header.id, paragraph.id)
children = listOf(header.id, title.id, paragraph.id)
)

val doc = listOf(page, header, paragraph, featuredBlock)
val doc = listOf(page, header, title, paragraph, featuredBlock)

val objectDetails = Block.Fields(
mapOf(
Expand Down

0 comments on commit b0c79c5

Please sign in to comment.