Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions app/src/main/java/org/monogram/app/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,35 @@ import android.annotation.SuppressLint
import android.content.ClipboardManager
import android.content.Context
import android.telephony.TelephonyManager
import android.text.format.DateFormat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
import org.monogram.core.Logger
import org.monogram.data.di.dataModule
import org.monogram.domain.managers.*
import org.monogram.domain.repository.*
import org.monogram.presentation.core.util.*
import org.monogram.domain.managers.AssetsManager
import org.monogram.domain.managers.ClipManager
import org.monogram.domain.managers.DistrManager
import org.monogram.domain.managers.DomainManager
import org.monogram.domain.managers.PhoneManager
import org.monogram.domain.repository.AppPreferencesProvider
import org.monogram.domain.repository.BotPreferencesProvider
import org.monogram.domain.repository.CacheProvider
import org.monogram.domain.repository.EditorSnippetProvider
import org.monogram.domain.repository.ExternalNavigator
import org.monogram.domain.repository.MessageDisplayer
import org.monogram.presentation.core.util.AppPreferences
import org.monogram.presentation.core.util.BotPreferences
import org.monogram.presentation.core.util.CachePreferences
import org.monogram.presentation.core.util.DateFormatManager
import org.monogram.presentation.core.util.DateFormatManagerImpl
import org.monogram.presentation.core.util.DownloadUtils
import org.monogram.presentation.core.util.EditorSnippetPreferences
import org.monogram.presentation.core.util.ExternalNavigatorImpl
import org.monogram.presentation.core.util.IDownloadUtils
import org.monogram.presentation.core.util.ToastMessageDisplayer
import org.monogram.presentation.di.uiModule
import org.monogram.presentation.features.chats.currentChat.components.ExoPlayerCache
import org.monogram.presentation.features.chats.currentChat.components.VideoPlayerPool
Expand Down Expand Up @@ -41,6 +60,8 @@ val appModule = module {
}
single<Logger> { LoggerImpl() }

single<DateFormatManager> { DateFormatManagerImpl(DateFormat.is24HourFormat(androidContext())) }

factory<PhoneManager> {
PhoneManagerImpl(
androidContext().getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager,
Expand Down
23 changes: 23 additions & 0 deletions core/src/main/kotlin/org/monogram/core/date/DateFormatManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.monogram.core.date

interface DateFormatManager {
fun is24HourFormat(): Boolean
fun getHourMinuteFormat(): String
}

class DateFormatManagerImpl(
private val use24HourFormat: Boolean
) : DateFormatManager {
override fun is24HourFormat(): Boolean = use24HourFormat
override fun getHourMinuteFormat(): String = if (use24HourFormat) "HH:mm" else "h:mm a"
}

class Fake12HourDateFormatManagerImpl : DateFormatManager {
override fun is24HourFormat(): Boolean = false
override fun getHourMinuteFormat(): String = "h:mm a"
}

class Fake24HourDateFormatManagerImpl : DateFormatManager {
override fun is24HourFormat(): Boolean = true
override fun getHourMinuteFormat(): String = "HH:mm"
}
2 changes: 1 addition & 1 deletion data/src/main/java/org/monogram/data/di/dataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ val dataModule = module {
}

single {
ChatMapper(get())
ChatMapper(get(), get())
}

single {
Expand Down
19 changes: 15 additions & 4 deletions data/src/main/java/org/monogram/data/mapper/ChatMapper.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package org.monogram.data.mapper

import org.drinkless.tdlib.TdApi
import org.monogram.core.date.DateFormatManager
import org.monogram.data.db.model.ChatEntity
import org.monogram.domain.models.*
import org.monogram.domain.models.ChatModel
import org.monogram.domain.models.ChatType
import org.monogram.domain.models.MessageEntity
import org.monogram.domain.models.MessageEntityType
import org.monogram.domain.models.UsernamesModel
import org.monogram.domain.repository.StringProvider
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale

class ChatMapper(private val stringProvider: StringProvider) {
class ChatMapper(
private val stringProvider: StringProvider,
private val dateFormatManager: DateFormatManager
) {
fun mapChatToModel(
chat: TdApi.Chat,
order: Long,
Expand Down Expand Up @@ -431,7 +440,8 @@ class ChatMapper(private val stringProvider: StringProvider) {
}

val date = lastMsg.date
val timeFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
val timeFormat =
SimpleDateFormat(dateFormatManager.getHourMinuteFormat(), Locale.getDefault())
val time = if (date > 0) timeFormat.format(Date(date.toLong() * 1000)) else ""
return Triple(txt, entities, time)
}
Expand All @@ -455,6 +465,7 @@ class ChatMapper(private val stringProvider: StringProvider) {
return formatChatUserStatus(
status = status,
stringProvider = stringProvider,
dateFormatManager = dateFormatManager,
isBot = isBot
)
}
Expand Down
15 changes: 12 additions & 3 deletions data/src/main/java/org/monogram/data/mapper/UserStatusFormatter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package org.monogram.data.mapper

import android.text.format.DateUtils
import org.drinkless.tdlib.TdApi
import org.monogram.core.date.DateFormatManager
import org.monogram.domain.repository.StringProvider
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale

internal fun formatChatUserStatus(
status: TdApi.UserStatus,
stringProvider: StringProvider,
dateFormatManager: DateFormatManager,
isBot: Boolean = false
): String {
if (isBot) return stringProvider.getString("chat_mapper_bot")
Expand All @@ -29,13 +32,19 @@ internal fun formatChatUserStatus(

DateUtils.isToday(wasOnline) -> {
val date = Date(wasOnline)
val format = SimpleDateFormat("HH:mm", Locale.getDefault())
val format = SimpleDateFormat(
dateFormatManager.getHourMinuteFormat(),
Locale.getDefault()
)
stringProvider.getString("chat_mapper_seen_at", format.format(date))
}

isYesterday(wasOnline) -> {
val date = Date(wasOnline)
val format = SimpleDateFormat("HH:mm", Locale.getDefault())
val format = SimpleDateFormat(
dateFormatManager.getHourMinuteFormat(),
Locale.getDefault()
)
stringProvider.getString("chat_mapper_seen_yesterday", format.format(date))
}

Expand Down
61 changes: 61 additions & 0 deletions data/src/test/java/org/monogram/data/mapper/ChatMapperTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.monogram.data.mapper

import org.drinkless.tdlib.TdApi
import org.junit.Assert.assertEquals
import org.junit.Test
import org.monogram.core.date.Fake12HourDateFormatManagerImpl
import org.monogram.core.date.Fake24HourDateFormatManagerImpl
import org.monogram.domain.repository.StringProvider
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class ChatMapperTest {

@Test
fun `formatMessageInfo uses 12 hour time format`() {
val mapper = ChatMapper(FakeStringProvider(), Fake12HourDateFormatManagerImpl())
val timestampSeconds = 1710948000
val message = createTextMessage(timestampSeconds)

val (_, _, time) = mapper.formatMessageInfo(message, null) { null }

val expected =
SimpleDateFormat("h:mm a", Locale.getDefault()).format(Date(timestampSeconds * 1000L))
assertEquals(expected, time)
}

@Test
fun `formatMessageInfo uses 24 hour time format`() {
val mapper = ChatMapper(FakeStringProvider(), Fake24HourDateFormatManagerImpl())
val timestampSeconds = 1710948000
val message = createTextMessage(timestampSeconds)

val (_, _, time) = mapper.formatMessageInfo(message, null) { null }

val expected =
SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(timestampSeconds * 1000L))
assertEquals(expected, time)
}

private fun createTextMessage(timestampSeconds: Int): TdApi.Message {
return TdApi.Message().apply {
date = timestampSeconds
content = TdApi.MessageText().apply {
text = TdApi.FormattedText("test", emptyArray())
}
}
}

private class FakeStringProvider : StringProvider {
override fun getString(resName: String): String = resName

override fun getString(resName: String, vararg formatArgs: Any): String = resName

override fun getQuantityString(
resName: String,
quantity: Int,
vararg formatArgs: Any
): String = resName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import java.util.Date
import java.util.Locale
import kotlin.math.abs
import kotlin.math.roundToLong
import org.monogram.core.date.DateFormatManager as CoreDateFormatManager
import org.monogram.core.date.DateFormatManagerImpl as CoreDateFormatManagerImpl
import org.monogram.core.date.Fake12HourDateFormatManagerImpl as CoreFake12HourDateFormatManagerImpl
import org.monogram.core.date.Fake24HourDateFormatManagerImpl as CoreFake24HourDateFormatManagerImpl

/**
* Formats date as relative string as for day, week, year, periods and so-on
Expand All @@ -14,6 +18,7 @@ import kotlin.math.roundToLong
* @param now optional current date (for custom formatting or testing)
**/
fun Date.toShortRelativeDate(
timeFormat: String,
locale: Locale = Locale.getDefault(),
now: Date = Date()
): String {
Expand Down Expand Up @@ -42,7 +47,7 @@ fun Date.toShortRelativeDate(

return when (diffDays) {
0L -> {
SimpleDateFormat("HH:mm", locale).format(this)
SimpleDateFormat(timeFormat, locale).format(this)
}
in 1..6 -> {
SimpleDateFormat("EEE", locale).format(this)
Expand All @@ -59,3 +64,8 @@ fun Date.toShortRelativeDate(
}
}
}

typealias DateFormatManager = CoreDateFormatManager
typealias DateFormatManagerImpl = CoreDateFormatManagerImpl
typealias Fake12HourDateFormatManagerImpl = CoreFake12HourDateFormatManagerImpl
typealias Fake24HourDateFormatManagerImpl = CoreFake24HourDateFormatManagerImpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import org.koin.compose.koinInject
import org.monogram.domain.models.*
import org.monogram.presentation.R
import java.text.SimpleDateFormat
import java.util.*

fun formatLastSeen(lastSeen: Long?, context: Context): String {
fun formatLastSeen(lastSeen: Long?, context: Context, timeFormat: String): String {
if (lastSeen == null || lastSeen <= 0L) return context.getString(R.string.last_seen_recently)

val now = System.currentTimeMillis()
val diff = now - lastSeen

if (diff < 0) return context.getString(R.string.last_seen_just_now)

return when {
Expand All @@ -35,12 +35,12 @@ fun formatLastSeen(lastSeen: Long?, context: Context): String {
}

DateUtils.isToday(lastSeen) -> {
val time = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(lastSeen))
val time = SimpleDateFormat(timeFormat, Locale.getDefault()).format(Date(lastSeen))
context.getString(R.string.last_seen_at, time)
}

isYesterday(lastSeen) -> {
val time = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(lastSeen))
val time = SimpleDateFormat(timeFormat, Locale.getDefault()).format(Date(lastSeen))
context.getString(R.string.last_seen_yesterday_at, time)
}

Expand All @@ -57,10 +57,12 @@ fun rememberUserStatusText(user: UserModel?): String {
if (user.type == UserTypeEnum.BOT) return stringResource(R.string.status_bot)

val context = LocalContext.current
val dateFormatManager: DateFormatManager = koinInject()
val timeFormat = dateFormatManager.getHourMinuteFormat()
return remember(user.userStatus, user.lastSeen) {
when (user.userStatus) {
UserStatusType.ONLINE -> context.getString(R.string.status_online)
UserStatusType.OFFLINE -> formatLastSeen(user.lastSeen, context)
UserStatusType.OFFLINE -> formatLastSeen(user.lastSeen, context, timeFormat)
UserStatusType.RECENTLY -> context.getString(R.string.last_seen_recently)
UserStatusType.LAST_WEEK -> context.getString(R.string.last_seen_within_week)
UserStatusType.LAST_MONTH -> context.getString(R.string.last_seen_within_month)
Expand All @@ -73,13 +75,13 @@ private fun isYesterday(timestamp: Long): Boolean {
return DateUtils.isToday(timestamp + DateUtils.DAY_IN_MILLIS)
}

fun getUserStatusText(user: UserModel?, context: Context): String {
fun getUserStatusText(user: UserModel?, context: Context, timeFormat: String): String {
if (user == null) return context.getString(R.string.status_offline)
if (user.type == UserTypeEnum.BOT) return context.getString(R.string.status_bot)

return when (user.userStatus) {
UserStatusType.ONLINE -> context.getString(R.string.status_online)
UserStatusType.OFFLINE -> formatLastSeen(user.lastSeen, context)
UserStatusType.OFFLINE -> formatLastSeen(user.lastSeen, context, timeFormat)
UserStatusType.RECENTLY -> context.getString(R.string.last_seen_recently)
UserStatusType.LAST_WEEK -> context.getString(R.string.last_seen_within_week)
UserStatusType.LAST_MONTH -> context.getString(R.string.last_seen_within_month)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import org.monogram.core.date.toDate
import org.koin.compose.koinInject
import org.monogram.domain.models.ChatModel
import org.monogram.domain.models.MessageEntityType
import org.monogram.presentation.R
import org.monogram.presentation.core.ui.AvatarForChat
import org.monogram.presentation.core.ui.TypingDots
import org.monogram.presentation.core.util.DateFormatManager
import org.monogram.presentation.core.util.toShortRelativeDate
import org.monogram.presentation.features.chats.currentChat.components.chats.addEmojiStyle
import org.monogram.presentation.features.chats.currentChat.components.chats.buildAnnotatedMessageTextWithEmoji
Expand Down Expand Up @@ -219,7 +221,9 @@ private fun ChatListItemHeader(
chat: ChatModel,
isSavedMessages: Boolean
) {
val chatTime = chat.lastMessageDate.toDate().toShortRelativeDate()
val dateFormatManager: DateFormatManager = koinInject()
val timeFormat = dateFormatManager.getHourMinuteFormat()
val chatTime = chat.lastMessageDate.toDate().toShortRelativeDate(timeFormat)
val savedMessagesTitle = stringResource(R.string.menu_saved_messages)

Row(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.koin.compose.koinInject
import org.monogram.domain.models.MessageContent
import org.monogram.domain.models.MessageModel
import org.monogram.presentation.core.ui.Avatar
import org.monogram.presentation.core.util.DateFormatManager
import java.text.SimpleDateFormat
import java.util.*

Expand All @@ -27,11 +29,14 @@ fun MessageSearchItem(
val currentCalendar = Calendar.getInstance()
calendar.time = date

val dateFormatManager: DateFormatManager = koinInject();
val timeFormat = dateFormatManager.getHourMinuteFormat()

val isToday = calendar.get(Calendar.YEAR) == currentCalendar.get(Calendar.YEAR) &&
calendar.get(Calendar.DAY_OF_YEAR) == currentCalendar.get(Calendar.DAY_OF_YEAR)

val format = if (isToday) {
SimpleDateFormat("HH:mm", Locale.getDefault())
SimpleDateFormat(timeFormat, Locale.getDefault())
} else {
SimpleDateFormat("MMM d", Locale.getDefault())
}
Expand Down
Loading