1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3126 Date as an Object | Updated header (#1880)

This commit is contained in:
Konstantin Ivanov 2024-12-06 14:59:39 +01:00 committed by GitHub
parent b9a38a4fb2
commit d455a4828c
Signed by: github
GPG key ID: B5690EEEBB952194
20 changed files with 361 additions and 111 deletions

View file

@ -63,10 +63,12 @@ object DateObjectModule {
@PerScreen
fun getObject(
repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
dispatchers: AppCoroutineDispatchers,
settings: UserSettingsRepository,
): GetObject = GetObject(
repo = repo,
dispatchers = dispatchers
dispatchers = dispatchers,
settings = settings
)
@JvmStatic

View file

@ -145,10 +145,12 @@ object HomeScreenModule {
@PerScreen
fun getObject(
repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
dispatchers: AppCoroutineDispatchers,
settings: UserSettingsRepository,
): GetObject = GetObject(
repo = repo,
dispatchers = dispatchers
dispatchers = dispatchers,
settings = settings
)
@JvmStatic

View file

@ -24,6 +24,7 @@ import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.other.DefaultDeepLinkResolver
import com.anytypeio.anytype.presentation.splash.SplashViewModel
import com.anytypeio.anytype.presentation.splash.SplashViewModelFactory
import com.anytypeio.anytype.ui.date.DateObjectFragment
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.home.HomeScreenFragment
import com.anytypeio.anytype.ui.onboarding.OnboardingFragment
@ -171,6 +172,27 @@ class SplashFragment : BaseFragment<FragmentSplashBinding>(R.layout.fragment_spl
Timber.e(it, "Error while navigating to set-or-collection from splash")
}
}
is SplashViewModel.Command.NavigateToDateObject -> {
runCatching {
findNavController().navigate(R.id.actionOpenVaultFromSplash)
findNavController().navigate(
R.id.actionOpenSpaceFromVault,
args = HomeScreenFragment.args(
space = command.space,
deeplink = null
)
)
findNavController().navigate(
resId = R.id.dateObjectScreen,
args = DateObjectFragment.args(
objectId = command.id,
space = command.space
)
)
}.onFailure {
Timber.e(it, "Error while navigating to date object from splash")
}
}
is SplashViewModel.Command.NavigateToAuthStart -> {
val intent = activity?.intent
val deepLink: String?

View file

@ -2,13 +2,43 @@ package com.anytypeio.anytype.core_models
sealed class RelativeDate {
abstract val initialTimeInMillis: TimeInMillis
abstract val dayOfWeek: DayOfWeekCustom
/** Represents an unset date (timestamp = 0.0) */
data object Empty : RelativeDate() {
override val initialTimeInMillis: TimeInMillis = 0
override val dayOfWeek: DayOfWeekCustom = DayOfWeekCustom.MONDAY // Default value
}
data class Today(
override val initialTimeInMillis: TimeInMillis,
override val dayOfWeek: DayOfWeekCustom
) : RelativeDate()
data class Tomorrow(
override val initialTimeInMillis: TimeInMillis,
override val dayOfWeek: DayOfWeekCustom
) : RelativeDate()
data class Yesterday(
override val initialTimeInMillis: TimeInMillis,
override val dayOfWeek: DayOfWeekCustom
) : RelativeDate()
data class Today(override val initialTimeInMillis: TimeInMillis) : RelativeDate()
data class Tomorrow(override val initialTimeInMillis: TimeInMillis) : RelativeDate()
data class Yesterday(override val initialTimeInMillis: TimeInMillis) : RelativeDate()
data class Other(
override val initialTimeInMillis: TimeInMillis,
override val dayOfWeek: DayOfWeekCustom,
val formattedDate: String,
val formattedTime: String
) : RelativeDate()
}
enum class DayOfWeekCustom {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}

View file

@ -66,6 +66,8 @@ object SupportedLayouts {
val widgetsLayouts = layouts + dateLayouts
val lastOpenObjectLayouts = layouts + dateLayouts
fun isSupported(layout: ObjectType.Layout?) : Boolean {
return layouts.contains(layout)
}

View file

@ -15,6 +15,9 @@ import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import com.anytypeio.anytype.core_models.DayOfWeekCustom
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
@ -96,3 +99,27 @@ fun <T> SnapshotStateList<T>.swapList(newList: List<T>){
clear()
addAll(newList)
}
@Composable
fun getLocalizedDayName(dayOfWeek: DayOfWeekCustom): String {
return when (dayOfWeek) {
DayOfWeekCustom.MONDAY -> stringResource(id = R.string.day_of_week_monday)
DayOfWeekCustom.TUESDAY -> stringResource(id = R.string.day_of_week_tuesday)
DayOfWeekCustom.WEDNESDAY -> stringResource(id = R.string.day_of_week_wednesday)
DayOfWeekCustom.THURSDAY -> stringResource(id = R.string.day_of_week_thursday)
DayOfWeekCustom.FRIDAY -> stringResource(id = R.string.day_of_week_friday)
DayOfWeekCustom.SATURDAY -> stringResource(id = R.string.day_of_week_saturday)
DayOfWeekCustom.SUNDAY -> stringResource(id = R.string.day_of_week_sunday)
}
}
@Composable
fun RelativeDate.getPrettyName(): String {
return when (this) {
is RelativeDate.Today -> stringResource(id = R.string.today)
is RelativeDate.Tomorrow -> stringResource(id = R.string.tomorrow)
is RelativeDate.Yesterday -> stringResource(id = R.string.yesterday)
is RelativeDate.Other -> this.formattedDate
RelativeDate.Empty -> ""
}
}

View file

@ -309,4 +309,5 @@ fun RelativeDate.getPrettyName(
is RelativeDate.Today -> resources.getString(R.string.today)
is RelativeDate.Tomorrow -> resources.getString(R.string.tomorrow)
is RelativeDate.Yesterday -> resources.getString(R.string.yesterday)
RelativeDate.Empty -> ""
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="3dp"
android:height="4dp"
android:viewportWidth="3"
android:viewportHeight="4">
<path
android:pathData="M1.5,2m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"
android:fillColor="@color/text_secondary"/>
</vector>

View file

@ -1,6 +1,7 @@
package com.anytypeio.anytype.device.providers
import android.text.format.DateUtils
import com.anytypeio.anytype.core_models.DayOfWeekCustom
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.TimeInSeconds
@ -185,9 +186,9 @@ class DateProviderImpl @Inject constructor(
return truncatedDateTime1 == truncatedDateTime2
}
override fun calculateRelativeDates(dateInSeconds: TimeInSeconds?): RelativeDate? {
override fun calculateRelativeDates(dateInSeconds: TimeInSeconds?): RelativeDate {
if (dateInSeconds == null || dateInSeconds == 0L) return null
if (dateInSeconds == null || dateInSeconds == 0L) return RelativeDate.Empty
val initialTimeInMillis = dateInSeconds * 1000
val zoneId = defaultZoneId
val dateInstant = Instant.ofEpochSecond(dateInSeconds)
@ -196,10 +197,33 @@ class DateProviderImpl @Inject constructor(
val daysDifference = ChronoUnit.DAYS.between(today, givenDate)
// Convert java.time.DayOfWeek to DayOfWeekCustom
val dayOfWeekCustom = when (givenDate.dayOfWeek) {
java.time.DayOfWeek.MONDAY -> DayOfWeekCustom.MONDAY
java.time.DayOfWeek.TUESDAY -> DayOfWeekCustom.TUESDAY
java.time.DayOfWeek.WEDNESDAY -> DayOfWeekCustom.WEDNESDAY
java.time.DayOfWeek.THURSDAY -> DayOfWeekCustom.THURSDAY
java.time.DayOfWeek.FRIDAY -> DayOfWeekCustom.FRIDAY
java.time.DayOfWeek.SATURDAY -> DayOfWeekCustom.SATURDAY
java.time.DayOfWeek.SUNDAY -> DayOfWeekCustom.SUNDAY
}
return when (daysDifference) {
0L -> RelativeDate.Today(initialTimeInMillis = initialTimeInMillis)
1L -> RelativeDate.Tomorrow(initialTimeInMillis = initialTimeInMillis)
-1L -> RelativeDate.Yesterday(initialTimeInMillis = initialTimeInMillis)
0L -> RelativeDate.Today(
initialTimeInMillis = initialTimeInMillis,
dayOfWeek = dayOfWeekCustom
)
1L -> RelativeDate.Tomorrow(
initialTimeInMillis = initialTimeInMillis,
dayOfWeek = dayOfWeekCustom
)
-1L -> RelativeDate.Yesterday(
initialTimeInMillis = initialTimeInMillis,
dayOfWeek = dayOfWeekCustom
)
else -> {
val timestampMillis = TimeUnit.SECONDS.toMillis(dateInSeconds)
@ -207,7 +231,8 @@ class DateProviderImpl @Inject constructor(
RelativeDate.Other(
initialTimeInMillis = initialTimeInMillis,
formattedDate = dateString,
formattedTime = timeString
formattedTime = timeString,
dayOfWeek = dayOfWeekCustom
)
}
}

View file

@ -26,7 +26,7 @@ interface DateProvider {
timestamp: TimeInMillis,
timeStyle: Int = DEFAULT_DATE_FORMAT_STYLE
): Pair<String, String>
fun calculateRelativeDates(dateInSeconds: TimeInSeconds?): RelativeDate?
fun calculateRelativeDates(dateInSeconds: TimeInSeconds?): RelativeDate
fun isSameMinute(timestamp1: Long, timestamp2: Long): Boolean
fun getLocalDateOfTime(epochMilli: Long): LocalDate
fun isTimestampWithinYearRange(timeStampInMillis: Long, yearRange: IntRange): Boolean

View file

@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.UserSettingsRepository
/**
* Use-case for opening an object as preview without subscribing to its subsequent changes.
@ -13,15 +14,24 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
*/
class GetObject(
private val repo: BlockRepository,
private val settings: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<GetObject.Params, ObjectView>(dispatchers.io) {
override suspend fun doWork(params: Params): ObjectView = repo.getObject(
id = params.target,
space = params.space
)
).also {
if (params.saveAsLastOpened) {
settings.setLastOpenedObject(
id = params.target,
space = params.space
)
}
}
data class Params(
val target: Id,
val space: SpaceId
val space: SpaceId,
val saveAsLastOpened: Boolean = false
)
}

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.MAX_SNIPPET_SIZE
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.RelativeDate
import com.anytypeio.anytype.core_models.SupportedLayouts
import com.anytypeio.anytype.core_models.TimeInSeconds
import com.anytypeio.anytype.core_models.primitives.Field
@ -91,7 +92,7 @@ class FieldParserImpl @Inject constructor(
private fun calculateFieldDate(value: Value.Single<Long>?): Field.Date? {
val dateInSeconds = value?.single ?: return null
val relativeDate = dateProvider.calculateRelativeDates(dateInSeconds)
if (relativeDate == null) {
if (relativeDate is RelativeDate.Empty) {
return null
}
return Field.Date(

View file

@ -43,6 +43,7 @@ import com.anytypeio.anytype.feature_date.viewmodel.UiFieldsState
@Composable
fun FieldsScreen(
modifier: Modifier,
uiState: UiFieldsState,
onDateEvent: (DateEvent) -> Unit
) {
@ -66,9 +67,9 @@ fun FieldsScreen(
LazyRow(
state = lazyFieldsListState,
modifier = Modifier.fillMaxWidth(),
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(start = 16.dp, end = 16.dp, top = 24.dp)
contentPadding = PaddingValues(start = 16.dp, end = 16.dp)
) {
items(
count = items.size,
@ -181,6 +182,7 @@ fun FieldsScreen(
@DefaultPreviews
fun FieldsScreenPreview() {
FieldsScreen(
modifier = Modifier.fillMaxWidth().height(40.dp),
uiState = UiFieldsState(
items = StubHorizontalItems,
selectedRelationKey = RelationKey("1")
@ -193,6 +195,7 @@ fun FieldsScreenPreview() {
@DefaultPreviews
fun LoadingPreview() {
FieldsScreen(
modifier = Modifier.fillMaxWidth().height(40.dp),
uiState = UiFieldsState.LoadingState,
onDateEvent = {}
)

View file

@ -2,11 +2,15 @@ package com.anytypeio.anytype.feature_date.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@ -18,13 +22,18 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_models.DayOfWeekCustom
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.common.ShimmerEffect
import com.anytypeio.anytype.core_ui.extensions.getLocalizedDayName
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
import com.anytypeio.anytype.core_ui.views.HeadlineTitle
import com.anytypeio.anytype.core_ui.views.Relations2
import com.anytypeio.anytype.feature_date.R
import com.anytypeio.anytype.feature_date.viewmodel.UiHeaderState
import com.anytypeio.anytype.feature_date.ui.models.DateEvent
import com.anytypeio.anytype.feature_date.viewmodel.UiHeaderState
@Composable
fun HeaderScreen(
@ -32,91 +41,155 @@ fun HeaderScreen(
uiState: UiHeaderState,
onDateEvent: (DateEvent) -> Unit
) {
Row(
modifier = modifier
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
RelativeDateAndDayOfWeek(
modifier = Modifier
.height(48.dp)
.width(52.dp)
.rotate(180f)
.noRippleThrottledClickable {
onDateEvent(DateEvent.Header.OnPreviousClick)
},
contentDescription = "Previous day",
painter = painterResource(id = R.drawable.ic_arrow_disclosure_18),
contentScale = ContentScale.None
.wrapContentSize(),
uiState = uiState
)
when (uiState) {
is UiHeaderState.Content -> {
Text(
textAlign = TextAlign.Center,
text = uiState.title,
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.align(Alignment.CenterVertically),
style = HeadlineTitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = colorResource(id = R.color.text_primary)
)
}
UiHeaderState.Loading -> {
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.align(Alignment.CenterVertically),
contentAlignment = Alignment.Center
) {
ShimmerEffect(
Spacer(modifier = Modifier.height(4.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
verticalAlignment = Alignment.CenterVertically
) {
Image(
modifier = Modifier
.height(32.dp)
.width(52.dp)
.rotate(180f)
.noRippleThrottledClickable {
onDateEvent(DateEvent.Header.OnPreviousClick)
},
contentDescription = "Previous day",
painter = painterResource(id = R.drawable.ic_arrow_disclosure_18),
contentScale = ContentScale.None
)
when (uiState) {
is UiHeaderState.Content -> {
Text(
textAlign = TextAlign.Center,
text = uiState.title,
modifier = Modifier
.width(200.dp)
.height(30.dp)
.wrapContentHeight()
.fillMaxWidth()
.weight(1f)
.noRippleThrottledClickable {
onDateEvent(
DateEvent.Header.OnHeaderClick(
timeInMillis = uiState.relativeDate.initialTimeInMillis
)
)
},
style = HeadlineTitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = colorResource(id = R.color.text_primary)
)
}
}
UiHeaderState.Empty -> {
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.align(Alignment.CenterVertically),
contentAlignment = Alignment.Center
) {
Spacer(
UiHeaderState.Loading -> {
Box(
modifier = Modifier
.width(200.dp)
.height(30.dp)
)
.fillMaxWidth()
.weight(1f)
.align(Alignment.CenterVertically),
contentAlignment = Alignment.Center
) {
ShimmerEffect(
modifier = Modifier
.width(200.dp)
.height(30.dp)
)
}
}
UiHeaderState.Empty -> {
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.align(Alignment.CenterVertically),
contentAlignment = Alignment.Center
) {
Spacer(
modifier = Modifier
.width(200.dp)
.height(30.dp)
)
}
}
}
Image(
modifier = Modifier
.height(32.dp)
.width(52.dp)
.noRippleThrottledClickable {
onDateEvent(DateEvent.Header.OnNextClick)
},
contentDescription = "Next day",
painter = painterResource(id = R.drawable.ic_arrow_disclosure_18),
contentScale = ContentScale.None
)
}
Image(
modifier = Modifier
.height(48.dp)
.width(52.dp)
.noRippleThrottledClickable {
onDateEvent(DateEvent.Header.OnNextClick)
},
contentDescription = "Next day",
painter = painterResource(id = R.drawable.ic_arrow_disclosure_18),
contentScale = ContentScale.None
)
}
}
@Composable
fun RelativeDateAndDayOfWeek(
modifier: Modifier = Modifier,
uiState: UiHeaderState
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
if (uiState is UiHeaderState.Content) {
uiState.relativeDate.takeIf { it is RelativeDate.Today || it is RelativeDate.Tomorrow || it is RelativeDate.Yesterday }
?.let { relativeDate ->
DateWithDot(relativeDate.getPrettyName())
}
val dayOfWeek = getLocalizedDayName(uiState.relativeDate.dayOfWeek)
Text(
text = dayOfWeek,
style = Relations2,
color = colorResource(id = R.color.text_secondary),
modifier = Modifier.wrapContentSize()
)
}
}
}
@Composable
fun DateWithDot(dateText: String) {
Text(
text = dateText,
style = Relations2,
color = colorResource(id = R.color.text_secondary),
modifier = Modifier.wrapContentSize()
)
Image(
painter = painterResource(id = R.drawable.ic_dot_3),
contentDescription = "dot",
contentScale = ContentScale.Fit,
modifier = Modifier
.padding(horizontal = 8.dp)
.wrapContentSize()
)
}
@Composable
@DefaultPreviews
fun DateLayoutHeaderEmptyPreview() {
val state = UiHeaderState.Empty
HeaderScreen(
modifier = Modifier
.fillMaxWidth()
.height(48.dp), uiState = state
.fillMaxWidth(), uiState = state
) {}
}
@ -126,18 +199,22 @@ fun DateLayoutHeaderLoadingPreview() {
val state = UiHeaderState.Loading
HeaderScreen(
Modifier
.fillMaxWidth()
.height(48.dp), state
.fillMaxWidth(), state
) {}
}
@Composable
@DefaultPreviews
fun DateLayoutHeaderPreview() {
val state = UiHeaderState.Content("Tue, 12 Oct")
val state = UiHeaderState.Content(
title = "Tue, 12 Oct",
relativeDate = RelativeDate.Today(
initialTimeInMillis = 1634016000000,
dayOfWeek = DayOfWeekCustom.MONDAY
)
)
HeaderScreen(
Modifier
.fillMaxWidth()
.height(48.dp), state
.fillMaxWidth(), state
) {}
}

View file

@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
@ -83,16 +84,20 @@ fun DateMainScreen(
onDateEvent = onDateEvent
)
Spacer(
modifier = Modifier.height(24.dp)
modifier = Modifier.height(16.dp)
)
HeaderScreen(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
.height(54.dp),
uiState = uiHeaderState,
onDateEvent = onDateEvent
)
Spacer(
modifier = Modifier.height(32.dp)
)
FieldsScreen(
modifier = Modifier.fillMaxWidth().height(40.dp),
uiState = uiFieldsState,
onDateEvent = onDateEvent
)

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.feature_date.ui.models
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncAndP2PStatusState
import com.anytypeio.anytype.core_models.primitives.TimestampInSeconds
import com.anytypeio.anytype.feature_date.viewmodel.UiFieldsItem
@ -15,6 +16,7 @@ sealed class DateEvent {
sealed class Header : DateEvent() {
data object OnNextClick : Header()
data object OnPreviousClick : Header()
data class OnHeaderClick(val timeInMillis: TimeInMillis): Header()
}
sealed class FieldsSheet : DateEvent() {

View file

@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.DVSortType
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncAndP2PStatusState
import com.anytypeio.anytype.core_models.primitives.RelationKey
@ -29,7 +30,8 @@ sealed class UiHeaderState {
data object Empty : UiHeaderState()
data object Loading : UiHeaderState()
data class Content(
val title: String
val title: String,
val relativeDate: RelativeDate
) : UiHeaderState()
}

View file

@ -293,7 +293,8 @@ class DateObjectViewModel(
.collect { id ->
val params = GetObject.Params(
target = id,
space = vmParams.spaceId
space = vmParams.spaceId,
saveAsLastOpened = true
)
Timber.d("Start GetObject with params: $params")
getObject.async(params).fold(
@ -312,7 +313,10 @@ class DateObjectViewModel(
timestampInSeconds = TimestampInSeconds(timestampInSeconds)
)
uiHeaderState.value = UiHeaderState.Content(
title = formattedDate
title = formattedDate,
relativeDate = dateProvider.calculateRelativeDates(
dateInSeconds = timestampInSeconds
)
)
}
},
@ -668,21 +672,7 @@ class DateObjectViewModel(
private fun onTopToolbarEvent(event: DateEvent.TopToolbar) {
when (event) {
is DateEvent.TopToolbar.OnCalendarClick -> {
val timestampInSeconds = event.timestampInSeconds
val timeInMillis = dateProvider.adjustToStartOfDayInUserTimeZone(
timestamp = timestampInSeconds.time
)
val isValid = dateProvider.isTimestampWithinYearRange(
timeStampInMillis = timeInMillis,
yearRange = DATE_PICKER_YEAR_RANGE
)
if (isValid) {
uiCalendarState.value = UiCalendarState.Calendar(
timeInMillis = timeInMillis
)
} else {
showDateOutOfRangeError()
}
proceedWithShowCalendar(timestampInSeconds = event.timestampInSeconds)
}
is DateEvent.TopToolbar.OnSyncStatusClick -> {
@ -694,10 +684,33 @@ class DateObjectViewModel(
}
}
private fun proceedWithShowCalendar(timestampInSeconds: TimestampInSeconds) {
val timeInMillis = dateProvider.adjustToStartOfDayInUserTimeZone(
timestamp = timestampInSeconds.time
)
val isValid = dateProvider.isTimestampWithinYearRange(
timeStampInMillis = timeInMillis,
yearRange = DATE_PICKER_YEAR_RANGE
)
if (isValid) {
uiCalendarState.value = UiCalendarState.Calendar(
timeInMillis = timeInMillis
)
} else {
showDateOutOfRangeError()
}
}
private fun onHeaderEvent(event: DateEvent.Header) {
when (event) {
DateEvent.Header.OnNextClick -> proceedWithReopeningDate(offset = SECONDS_IN_DAY)
DateEvent.Header.OnPreviousClick -> proceedWithReopeningDate(offset = -SECONDS_IN_DAY)
is DateEvent.Header.OnHeaderClick -> {
val timestampInSeconds = TimestampInSeconds(
time = event.timeInMillis / 1000
)
proceedWithShowCalendar(timestampInSeconds)
}
}
}

View file

@ -1838,4 +1838,12 @@ Please provide specific details of your needs here.</string>
<string name="chat_attachment_upload">Upload</string>
<string name="chats_reply">Reply</string>
<string name="day_of_week_monday">Monday</string>
<string name="day_of_week_tuesday">Tuesday</string>
<string name="day_of_week_wednesday">Wednesday</string>
<string name="day_of_week_thursday">Thursday</string>
<string name="day_of_week_friday">Friday</string>
<string name="day_of_week_saturday">Saturday</string>
<string name="day_of_week_sunday">Sunday</string>
</resources>

View file

@ -241,7 +241,7 @@ class SplashViewModel(
success = { response ->
when (response) {
is GetLastOpenedObject.Response.Success -> {
if (SupportedLayouts.layouts.contains(response.obj.layout)) {
if (SupportedLayouts.lastOpenObjectLayouts.contains(response.obj.layout)) {
val id = response.obj.id
val space = requireNotNull(response.obj.spaceId)
when (response.obj.layout) {
@ -252,6 +252,14 @@ class SplashViewModel(
space = space
)
)
ObjectType.Layout.DATE -> {
commands.emit(
Command.NavigateToDateObject(
id = id,
space = space
)
)
}
else ->
commands.emit(
Command.NavigateToObject(
@ -319,6 +327,7 @@ class SplashViewModel(
data object CheckAppStartIntent : Command()
data class NavigateToObject(val id: Id, val space: Id) : Command()
data class NavigateToObjectSet(val id: Id, val space: Id) : Command()
data class NavigateToDateObject(val id: Id, val space: Id) : Command()
data class Toast(val message: String) : Command()
}