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:
parent
d5a51d58f5
commit
d04c4c62d2
11 changed files with 109 additions and 44 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue