Skip to content

Commit

Permalink
DROID-2797 Date as an object | Support relative dates setting as defa…
Browse files Browse the repository at this point in the history
…ult in object lists (#1908)
  • Loading branch information
konstantiniiv authored Dec 11, 2024
1 parent 7acda60 commit da83051
Show file tree
Hide file tree
Showing 18 changed files with 171 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
Expand Down Expand Up @@ -122,6 +123,9 @@ class ObjectRelationListTest {
@Mock
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp

@Mock
lateinit var stringResourceProvider: StringResourceProvider

@Before
fun setup() {
MockitoAnnotations.openMocks(this)
Expand All @@ -130,7 +134,8 @@ class ObjectRelationListTest {
fieldParser = FieldParserImpl(
logger = logger,
dateProvider = dateProvider,
getDateObjectByTimestamp = getDateObjectByTimestamp
getDateObjectByTimestamp = getDateObjectByTimestamp,
stringResourceProvider = stringResourceProvider
)
addToFeaturedRelations = AddToFeaturedRelations(repo)
removeFromFeaturedRelations = RemoveFromFeaturedRelations(repo)
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/com/anytypeio/anytype/di/main/UtilModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.preference.PreferenceManager
import com.anytypeio.anytype.BuildConfig
import com.anytypeio.anytype.app.DefaultFeatureToggles
import com.anytypeio.anytype.app.TogglePrefs
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.core_utils.tools.AppInfo
import com.anytypeio.anytype.core_utils.tools.DefaultAppInfo
import com.anytypeio.anytype.core_utils.tools.DefaultThreadInfo
Expand All @@ -28,11 +27,13 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.middleware.interactor.MiddlewareProtobufLogger
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.util.StringResourceProviderImpl
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProvider
import com.anytypeio.anytype.presentation.widgets.collection.ResourceProviderImpl
import dagger.Binds
Expand Down Expand Up @@ -88,15 +89,22 @@ object UtilModule {
fun provideFieldsProvider(
dateProvider: DateProvider,
logger: Logger,
getDateObjectByTimestamp: GetDateObjectByTimestamp
): FieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp)
getDateObjectByTimestamp: GetDateObjectByTimestamp,
stringResourceProvider: StringResourceProvider
): FieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp, stringResourceProvider)

@JvmStatic
@Provides
@Singleton
fun provideResourceProvider(context: Context): ResourceProvider =
ResourceProviderImpl(context)

@JvmStatic
@Provides
@Singleton
fun provideStringResourceProvider(context: Context): StringResourceProvider =
StringResourceProviderImpl(context)

@Module
interface Bindings {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@ import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.extensions.isKeyboardVisible
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.di.feature.discussions.DiscussionFragment
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
import com.anytypeio.anytype.presentation.search.GlobalSearchViewModel
import com.anytypeio.anytype.ui.date.DateObjectFragment
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber

class GlobalSearchFragment : BaseBottomSheetComposeFragment() {

Expand Down Expand Up @@ -98,6 +101,25 @@ class GlobalSearchFragment : BaseBottomSheetComposeFragment() {
)
)
}
OpenObjectNavigation.NonValidObject -> {
toast(getString(R.string.error_non_valid_object))
}
is OpenObjectNavigation.OpenDataObject -> {
runCatching {
findNavController().navigate(
R.id.dateObjectScreen,
DateObjectFragment.args(
objectId = nav.target,
space = nav.space
)
)
}.onFailure {
Timber.e(it, "Failed to navigate to date object screen")
}
}
is OpenObjectNavigation.UnexpectedLayoutError -> {
toast(getString(R.string.error_unexpected_layout))
}
else -> {
// Do nothing.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ fun EmptyWidgetPlaceholderWithCreateButton(
fun WidgetView.Name.getPrettyName(): String {
return when (this) {
is WidgetView.Name.Bundled -> stringResource(id = source.res())
is WidgetView.Name.Date -> relativeDate.getPrettyName()
is WidgetView.Name.Default -> prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,18 @@ import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.debugging.Logger
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import javax.inject.Inject
import kotlin.collections.contains

interface FieldParser {
fun toDate(any: Any?): Field.Date?
fun calculateRelativeDate(timeStampInSeconds: TimeInSeconds): RelativeDate
suspend fun getDateObjectByTimeInSeconds(
timeInSeconds: TimeInSeconds,
spaceId: SpaceId,
actionSuccess: suspend (ObjectWrapper.Basic) -> Unit,
actionFailure: suspend (Throwable) -> Unit
)

fun getObjectName(objectWrapper: ObjectWrapper.Basic): String
fun getObjectTypeIdAndName(
objectWrapper: ObjectWrapper.Basic,
Expand All @@ -41,7 +40,8 @@ interface FieldParser {
class FieldParserImpl @Inject constructor(
private val dateProvider: DateProvider,
private val logger: Logger,
private val getDateObjectByTimestamp: GetDateObjectByTimestamp
private val getDateObjectByTimestamp: GetDateObjectByTimestamp,
private val stringResourceProvider: StringResourceProvider
) : FieldParser {

//region Date field
Expand Down Expand Up @@ -107,17 +107,41 @@ class FieldParserImpl @Inject constructor(
)
)
}

override fun calculateRelativeDate(timeStampInSeconds: TimeInSeconds): RelativeDate {
return dateProvider.calculateRelativeDates(
dateInSeconds = timeStampInSeconds
)
}
//endregion

//region ObjectWrapper.Basic fields
override fun getObjectName(objectWrapper: ObjectWrapper.Basic): String {
return objectWrapper.getProperObjectName().orEmpty()
val result = when (objectWrapper.layout) {
ObjectType.Layout.DATE -> {
val relativeDate = dateProvider.calculateRelativeDates(
dateInSeconds = objectWrapper.getSingleValue<Double>(Relations.TIMESTAMP)?.toLong()
)
stringResourceProvider.getRelativeDateName(relativeDate)
}
ObjectType.Layout.NOTE -> {
objectWrapper.snippet?.replace("\n", " ")?.take(MAX_SNIPPET_SIZE)
}
in SupportedLayouts.fileLayouts -> {
val fileName = if (objectWrapper.name.isNullOrBlank()) {
stringResourceProvider.getUntitledObjectTitle()
} else {
objectWrapper.name
}
when {
objectWrapper.fileExt.isNullOrBlank() -> fileName
fileName?.endsWith(".${objectWrapper.fileExt}") == true -> fileName
else -> "$fileName.${objectWrapper.fileExt}"
}
}
else -> {
objectWrapper.name
}
}
return if (result.isNullOrBlank()) {
stringResourceProvider.getUntitledObjectTitle()
} else {
result
}
}

override fun getObjectTypeIdAndName(
Expand All @@ -135,46 +159,5 @@ class FieldParserImpl @Inject constructor(
null to null
}
}

private fun ObjectWrapper.Basic.getProperObjectName(): String? {
return when (layout) {
ObjectType.Layout.DATE -> {
getProperDateName()
}

ObjectType.Layout.NOTE -> {
snippet?.replace("\n", " ")?.take(MAX_SNIPPET_SIZE)
}

in SupportedLayouts.fileLayouts -> {
val fileName = if (name.isNullOrBlank()) "Untitled" else name.orEmpty()
if (fileExt.isNullOrBlank()) {
fileName
} else {
if (fileName.endsWith(".$fileExt")) {
fileName
} else {
"$fileName.$fileExt"
}
}
}

else -> {
name
}
}
}

private fun ObjectWrapper.Basic.getProperDateName(): String {
val timestampInSeconds = getSingleValue<Double>(Relations.TIMESTAMP)?.toLong()
if (timestampInSeconds != null) {
val (formattedDate, _) = dateProvider.formatTimestampToDateAndTime(
timestamp = timestampInSeconds * 1000,
)
return formattedDate
} else {
return ""
}
}
//endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.anytypeio.anytype.domain.resources

import com.anytypeio.anytype.core_models.RelativeDate

interface StringResourceProvider {
fun getRelativeDateName(relativeDate: RelativeDate): String
fun getDeletedObjectTitle(): String
fun getUntitledObjectTitle(): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,12 @@ fun ObjectType.Layout.navigation(
space = space
)
}
ObjectType.Layout.DATE -> {
OpenObjectNavigation.OpenDataObject(
target = target,
space = space
)
}
else -> {
OpenObjectNavigation.UnexpectedLayoutError(this)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.anytypeio.anytype.presentation.util

import android.content.Context
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.presentation.R
import javax.inject.Inject

class StringResourceProviderImpl @Inject constructor(private val context: Context) :
StringResourceProvider {

override fun getRelativeDateName(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 getDeletedObjectTitle(): String {
return context.getString(R.string.non_existent_object)
}

override fun getUntitledObjectTitle(): String {
return context.getString(R.string.untitled)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,8 @@ fun buildWidgetName(
obj: ObjectWrapper.Basic,
fieldParser: FieldParser
): Name {
return if (obj.layout == ObjectType.Layout.DATE) {
val timestamp = obj.getSingleValue<Double>(Relations.TIMESTAMP)?.toLong()
if (timestamp != null) {
Name.Date(
relativeDate = fieldParser.calculateRelativeDate(timeStampInSeconds = timestamp)
)
} else {
createDefaultName(obj, fieldParser)
}
} else {
createDefaultName(obj, fieldParser)
}
val prettyPrintName = fieldParser.getObjectName(obj)
return Name.Default(prettyPrintName = prettyPrintName)
}

private fun createDefaultName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ sealed class WidgetView {
sealed interface Name {
data class Bundled(val source: Widget.Source.Bundled): Name
data class Default(val prettyPrintName: String): Name
data class Date(val relativeDate: RelativeDate): Name
}

interface Element {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.emojifier.data.DefaultDocumentEmojiIconProvider
import com.anytypeio.anytype.presentation.MockBlockContentFactory.StubLinkContent
import com.anytypeio.anytype.presentation.MockBlockFactory.link
Expand Down Expand Up @@ -126,10 +127,13 @@ class DefaultBlockViewRendererTest {
@Mock
lateinit var resourceProvider: ResourceProvider

@Mock
lateinit var stringResourceProvider: StringResourceProvider

@Before
fun setup() {
MockitoAnnotations.openMocks(this)
fieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp)
fieldParser = FieldParserImpl(dateProvider, logger, getDateObjectByTimestamp, stringResourceProvider)
renderer = DefaultBlockViewRenderer(
urlBuilder = UrlBuilder(gateway),
toggleStateHolder = toggleStateHolder,
Expand Down
Loading

0 comments on commit da83051

Please sign in to comment.