mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2797 Date as an object | Support relative dates setting as default mentions (#1898)
This commit is contained in:
parent
8d3854072b
commit
a03f37129b
16 changed files with 796 additions and 47 deletions
|
@ -114,6 +114,7 @@ import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
|||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DocumentFileShareDownloader
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
@ -298,6 +299,9 @@ open class EditorTestSetup {
|
|||
@Mock
|
||||
lateinit var fieldParser: FieldParser
|
||||
|
||||
@Mock
|
||||
lateinit var resourceProvider: ResourceProvider
|
||||
|
||||
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
|
||||
|
||||
lateinit var addRelationToObject: AddRelationToObject
|
||||
|
@ -415,7 +419,8 @@ open class EditorTestSetup {
|
|||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
),
|
||||
orchestrator = Orchestrator(
|
||||
createBlock = createBlock,
|
||||
|
|
|
@ -131,6 +131,7 @@ import com.anytypeio.anytype.presentation.util.Dispatcher
|
|||
import com.anytypeio.anytype.presentation.util.downloader.DebugTreeShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DocumentFileShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.providers.DefaultCoverImageHashProvider
|
||||
import com.anytypeio.anytype.ui.editor.EditorFragment
|
||||
import dagger.BindsInstance
|
||||
|
@ -380,14 +381,16 @@ object EditorSessionModule {
|
|||
coverImageHashProvider: CoverImageHashProvider,
|
||||
storeOfRelations: StoreOfRelations,
|
||||
storeOfObjectTypes: StoreOfObjectTypes,
|
||||
fieldParser: FieldParser
|
||||
fieldParser: FieldParser,
|
||||
resourceProvider: ResourceProvider
|
||||
): DefaultBlockViewRenderer = DefaultBlockViewRenderer(
|
||||
urlBuilder = urlBuilder,
|
||||
toggleStateHolder = toggleStateHolder,
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
|
|||
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.templates.TemplateBlankViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.providers.DefaultCoverImageHashProvider
|
||||
import com.anytypeio.anytype.ui.templates.TemplateBlankFragment
|
||||
import dagger.Binds
|
||||
|
@ -73,6 +74,7 @@ interface TemplateBlankDependencies : ComponentDependencies {
|
|||
fun storeOfObjectTypes(): StoreOfObjectTypes
|
||||
fun dateProvider(): DateProvider
|
||||
fun fieldsProvider(): FieldParser
|
||||
fun resourceProvider(): ResourceProvider
|
||||
}
|
||||
|
||||
@Scope
|
||||
|
|
|
@ -33,6 +33,8 @@ import com.anytypeio.anytype.middleware.interactor.ProtobufConverterProvider
|
|||
import com.anytypeio.anytype.other.BasicLogger
|
||||
import com.anytypeio.anytype.other.DefaultDateTypeNameProvider
|
||||
import com.anytypeio.anytype.other.DefaultDebugConfig
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProviderImpl
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
@ -89,6 +91,12 @@ object UtilModule {
|
|||
getDateObjectByTimestamp: GetDateObjectByTimestamp
|
||||
): FieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideResourceProvider(context: Context): ResourceProvider =
|
||||
ResourceProviderImpl(context)
|
||||
|
||||
@Module
|
||||
interface Bindings {
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.anytypeio.anytype.domain.workspace.SpaceManager
|
|||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.CollectionViewModel
|
||||
import com.anytypeio.anytype.ui.settings.RemoteFilesManageFragment
|
||||
import dagger.Binds
|
||||
|
@ -209,4 +210,5 @@ interface CollectionDependencies : ComponentDependencies {
|
|||
fun analyticsHelperDelegate(): AnalyticSpaceHelperDelegate
|
||||
fun provideUserPermissionProvider(): UserPermissionProvider
|
||||
fun fieldParser(): FieldParser
|
||||
fun resourceProvider(): ResourceProvider
|
||||
}
|
|
@ -58,6 +58,13 @@ data class Block(
|
|||
else -> null
|
||||
}
|
||||
|
||||
val timestamp: Double?
|
||||
get() = when (val value = map[Relations.TIMESTAMP]) {
|
||||
is Double -> value
|
||||
is Int -> value.toDouble()
|
||||
else -> null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun empty(): Fields = Fields(emptyMap())
|
||||
const val NAME_KEY = "name"
|
||||
|
|
|
@ -17,6 +17,7 @@ android {
|
|||
buildConfigField "boolean", "ENABLE_LINK_APPERANCE_MENU", "true"
|
||||
buildConfigField "boolean", "USE_SIMPLE_TABLES_IN_EDITOR_EDDITING", "true"
|
||||
buildConfigField "boolean", "ENABLE_VIEWS_MENU", "true"
|
||||
buildConfigField "boolean", "ENABLE_RELATIVE_DATES_IN_MENTIONS", "true"
|
||||
}
|
||||
namespace 'com.anytypeio.anytype.presentation'
|
||||
|
||||
|
|
|
@ -4,23 +4,23 @@ import com.anytypeio.anytype.core_models.Block
|
|||
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.Relations
|
||||
import com.anytypeio.anytype.core_models.ext.replaceRangeWithWord
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup.Companion.NON_EXISTENT_OBJECT_MENTION_NAME
|
||||
import com.anytypeio.anytype.presentation.extension.shift
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import timber.log.Timber
|
||||
|
||||
fun Block.Content.Text.getTextAndMarks(
|
||||
details: Block.Details,
|
||||
marks: List<Markup.Mark>,
|
||||
fieldParser: FieldParser
|
||||
fieldParser: FieldParser,
|
||||
resourceProvider: ResourceProvider
|
||||
): Pair<String, List<Markup.Mark>> {
|
||||
if (details.details.isEmpty() ||
|
||||
marks.none { it is Markup.Mark.Mention }
|
||||
) {
|
||||
return Pair(text, marks)
|
||||
|
||||
if (details.details.isEmpty() || marks.none { it is Markup.Mark.Mention }) {
|
||||
return text to marks
|
||||
}
|
||||
var updatedText = text
|
||||
val updatedMarks = marks.toMutableList()
|
||||
|
@ -28,31 +28,54 @@ fun Block.Content.Text.getTextAndMarks(
|
|||
try {
|
||||
updatedMarks.forEach { mark ->
|
||||
if (mark !is Markup.Mark.Mention || mark.param.isBlank()) return@forEach
|
||||
var newName = if (mark is Markup.Mark.Mention.Deleted) {
|
||||
NON_EXISTENT_OBJECT_MENTION_NAME
|
||||
} else {
|
||||
details.details.getProperObjectName(id = mark.param) ?: return@forEach
|
||||
val newName = when (mark) {
|
||||
is Markup.Mark.Mention.Date -> getFormattedDateMention(
|
||||
mark = mark,
|
||||
details = details,
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
is Markup.Mark.Mention.Deleted -> resourceProvider.getNonExistentObjectTitle()
|
||||
else -> details.details.getProperObjectName(id = mark.param) ?: return@forEach
|
||||
}
|
||||
val oldName = updatedText.substring(mark.from, mark.to)
|
||||
if (newName != oldName) {
|
||||
if (newName.isEmpty()) newName = Relations.RELATION_NAME_EMPTY
|
||||
val d = newName.length - oldName.length
|
||||
val finalName =
|
||||
if (newName.isNullOrBlank()) resourceProvider.getUntitledTitle() else newName
|
||||
|
||||
if (finalName != oldName) {
|
||||
val lengthDifference = finalName.length - oldName.length
|
||||
updatedText = updatedText.replaceRangeWithWord(
|
||||
replace = newName,
|
||||
replace = finalName,
|
||||
from = mark.from,
|
||||
to = mark.to
|
||||
)
|
||||
updatedMarks.shift(
|
||||
start = mark.from,
|
||||
length = d
|
||||
length = lengthDifference
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while update mention markups")
|
||||
return Pair(text, marks)
|
||||
return text to marks
|
||||
}
|
||||
return updatedText to updatedMarks
|
||||
}
|
||||
|
||||
private fun Block.Content.Text.getFormattedDateMention(
|
||||
mark: Markup.Mark.Mention.Date,
|
||||
details: Block.Details,
|
||||
fieldParser: FieldParser,
|
||||
resourceProvider: ResourceProvider
|
||||
): String? {
|
||||
return if (BuildConfig.ENABLE_RELATIVE_DATES_IN_MENTIONS) {
|
||||
val dateObject = details.details[mark.param] ?: return null
|
||||
val timestamp = dateObject.timestamp ?: return null
|
||||
val relativeDate = fieldParser.toDate(timestamp)?.relativeDate
|
||||
resourceProvider.toFormattedString(relativeDate = relativeDate).takeIf { it.isNotEmpty() }
|
||||
} else {
|
||||
details.details[mark.param]?.name
|
||||
}
|
||||
return Pair(updatedText, updatedMarks)
|
||||
}
|
||||
|
||||
private fun Map<Id, Block.Fields>.getProperObjectName(id: Id?): String? {
|
||||
|
|
|
@ -41,6 +41,7 @@ import com.anytypeio.anytype.presentation.relations.getCover
|
|||
import com.anytypeio.anytype.presentation.relations.linksFeaturedRelation
|
||||
import com.anytypeio.anytype.presentation.relations.objectTypeRelation
|
||||
import com.anytypeio.anytype.presentation.relations.view
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import javax.inject.Inject
|
||||
import timber.log.Timber
|
||||
import com.anytypeio.anytype.presentation.editor.Editor.Mode as EditorMode
|
||||
|
@ -51,7 +52,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
private val coverImageHashProvider: CoverImageHashProvider,
|
||||
private val storeOfRelations: StoreOfRelations,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val fieldParser: FieldParser
|
||||
private val fieldParser: FieldParser,
|
||||
private val resourceProvider: ResourceProvider
|
||||
) : BlockViewRenderer, ToggleStateHolder by toggleStateHolder {
|
||||
|
||||
override suspend fun Map<Id, List<Block>>.render(
|
||||
|
@ -802,7 +804,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
val isFocused = resolveIsFocused(focus, block)
|
||||
|
||||
|
@ -864,7 +867,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Header.Three(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -900,7 +904,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Header.Two(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -936,7 +941,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Header.One(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -972,7 +978,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Checkbox(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1008,7 +1015,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Bulleted(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1068,7 +1076,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
val current = listOf(
|
||||
BlockView.Decoration(
|
||||
|
@ -1111,7 +1120,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
val iconImage = content.iconImage
|
||||
val iconEmoji = content.iconEmoji
|
||||
|
@ -1165,7 +1175,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Toggle(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
@ -1203,7 +1214,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val (normalizedText, normalizedMarks) = content.getTextAndMarks(
|
||||
details = details,
|
||||
marks = marks,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
return BlockView.Text.Numbered(
|
||||
mode = if (mode == EditorMode.Edit) BlockView.Mode.EDIT else BlockView.Mode.READ,
|
||||
|
|
|
@ -95,7 +95,7 @@ class CollectionViewModel(
|
|||
private val setObjectListIsArchived: SetObjectListIsArchived,
|
||||
private val setObjectListIsFavorite: SetObjectListIsFavorite,
|
||||
private val deleteObjects: DeleteObjects,
|
||||
private val resourceProvider: CollectionResourceProvider,
|
||||
private val resourceProvider: ResourceProvider,
|
||||
private val openObject: OpenObject,
|
||||
private val createObject: CreateObject,
|
||||
interceptEvents: InterceptEvents,
|
||||
|
@ -988,7 +988,7 @@ class CollectionViewModel(
|
|||
private val setObjectListIsArchived: SetObjectListIsArchived,
|
||||
private val setObjectListIsFavorite: SetObjectListIsFavorite,
|
||||
private val deleteObjects: DeleteObjects,
|
||||
private val resourceProvider: CollectionResourceProvider,
|
||||
private val resourceProvider: ResourceProvider,
|
||||
private val openObject: OpenObject,
|
||||
private val createObject: CreateObject,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
|
|
|
@ -1,15 +1,31 @@
|
|||
package com.anytypeio.anytype.presentation.widgets.collection
|
||||
|
||||
import android.content.Context
|
||||
import com.anytypeio.anytype.core_models.RelativeDate
|
||||
import com.anytypeio.anytype.presentation.R
|
||||
import javax.inject.Inject
|
||||
|
||||
class CollectionResourceProvider @Inject constructor(
|
||||
private val context: Context
|
||||
) {
|
||||
interface ResourceProvider {
|
||||
fun actionModeName(
|
||||
actionMode: ActionMode,
|
||||
isResultEmpty: Boolean
|
||||
): String
|
||||
|
||||
fun subscriptionName(subscription: Subscription): String
|
||||
|
||||
fun toFormattedString(relativeDate: RelativeDate?): String
|
||||
|
||||
fun getNonExistentObjectTitle(): String
|
||||
|
||||
fun getUntitledTitle(): String
|
||||
}
|
||||
|
||||
class ResourceProviderImpl @Inject constructor(
|
||||
private val context: Context
|
||||
) : ResourceProvider {
|
||||
override fun actionModeName(
|
||||
actionMode: ActionMode,
|
||||
isResultEmpty: Boolean
|
||||
): String {
|
||||
return when (actionMode) {
|
||||
ActionMode.SelectAll -> {
|
||||
|
@ -18,6 +34,7 @@ class CollectionResourceProvider @Inject constructor(
|
|||
else
|
||||
context.getString(R.string.select_all)
|
||||
}
|
||||
|
||||
ActionMode.UnselectAll -> {
|
||||
if (isResultEmpty) {
|
||||
""
|
||||
|
@ -25,12 +42,13 @@ class CollectionResourceProvider @Inject constructor(
|
|||
context.getString(R.string.unselect_all)
|
||||
}
|
||||
}
|
||||
|
||||
ActionMode.Edit -> context.getString(R.string.edit)
|
||||
ActionMode.Done -> context.getString(R.string.done)
|
||||
}
|
||||
}
|
||||
|
||||
fun subscriptionName(subscription: Subscription): String {
|
||||
override fun subscriptionName(subscription: Subscription): String {
|
||||
return when (subscription) {
|
||||
Subscription.Recent -> context.getString(R.string.recent)
|
||||
Subscription.RecentLocal -> context.getString(R.string.recently_opened)
|
||||
|
@ -42,4 +60,23 @@ class CollectionResourceProvider @Inject constructor(
|
|||
Subscription.Files -> context.getString(R.string.synced_files)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toFormattedString(relativeDate: RelativeDate?): String {
|
||||
return when (relativeDate) {
|
||||
RelativeDate.Empty -> ""
|
||||
is RelativeDate.Other -> relativeDate.formattedDate
|
||||
is RelativeDate.Today -> context.getString(R.string.today)
|
||||
is RelativeDate.Tomorrow -> context.getString(R.string.tomorrow)
|
||||
is RelativeDate.Yesterday -> context.getString(R.string.yesterday)
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNonExistentObjectTitle(): String {
|
||||
return context.getString(R.string.non_existent_object)
|
||||
}
|
||||
|
||||
override fun getUntitledTitle(): String {
|
||||
return context.getString(R.string.untitled)
|
||||
}
|
||||
}
|
|
@ -3,9 +3,12 @@ package com.anytypeio.anytype.presentation.editor
|
|||
import android.util.Log
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Block.Content.Link
|
||||
import com.anytypeio.anytype.core_models.DayOfWeekCustom
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectType.Layout
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.RelativeDate
|
||||
import com.anytypeio.anytype.core_models.StubBookmark
|
||||
import com.anytypeio.anytype.core_models.StubCallout
|
||||
import com.anytypeio.anytype.core_models.StubFile
|
||||
|
@ -44,6 +47,7 @@ import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColo
|
|||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.util.TXT
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlin.test.assertEquals
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -119,6 +123,9 @@ class DefaultBlockViewRendererTest {
|
|||
@Mock
|
||||
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp
|
||||
|
||||
@Mock
|
||||
lateinit var resourceProvider: ResourceProvider
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
|
@ -129,7 +136,8 @@ class DefaultBlockViewRendererTest {
|
|||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2373,6 +2381,10 @@ class DefaultBlockViewRendererTest {
|
|||
val title = MockTypicalDocumentFactory.title
|
||||
val header = MockTypicalDocumentFactory.header
|
||||
|
||||
resourceProvider.stub {
|
||||
onBlocking { getNonExistentObjectTitle() } doReturn NON_EXISTENT_OBJECT_MENTION_NAME
|
||||
}
|
||||
|
||||
val mentionText1 = "Foobar"
|
||||
val mentionTextUpdated1 = NON_EXISTENT_OBJECT_MENTION_NAME //Non-existent object
|
||||
val mentionText2 = "Anytype"
|
||||
|
@ -5452,4 +5464,288 @@ class DefaultBlockViewRendererTest {
|
|||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Date mention
|
||||
|
||||
/**
|
||||
* ENABLE_RELATIVE_DATES_IN_MENTIONS should be enabled
|
||||
*/
|
||||
@Test
|
||||
fun `should set date mention in text and shift all markups when relative date is shorter then mention text`() {
|
||||
|
||||
val title = MockTypicalDocumentFactory.title
|
||||
val header = MockTypicalDocumentFactory.header
|
||||
|
||||
val timestamp = 1733775232L
|
||||
|
||||
val relativeDateTomorrow = "Tomorrow"
|
||||
|
||||
val relativeDate = RelativeDate.Tomorrow(
|
||||
initialTimeInMillis = timestamp,
|
||||
dayOfWeek = DayOfWeekCustom.MONDAY
|
||||
)
|
||||
|
||||
dateProvider.stub {
|
||||
onBlocking { calculateRelativeDates(dateInSeconds = timestamp) } doReturn relativeDate
|
||||
}
|
||||
|
||||
resourceProvider.stub {
|
||||
onBlocking { toFormattedString(relativeDate) } doReturn relativeDateTomorrow
|
||||
}
|
||||
|
||||
val mentionTextUpdated1 = "07-12-2024"
|
||||
val source = "Start 07-12-2024 middle"
|
||||
val sourceUpdated = "Start $relativeDateTomorrow middle"
|
||||
val textColor = "F0So"
|
||||
val mentionTarget1 = "_date_07_12_2024"
|
||||
|
||||
val marks: List<Block.Content.Text.Mark> = listOf(
|
||||
Block.Content.Text.Mark(
|
||||
range = 0..5,
|
||||
type = Block.Content.Text.Mark.Type.TEXT_COLOR,
|
||||
param = textColor
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = 6..16,
|
||||
type = Block.Content.Text.Mark.Type.MENTION,
|
||||
param = mentionTarget1
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = 17..22,
|
||||
type = Block.Content.Text.Mark.Type.BOLD
|
||||
)
|
||||
)
|
||||
|
||||
val a = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
children = listOf(),
|
||||
content = Block.Content.Text(
|
||||
text = source,
|
||||
style = Block.Content.Text.Style.P,
|
||||
marks = marks,
|
||||
align = Block.Align.AlignLeft
|
||||
),
|
||||
fields = Block.Fields.empty()
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
children = listOf(header.id, a.id),
|
||||
fields = Block.Fields.empty(),
|
||||
content = Block.Content.Smart
|
||||
)
|
||||
|
||||
val fieldsUpdated1 = Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to mentionTarget1,
|
||||
Relations.NAME to mentionTextUpdated1,
|
||||
Relations.TIMESTAMP to 1733775232,
|
||||
Relations.LAYOUT to Layout.DATE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val detailsAmend = mapOf(
|
||||
mentionTarget1 to fieldsUpdated1,
|
||||
)
|
||||
|
||||
val blocks = listOf(page, header, title, a)
|
||||
|
||||
val map = blocks.asMap()
|
||||
|
||||
wrapper = BlockViewRenderWrapper(
|
||||
blocks = map,
|
||||
renderer = renderer
|
||||
)
|
||||
|
||||
val result = runBlocking {
|
||||
wrapper.render(
|
||||
root = page,
|
||||
anchor = page.id,
|
||||
focus = Editor.Focus.id(a.id),
|
||||
indent = 0,
|
||||
details = Block.Details(detailsAmend)
|
||||
)
|
||||
}
|
||||
|
||||
val expected = listOf(
|
||||
BlockView.Title.Basic(
|
||||
id = title.id,
|
||||
isFocused = false,
|
||||
text = title.content<Block.Content.Text>().text,
|
||||
image = null,
|
||||
mode = BlockView.Mode.EDIT
|
||||
),
|
||||
BlockView.Text.Paragraph(
|
||||
id = a.id,
|
||||
text = sourceUpdated,
|
||||
marks = listOf(
|
||||
Markup.Mark.TextColor(
|
||||
from = 0,
|
||||
to = 5,
|
||||
color = textColor
|
||||
),
|
||||
Markup.Mark.Mention.Date(
|
||||
from = 6,
|
||||
to = 14,
|
||||
param = mentionTarget1
|
||||
),
|
||||
Markup.Mark.Bold(
|
||||
from = 15,
|
||||
to = 20
|
||||
)
|
||||
),
|
||||
isFocused = true,
|
||||
alignment = Alignment.START,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
background = a.parseThemeBackgroundColor()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(expected = expected, actual = result)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ENABLE_RELATIVE_DATES_IN_MENTIONS should be enabled
|
||||
*/
|
||||
@Test
|
||||
fun `should set date mention in text and shift all markups when relative date is longer then mention text`() {
|
||||
|
||||
val title = MockTypicalDocumentFactory.title
|
||||
val header = MockTypicalDocumentFactory.header
|
||||
|
||||
val timestamp = 1733775232L
|
||||
|
||||
val relativeDateTomorrow = "TomorrowTomorrowTomorrow"
|
||||
|
||||
val relativeDate = RelativeDate.Tomorrow(
|
||||
initialTimeInMillis = timestamp,
|
||||
dayOfWeek = DayOfWeekCustom.MONDAY
|
||||
)
|
||||
|
||||
dateProvider.stub {
|
||||
onBlocking { calculateRelativeDates(dateInSeconds = timestamp) } doReturn relativeDate
|
||||
}
|
||||
|
||||
resourceProvider.stub {
|
||||
onBlocking { toFormattedString(relativeDate) } doReturn relativeDateTomorrow
|
||||
}
|
||||
|
||||
val mentionTextUpdated1 = "07-12-2024"
|
||||
val source = "Start 07-12-2024 middle"
|
||||
val sourceUpdated = "Start $relativeDateTomorrow middle"
|
||||
val textColor = "F0So"
|
||||
val mentionTarget1 = "_date_07_12_2024"
|
||||
|
||||
val marks: List<Block.Content.Text.Mark> = listOf(
|
||||
Block.Content.Text.Mark(
|
||||
range = 0..5,
|
||||
type = Block.Content.Text.Mark.Type.TEXT_COLOR,
|
||||
param = textColor
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = 6..16,
|
||||
type = Block.Content.Text.Mark.Type.MENTION,
|
||||
param = mentionTarget1
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = 17..22,
|
||||
type = Block.Content.Text.Mark.Type.BOLD
|
||||
)
|
||||
)
|
||||
|
||||
val a = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
children = listOf(),
|
||||
content = Block.Content.Text(
|
||||
text = source,
|
||||
style = Block.Content.Text.Style.P,
|
||||
marks = marks,
|
||||
align = Block.Align.AlignLeft
|
||||
),
|
||||
fields = Block.Fields.empty()
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
children = listOf(header.id, a.id),
|
||||
fields = Block.Fields.empty(),
|
||||
content = Block.Content.Smart
|
||||
)
|
||||
|
||||
val fieldsUpdated1 = Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to mentionTarget1,
|
||||
Relations.NAME to mentionTextUpdated1,
|
||||
Relations.TIMESTAMP to 1733775232,
|
||||
Relations.LAYOUT to Layout.DATE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val detailsAmend = mapOf(
|
||||
mentionTarget1 to fieldsUpdated1,
|
||||
)
|
||||
|
||||
val blocks = listOf(page, header, title, a)
|
||||
|
||||
val map = blocks.asMap()
|
||||
|
||||
wrapper = BlockViewRenderWrapper(
|
||||
blocks = map,
|
||||
renderer = renderer
|
||||
)
|
||||
|
||||
val result = runBlocking {
|
||||
wrapper.render(
|
||||
root = page,
|
||||
anchor = page.id,
|
||||
focus = Editor.Focus.id(a.id),
|
||||
indent = 0,
|
||||
details = Block.Details(detailsAmend)
|
||||
)
|
||||
}
|
||||
|
||||
val expected = listOf(
|
||||
BlockView.Title.Basic(
|
||||
id = title.id,
|
||||
isFocused = false,
|
||||
text = title.content<Block.Content.Text>().text,
|
||||
image = null,
|
||||
mode = BlockView.Mode.EDIT
|
||||
),
|
||||
BlockView.Text.Paragraph(
|
||||
id = a.id,
|
||||
text = sourceUpdated,
|
||||
marks = listOf(
|
||||
Markup.Mark.TextColor(
|
||||
from = 0,
|
||||
to = 5,
|
||||
color = textColor
|
||||
),
|
||||
Markup.Mark.Mention.Date(
|
||||
from = 6,
|
||||
to = 30,
|
||||
param = mentionTarget1
|
||||
),
|
||||
Markup.Mark.Bold(
|
||||
from = 31,
|
||||
to = 36
|
||||
)
|
||||
),
|
||||
isFocused = true,
|
||||
alignment = Alignment.START,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
background = a.parseThemeBackgroundColor()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
assertEquals(expected = expected, actual = result)
|
||||
}
|
||||
//endregion
|
||||
}
|
|
@ -131,6 +131,7 @@ import com.anytypeio.anytype.presentation.util.TXT
|
|||
import com.anytypeio.anytype.presentation.util.dispatchers
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DocumentFileShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import com.jraska.livedata.test
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -373,6 +374,9 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var fieldParser: FieldParser
|
||||
|
||||
@Mock
|
||||
lateinit var resourceProvider: ResourceProvider
|
||||
|
||||
lateinit var vm: EditorViewModel
|
||||
|
||||
lateinit var orchestrator: Orchestrator
|
||||
|
@ -3942,7 +3946,8 @@ open class EditorViewModelTest {
|
|||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider,
|
||||
),
|
||||
orchestrator = orchestrator,
|
||||
analytics = analytics,
|
||||
|
|
|
@ -5,8 +5,10 @@ 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.Event
|
||||
import com.anytypeio.anytype.core_models.ObjectType.Layout
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
import com.anytypeio.anytype.domain.base.Either
|
||||
import com.anytypeio.anytype.domain.base.Result
|
||||
|
@ -972,10 +974,26 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
children = listOf(header.id, a.id)
|
||||
)
|
||||
|
||||
val fieldsUpdated1 = Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to mentionTarget,
|
||||
Relations.NAME to ""
|
||||
)
|
||||
)
|
||||
|
||||
val detailsAmend = mapOf(
|
||||
mentionTarget to fieldsUpdated1,
|
||||
)
|
||||
|
||||
val document = listOf(page, header, title, a)
|
||||
|
||||
val params = InterceptEvents.Params(context = root)
|
||||
|
||||
val untitled = "UntitledWord"
|
||||
resourceProvider.stub {
|
||||
onBlocking { getUntitledTitle() } doReturn untitled
|
||||
}
|
||||
|
||||
openPage.stub {
|
||||
onBlocking { async(any()) } doReturn Resultat.success(
|
||||
Result.Success(
|
||||
|
@ -985,7 +1003,7 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
Event.Command.ShowObject(
|
||||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(),
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
|
@ -1010,6 +1028,7 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
val actual = vm.state.value
|
||||
|
||||
val expected = ViewState.Success(
|
||||
blocks = listOf(
|
||||
BlockView.Title.Basic(
|
||||
|
@ -1030,17 +1049,17 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
),
|
||||
Markup.Mark.Mention.Base(
|
||||
from = 6,
|
||||
to = 14,
|
||||
to = 18,
|
||||
param = mentionTarget,
|
||||
isArchived = false
|
||||
),
|
||||
Markup.Mark.Strikethrough(
|
||||
from = 15,
|
||||
to = 18
|
||||
from = 19,
|
||||
to = 22
|
||||
)
|
||||
),
|
||||
indent = 0,
|
||||
text = "Start Untitled end",
|
||||
text = "Start $untitled end",
|
||||
mode = BlockView.Mode.EDIT,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
|
@ -1184,6 +1203,325 @@ class EditorMentionTest : EditorPresentationTestSetup() {
|
|||
clearPendingCoroutines()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should update mention text with details amend event when new text is blank`() {
|
||||
|
||||
val title = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.Text(
|
||||
text = MockDataFactory.randomString(),
|
||||
style = Block.Content.Text.Style.TITLE,
|
||||
marks = emptyList()
|
||||
),
|
||||
children = emptyList(),
|
||||
fields = Block.Fields.empty()
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(title.id)
|
||||
)
|
||||
|
||||
val mentionTarget = MockDataFactory.randomUuid()
|
||||
val givenText = "Start F end"
|
||||
|
||||
val a = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.Text(
|
||||
text = givenText,
|
||||
marks = listOf(
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(0, 5),
|
||||
type = Block.Content.Text.Mark.Type.BOLD
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(6, 7),
|
||||
type = Block.Content.Text.Mark.Type.MENTION,
|
||||
param = mentionTarget
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(8, 11),
|
||||
type = Block.Content.Text.Mark.Type.STRIKETHROUGH
|
||||
)
|
||||
),
|
||||
style = Block.Content.Text.Style.P
|
||||
)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart,
|
||||
children = listOf(header.id, a.id)
|
||||
)
|
||||
|
||||
val fieldsUpdated1 = Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to mentionTarget,
|
||||
Relations.NAME to " "
|
||||
)
|
||||
)
|
||||
|
||||
val detailsAmend = mapOf(
|
||||
mentionTarget to fieldsUpdated1,
|
||||
)
|
||||
|
||||
val document = listOf(page, header, title, a)
|
||||
|
||||
val params = InterceptEvents.Params(context = root)
|
||||
|
||||
val untitled = "UntitledWord"
|
||||
resourceProvider.stub {
|
||||
onBlocking { getUntitledTitle() } doReturn untitled
|
||||
}
|
||||
|
||||
openPage.stub {
|
||||
onBlocking { async(any()) } doReturn Resultat.success(
|
||||
Result.Success(
|
||||
Payload(
|
||||
context = root,
|
||||
events = listOf(
|
||||
Event.Command.ShowObject(
|
||||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
Event.Command.Details.Amend(
|
||||
context = root,
|
||||
target = mentionTarget,
|
||||
details = mapOf(Block.Fields.NAME_KEY to "")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
stubInterceptEvents()
|
||||
stubSearchObjects()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
verifyNoInteractions(interceptEvents)
|
||||
|
||||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
val actual = vm.state.value
|
||||
|
||||
val expected = ViewState.Success(
|
||||
blocks = listOf(
|
||||
BlockView.Title.Basic(
|
||||
id = title.id,
|
||||
isFocused = false,
|
||||
text = title.content<TXT>().text,
|
||||
mode = BlockView.Mode.EDIT
|
||||
),
|
||||
BlockView.Text.Paragraph(
|
||||
id = a.id,
|
||||
cursor = null,
|
||||
isSelected = false,
|
||||
isFocused = false,
|
||||
marks = listOf(
|
||||
Markup.Mark.Bold(
|
||||
from = 0,
|
||||
to = 5
|
||||
),
|
||||
Markup.Mark.Mention.Base(
|
||||
from = 6,
|
||||
to = 18,
|
||||
param = mentionTarget,
|
||||
isArchived = false
|
||||
),
|
||||
Markup.Mark.Strikethrough(
|
||||
from = 19,
|
||||
to = 22
|
||||
)
|
||||
),
|
||||
indent = 0,
|
||||
text = "Start $untitled end",
|
||||
mode = BlockView.Mode.EDIT,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
background = a.parseThemeBackgroundColor()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
verify(interceptEvents, times(1)).build(params = params)
|
||||
|
||||
assertEquals(expected = expected, actual = actual)
|
||||
clearPendingCoroutines()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should update mention text with details amend event when new text is null`() {
|
||||
|
||||
val title = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.Text(
|
||||
text = MockDataFactory.randomString(),
|
||||
style = Block.Content.Text.Style.TITLE,
|
||||
marks = emptyList()
|
||||
),
|
||||
children = emptyList(),
|
||||
fields = Block.Fields.empty()
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(title.id)
|
||||
)
|
||||
|
||||
val mentionTarget = MockDataFactory.randomUuid()
|
||||
val givenText = "Start F end"
|
||||
|
||||
val a = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.Text(
|
||||
text = givenText,
|
||||
marks = listOf(
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(0, 5),
|
||||
type = Block.Content.Text.Mark.Type.BOLD
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(6, 7),
|
||||
type = Block.Content.Text.Mark.Type.MENTION,
|
||||
param = mentionTarget
|
||||
),
|
||||
Block.Content.Text.Mark(
|
||||
range = IntRange(8, 11),
|
||||
type = Block.Content.Text.Mark.Type.STRIKETHROUGH
|
||||
)
|
||||
),
|
||||
style = Block.Content.Text.Style.P
|
||||
)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart,
|
||||
children = listOf(header.id, a.id)
|
||||
)
|
||||
|
||||
val fieldsUpdated1 = Block.Fields(
|
||||
mapOf(
|
||||
Relations.ID to mentionTarget
|
||||
)
|
||||
)
|
||||
|
||||
val detailsAmend = mapOf(
|
||||
mentionTarget to fieldsUpdated1,
|
||||
)
|
||||
|
||||
val document = listOf(page, header, title, a)
|
||||
|
||||
val params = InterceptEvents.Params(context = root)
|
||||
|
||||
val untitled = "UntitledWord"
|
||||
resourceProvider.stub {
|
||||
onBlocking { getUntitledTitle() } doReturn untitled
|
||||
}
|
||||
|
||||
openPage.stub {
|
||||
onBlocking { async(any()) } doReturn Resultat.success(
|
||||
Result.Success(
|
||||
Payload(
|
||||
context = root,
|
||||
events = listOf(
|
||||
Event.Command.ShowObject(
|
||||
context = root,
|
||||
root = root,
|
||||
details = Block.Details(detailsAmend),
|
||||
relations = emptyList(),
|
||||
blocks = document,
|
||||
objectRestrictions = emptyList()
|
||||
),
|
||||
Event.Command.Details.Amend(
|
||||
context = root,
|
||||
target = mentionTarget,
|
||||
details = mapOf(Block.Fields.NAME_KEY to "")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
stubInterceptEvents()
|
||||
stubSearchObjects()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
verifyNoInteractions(interceptEvents)
|
||||
|
||||
vm.onStart(id = root, space = defaultSpace)
|
||||
|
||||
val actual = vm.state.value
|
||||
|
||||
val expected = ViewState.Success(
|
||||
blocks = listOf(
|
||||
BlockView.Title.Basic(
|
||||
id = title.id,
|
||||
isFocused = false,
|
||||
text = title.content<TXT>().text,
|
||||
mode = BlockView.Mode.EDIT
|
||||
),
|
||||
BlockView.Text.Paragraph(
|
||||
id = a.id,
|
||||
cursor = null,
|
||||
isSelected = false,
|
||||
isFocused = false,
|
||||
marks = listOf(
|
||||
Markup.Mark.Bold(
|
||||
from = 0,
|
||||
to = 5
|
||||
),
|
||||
Markup.Mark.Mention.Base(
|
||||
from = 6,
|
||||
to = 18,
|
||||
param = mentionTarget,
|
||||
isArchived = false
|
||||
),
|
||||
Markup.Mark.Strikethrough(
|
||||
from = 19,
|
||||
to = 22
|
||||
)
|
||||
),
|
||||
indent = 0,
|
||||
text = "Start $untitled end",
|
||||
mode = BlockView.Mode.EDIT,
|
||||
decorations = listOf(
|
||||
BlockView.Decoration(
|
||||
background = a.parseThemeBackgroundColor()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
verify(interceptEvents, times(1)).build(params = params)
|
||||
|
||||
assertEquals(expected = expected, actual = actual)
|
||||
clearPendingCoroutines()
|
||||
}
|
||||
|
||||
private fun clearPendingCoroutines() {
|
||||
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
|||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.dispatchers
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DocumentFileShareDownloader
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
@ -231,6 +232,9 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var setupBookmark: SetupBookmark
|
||||
|
||||
@Mock
|
||||
lateinit var resourceProvider: ResourceProvider
|
||||
|
||||
@Mock
|
||||
lateinit var createBookmarkBlock: CreateBookmarkBlock
|
||||
|
||||
|
@ -477,7 +481,8 @@ open class EditorPresentationTestSetup {
|
|||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
),
|
||||
orchestrator = orchestrator,
|
||||
analytics = analytics,
|
||||
|
|
|
@ -30,6 +30,7 @@ import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
|||
import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColor
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.util.TXT
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
|
||||
import kotlin.test.assertEquals
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.lachlanmckee.timberjunit.TimberTestRule
|
||||
|
@ -90,6 +91,9 @@ class TableBlockRendererTest {
|
|||
|
||||
private val storeOfObjectTypes = DefaultStoreOfObjectTypes()
|
||||
|
||||
@Mock
|
||||
lateinit var resourceProvider: ResourceProvider
|
||||
|
||||
@Mock
|
||||
lateinit var fieldParser: FieldParser
|
||||
|
||||
|
@ -102,7 +106,8 @@ class TableBlockRendererTest {
|
|||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
resourceProvider = resourceProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue