Create module dateformatter
This commit is contained in:
parent
c3a7ab1de4
commit
ae4237abb5
12 changed files with 119 additions and 10 deletions
|
|
@ -41,7 +41,7 @@ dependencies {
|
|||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.elementresources)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
implementation(libs.datetime)
|
||||
implementation(projects.libraries.dateformatter)
|
||||
implementation(libs.accompanist.placeholder)
|
||||
|
||||
testImplementation(libs.test.junit)
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomlist
|
||||
|
||||
import android.text.format.DateFormat
|
||||
import android.text.format.DateUtils
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toInstant
|
||||
import kotlinx.datetime.toJavaLocalDate
|
||||
import kotlinx.datetime.toJavaLocalDateTime
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import java.time.Period
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
class LastMessageFormatter @Inject constructor() {
|
||||
|
||||
private val clock: Clock = Clock.System
|
||||
private val locale: Locale = Locale.getDefault()
|
||||
|
||||
private val onlyTimeFormatter: DateTimeFormatter by lazy {
|
||||
val pattern = DateFormat.getBestDateTimePattern(locale, "HH:mm")
|
||||
DateTimeFormatter.ofPattern(pattern)
|
||||
}
|
||||
|
||||
private val dateWithMonthFormatter: DateTimeFormatter by lazy {
|
||||
val pattern = DateFormat.getBestDateTimePattern(locale, "d MMM")
|
||||
DateTimeFormatter.ofPattern(pattern)
|
||||
}
|
||||
|
||||
private val dateWithYearFormatter: DateTimeFormatter by lazy {
|
||||
val pattern = DateFormat.getBestDateTimePattern(locale, "dd.MM.yyyy")
|
||||
DateTimeFormatter.ofPattern(pattern)
|
||||
}
|
||||
|
||||
fun format(timestamp: Long?): String {
|
||||
if (timestamp == null) return ""
|
||||
val now: Instant = clock.now()
|
||||
val tsInstant = Instant.fromEpochMilliseconds(timestamp)
|
||||
val nowDateTime = now.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
val tsDateTime = tsInstant.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
val isSameDay = nowDateTime.date == tsDateTime.date
|
||||
return when {
|
||||
isSameDay -> {
|
||||
onlyTimeFormatter.format(tsDateTime.toJavaLocalDateTime())
|
||||
}
|
||||
else -> {
|
||||
formatDate(tsDateTime, nowDateTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDate(
|
||||
date: LocalDateTime,
|
||||
currentDate: LocalDateTime,
|
||||
): String {
|
||||
val period = Period.between(date.date.toJavaLocalDate(), currentDate.date.toJavaLocalDate())
|
||||
return if (period.years.absoluteValue >= 1) {
|
||||
formatDateWithYear(date)
|
||||
} else if (period.days.absoluteValue < 2 && period.months.absoluteValue < 1) {
|
||||
getRelativeDay(date.toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds())
|
||||
} else {
|
||||
formatDateWithMonth(date)
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatDateWithMonth(localDateTime: LocalDateTime): String {
|
||||
return dateWithMonthFormatter.format(localDateTime.toJavaLocalDateTime())
|
||||
}
|
||||
|
||||
private fun formatDateWithYear(localDateTime: LocalDateTime): String {
|
||||
return dateWithYearFormatter.format(localDateTime.toJavaLocalDateTime())
|
||||
}
|
||||
|
||||
private fun getRelativeDay(ts: Long): String {
|
||||
return DateUtils.getRelativeTimeSpanString(
|
||||
ts,
|
||||
clock.now().toEpochMilliseconds(),
|
||||
DateUtils.DAY_IN_MILLIS,
|
||||
DateUtils.FORMAT_SHOW_WEEKDAY
|
||||
).toString()
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,7 @@ import io.element.android.features.roomlist.model.RoomListRoomSummaryPlaceholder
|
|||
import io.element.android.features.roomlist.model.RoomListState
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.parallelMap
|
||||
import io.element.android.libraries.dateformatter.LastMessageFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.matrix.MatrixClient
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import app.cash.turbine.test
|
|||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.roomlist.model.RoomListEvents
|
||||
import io.element.android.features.roomlist.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.dateformatter.impl.DefaultLastMessageFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.matrix.core.SessionId
|
||||
import io.element.android.libraries.matrixtest.FakeMatrixClient
|
||||
|
|
@ -45,7 +46,7 @@ class RoomListPresenterTests {
|
|||
FakeMatrixClient(
|
||||
SessionId("sessionId")
|
||||
),
|
||||
LastMessageFormatter()
|
||||
DefaultLastMessageFormatter()
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -63,7 +64,7 @@ class RoomListPresenterTests {
|
|||
FakeMatrixClient(
|
||||
SessionId("sessionId")
|
||||
),
|
||||
LastMessageFormatter()
|
||||
DefaultLastMessageFormatter()
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -85,7 +86,7 @@ class RoomListPresenterTests {
|
|||
sessionId = SessionId("sessionId"),
|
||||
roomSummaryDataSource = roomSummaryDataSource
|
||||
),
|
||||
LastMessageFormatter()
|
||||
DefaultLastMessageFormatter()
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -111,7 +112,7 @@ class RoomListPresenterTests {
|
|||
sessionId = SessionId("sessionId"),
|
||||
roomSummaryDataSource = roomSummaryDataSource
|
||||
),
|
||||
LastMessageFormatter()
|
||||
DefaultLastMessageFormatter()
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
|
|
@ -142,7 +143,7 @@ class RoomListPresenterTests {
|
|||
sessionId = SessionId("sessionId"),
|
||||
roomSummaryDataSource = roomSummaryDataSource
|
||||
),
|
||||
LastMessageFormatter()
|
||||
DefaultLastMessageFormatter()
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue