1
0
Fork 0
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 in widgets (#1901)

This commit is contained in:
Konstantin Ivanov 2024-12-10 20:19:19 +01:00 committed by konstantiniiv
parent d5a51d58f5
commit d04c4c62d2
11 changed files with 109 additions and 44 deletions

View file

@ -102,14 +102,7 @@ fun DataViewListWidgetCard(
.padding(horizontal = 0.dp, vertical = 6.dp)
) {
WidgetHeader(
title = when (val name = item.name) {
is WidgetView.Name.Default -> {
name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) }
}
is WidgetView.Name.Bundled -> {
stringResource(id = name.source.res())
}
},
title = item.getPrettyName(),
isCardMenuExpanded = isCardMenuExpanded,
isHeaderMenuExpanded = isHeaderMenuExpanded,
onWidgetHeaderClicked = {
@ -235,14 +228,7 @@ fun GalleryWidgetCard(
.padding(horizontal = 0.dp, vertical = 6.dp)
) {
WidgetHeader(
title = when (val source = item.name) {
is WidgetView.Name.Default -> {
source.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) }
}
is WidgetView.Name.Bundled -> {
stringResource(id = source.source.res())
}
},
title = item.getPrettyName(),
isCardMenuExpanded = isCardMenuExpanded,
isHeaderMenuExpanded = isHeaderMenuExpanded,
onWidgetHeaderClicked = {
@ -545,7 +531,7 @@ private fun GalleryWidgetItemCard(
onTaskIconClicked = {}
)
Text(
text = item.name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) },
text = item.getPrettyName(),
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = Caption1Medium,
@ -561,7 +547,7 @@ private fun GalleryWidgetItemCard(
}
} else {
Text(
text = item.name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) },
text = item.getPrettyName(),
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = Caption1Medium,

View file

@ -24,7 +24,6 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
@ -90,12 +89,7 @@ fun LinkWidgetCard(
) {
Text(
text = when(val name = item.name) {
is WidgetView.Name.Bundled -> stringResource(id = name.source.res())
is WidgetView.Name.Default -> {
name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) }
}
},
text = item.getPrettyName(),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier

View file

@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.PreviewTitle2Medium
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
@ -169,7 +170,7 @@ fun CompactListWidgetList(
}
)
Text(
text = element.name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) },
text = element.getPrettyName(),
modifier = Modifier
.padding(start = 8.dp)
.fillMaxWidth(),

View file

@ -101,12 +101,7 @@ fun TreeWidgetCard(
)
) {
WidgetHeader(
title = when (val name = item.name) {
is WidgetView.Name.Default -> {
name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) }
}
is WidgetView.Name.Bundled -> { stringResource(id = name.source.res()) }
},
title = item.getPrettyName(),
isCardMenuExpanded = isCardMenuExpanded,
isHeaderMenuExpanded = isHeaderMenuExpanded,
onWidgetHeaderClicked = { onWidgetSourceClicked(item.source) },
@ -227,7 +222,7 @@ private fun TreeWidgetTreeItems(
)
}
Text(
text = element.name.prettyPrintName.ifEmpty { stringResource(id = R.string.untitled) },
text = element.getPrettyName(),
modifier = Modifier
.padding(start = 8.dp)
.fillMaxWidth(),

View file

@ -18,9 +18,12 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.views.ButtonSecondary
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.Relations2
import com.anytypeio.anytype.presentation.widgets.WidgetView
import kotlin.text.ifEmpty
@Composable
fun EmptyWidgetPlaceholder(
@ -72,6 +75,50 @@ fun EmptyWidgetPlaceholderWithCreateButton(
}
}
@Composable
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) }
}
}
@Composable
fun WidgetView.Element.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.Link.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.Tree.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.SetOfObjects.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.SetOfObjects.Element.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.Gallery.getPrettyName(): String {
return name.getPrettyName()
}
@Composable
fun WidgetView.Tree.Element.getPrettyName(): String {
return name.getPrettyName()
}
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Light Mode")
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Dark Mode")
@Composable

View file

@ -23,6 +23,7 @@ import kotlin.collections.contains
interface FieldParser {
fun toDate(any: Any?): Field.Date?
fun calculateRelativeDate(timeStampInSeconds: TimeInSeconds): RelativeDate
suspend fun getDateObjectByTimeInSeconds(
timeInSeconds: TimeInSeconds,
spaceId: SpaceId,
@ -106,6 +107,12 @@ class FieldParserImpl @Inject constructor(
)
)
}
override fun calculateRelativeDate(timeStampInSeconds: TimeInSeconds): RelativeDate {
return dateProvider.calculateRelativeDates(
dateInSeconds = timeStampInSeconds
)
}
//endregion
//region ObjectWrapper.Basic fields

View file

@ -14,8 +14,9 @@ class LinkWidgetContainer(
source = widget.source,
name = when(val source = widget.source) {
is Widget.Source.Bundled -> WidgetView.Name.Bundled(source = source)
is Widget.Source.Default -> WidgetView.Name.Default(
prettyPrintName = fieldParser.getObjectName(source.obj)
is Widget.Source.Default -> buildWidgetName(
obj = source.obj,
fieldParser = fieldParser
)
}
)

View file

@ -160,9 +160,10 @@ class ListWidgetContainer(
objectIcon = obj.objectIcon(
builder = urlBuilder
),
name = WidgetView.Name.Default(
prettyPrintName = fieldParser.getObjectName(obj)
)
name = buildWidgetName(
obj = obj,
fieldParser = fieldParser
),
)
},
isExpanded = true,

View file

@ -285,8 +285,9 @@ class TreeWidgetContainer(
),
indent = level,
path = path + link,
name = WidgetView.Name.Default(
prettyPrintName = fieldParser.getObjectName(obj)
name = buildWidgetName(
obj = obj,
fieldParser = fieldParser
)
)
)

View file

@ -3,11 +3,14 @@ package com.anytypeio.anytype.presentation.widgets
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Config
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.Relations
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.ext.asMap
import com.anytypeio.anytype.core_models.SupportedLayouts.isSupportedForWidgets
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.widgets.WidgetView.Name
sealed class Widget {
@ -212,6 +215,33 @@ fun Id.bundled() : Widget.Source.Bundled = when (this) {
else -> throw IllegalStateException("Widget bundled id can't be $this")
}
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)
}
}
private fun createDefaultName(
obj: ObjectWrapper.Basic,
fieldParser: FieldParser
): Name.Default {
return Name.Default(
prettyPrintName = fieldParser.getObjectName(obj)
)
}
typealias WidgetId = Id
typealias ViewId = Id
typealias FromIndex = Int

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.widgets
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_models.SHARED_SPACE_TYPE
import com.anytypeio.anytype.core_models.SpaceType
import com.anytypeio.anytype.presentation.editor.cover.CoverView
@ -14,12 +15,13 @@ 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 {
val objectIcon: ObjectIcon
val obj: ObjectWrapper.Basic
val name: Name.Default
val name: Name
}
abstract val id: Id
@ -44,7 +46,7 @@ sealed class WidgetView {
val objectIcon: ObjectIcon = ObjectIcon.None,
val indent: Indent,
val path: String,
val name: Name.Default
val name: Name
)
sealed class ElementIcon {
@ -80,7 +82,7 @@ sealed class WidgetView {
data class Element(
override val objectIcon: ObjectIcon,
override val obj: ObjectWrapper.Basic,
override val name: Name.Default,
override val name: Name,
val cover: CoverView? = null
) : WidgetView.Element
}
@ -110,7 +112,7 @@ sealed class WidgetView {
data class Element(
override val objectIcon: ObjectIcon,
override val obj: ObjectWrapper.Basic,
override val name: Name.Default
override val name: Name
) : WidgetView.Element
sealed class Type {
data object Recent : Type()