core, mobile: correctly check whether date is recent (#2559)

This commit is contained in:
spaced4ndy 2023-06-08 11:23:04 +04:00 committed by GitHub
parent fb72dfcdee
commit f581e91f19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 124 additions and 15 deletions

View file

@ -1624,8 +1624,9 @@ fun getTimestampText(t: Instant): String {
val tz = TimeZone.currentSystemDefault() val tz = TimeZone.currentSystemDefault()
val now: LocalDateTime = Clock.System.now().toLocalDateTime(tz) val now: LocalDateTime = Clock.System.now().toLocalDateTime(tz)
val time: LocalDateTime = t.toLocalDateTime(tz) val time: LocalDateTime = t.toLocalDateTime(tz)
val period = now.date.minus(time.date)
val recent = now.date == time.date || val recent = now.date == time.date ||
(now.date.minus(time.date).days == 1 && now.hour < 12 && time.hour >= 18 ) (period.years == 0 && period.months == 0 && period.days == 1 && now.hour < 12 && time.hour >= 18 )
val dateFormatter = val dateFormatter =
if (recent) { if (recent) {
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)

View file

@ -2283,10 +2283,22 @@ let msgTimeFormat = Date.FormatStyle.dateTime.hour().minute()
let msgDateFormat = Date.FormatStyle.dateTime.day(.twoDigits).month(.twoDigits) let msgDateFormat = Date.FormatStyle.dateTime.day(.twoDigits).month(.twoDigits)
public func formatTimestampText(_ date: Date) -> Text { public func formatTimestampText(_ date: Date) -> Text {
let now = Calendar.current.dateComponents([.day, .hour], from: .now) return Text(date, format: recent(date) ? msgTimeFormat : msgDateFormat)
let dc = Calendar.current.dateComponents([.day, .hour], from: date) }
let recent = now.day == dc.day || ((now.day ?? 0) - (dc.day ?? 0) == 1 && (dc.hour ?? 0) >= 18 && (now.hour ?? 0) < 12)
return Text(date, format: recent ? msgTimeFormat : msgDateFormat) private func recent(_ date: Date) -> Bool {
let now = Date()
let calendar = Calendar.current
guard let previousDay = calendar.date(byAdding: DateComponents(day: -1), to: now),
let previousDay18 = calendar.date(bySettingHour: 18, minute: 0, second: 0, of: previousDay),
let currentDay00 = calendar.date(bySettingHour: 0, minute: 0, second: 0, of: now),
let currentDay12 = calendar.date(bySettingHour: 12, minute: 0, second: 0, of: now) else {
return false
}
let isSameDay = calendar.isDate(date, inSameDayAs: now)
return isSameDay || (now < currentDay12 && date >= previousDay18 && date < currentDay00)
} }
public enum CIStatus: Decodable { public enum CIStatus: Decodable {

View file

@ -374,6 +374,7 @@ test-suite simplex-chat-test
MobileTests MobileTests
ProtocolTests ProtocolTests
SchemaDump SchemaDump
ViewTests
WebRTCTests WebRTCTests
Paths_simplex_chat Paths_simplex_chat
hs-source-dirs: hs-source-dirs:

View file

@ -24,9 +24,10 @@ import Data.Maybe (fromMaybe, isJust, isNothing, mapMaybe)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Data.Text.Encoding (decodeLatin1) import Data.Text.Encoding (decodeLatin1)
import Data.Time.Clock (DiffTime, UTCTime) import Data.Time (LocalTime (..), TimeOfDay (..), TimeZone (..), utcToLocalTime)
import Data.Time.Calendar (addDays)
import Data.Time.Clock (UTCTime)
import Data.Time.Format (defaultTimeLocale, formatTime) import Data.Time.Format (defaultTimeLocale, formatTime)
import Data.Time.LocalTime (TimeZone, localDay, localTimeOfDay, timeOfDayToTime, utcToLocalTime)
import Data.Word (Word32) import Data.Word (Word32)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import qualified Network.HTTP.Types as Q import qualified Network.HTTP.Types as Q
@ -1107,16 +1108,22 @@ receivedWithTime_ ts tz from quote CIMeta {itemId, itemTs, itemEdited, itemDelet
_ -> "" _ -> ""
ttyMsgTime :: CurrentTime -> TimeZone -> UTCTime -> StyledString ttyMsgTime :: CurrentTime -> TimeZone -> UTCTime -> StyledString
ttyMsgTime currentTime tz time = ttyMsgTime now tz time =
let localTime = utcToLocalTime tz time let fmt = if recent now tz time then "%H:%M" else "%m-%d"
localCurrentTime = utcToLocalTime tz currentTime localTime = utcToLocalTime tz time
fmt =
if (localDay localTime < localDay localCurrentTime)
&& (timeOfDayToTime (localTimeOfDay localTime) > (6 * 60 * 60 :: DiffTime))
then "%m-%d" -- if message is from yesterday or before and 6 hours has passed since midnight
else "%H:%M"
in styleTime $ formatTime defaultTimeLocale fmt localTime in styleTime $ formatTime defaultTimeLocale fmt localTime
recent :: CurrentTime -> TimeZone -> UTCTime -> Bool
recent now tz time = do
let localNow = utcToLocalTime tz now
localNowDay = localDay localNow
localTime = utcToLocalTime tz time
localTimeDay = localDay localTime
previousDay18 = LocalTime (addDays (-1) localNowDay) (TimeOfDay 18 0 0)
currentDay12 = LocalTime localNowDay (TimeOfDay 12 0 0)
localNowDay == localTimeDay
|| (localNow < currentDay12 && localTime >= previousDay18 && localTimeDay < localNowDay)
viewSentMessage :: StyledString -> [StyledString] -> MsgContent -> CurrentTime -> TimeZone -> CIMeta c d -> [StyledString] viewSentMessage :: StyledString -> [StyledString] -> MsgContent -> CurrentTime -> TimeZone -> CIMeta c d -> [StyledString]
viewSentMessage to quote mc ts tz meta@CIMeta {itemEdited, itemDeleted, itemLive} = sentWithTime_ ts tz (prependFirst to $ quote <> prependFirst (indent <> live) (ttyMsgContent mc)) meta viewSentMessage to quote mc ts tz meta@CIMeta {itemEdited, itemDeleted, itemLive} = sentWithTime_ ts tz (prependFirst to $ quote <> prependFirst (indent <> live) (ttyMsgContent mc)) meta
where where

View file

@ -8,6 +8,7 @@ import ProtocolTests
import SchemaDump import SchemaDump
import Test.Hspec import Test.Hspec
import UnliftIO.Temporary (withTempDirectory) import UnliftIO.Temporary (withTempDirectory)
import ViewTests
import WebRTCTests import WebRTCTests
main :: IO () main :: IO ()
@ -15,6 +16,7 @@ main = do
setLogLevel LogError -- LogDebug setLogLevel LogError -- LogDebug
withGlobalLogging logCfg . hspec $ do withGlobalLogging logCfg . hspec $ do
describe "SimpleX chat markdown" markdownTests describe "SimpleX chat markdown" markdownTests
describe "SimpleX chat view" viewTests
describe "SimpleX chat protocol" protocolTests describe "SimpleX chat protocol" protocolTests
describe "WebRTC encryption" webRTCTests describe "WebRTC encryption" webRTCTests
describe "Schema dump" schemaDumpTest describe "Schema dump" schemaDumpTest

86
tests/ViewTests.hs Normal file
View file

@ -0,0 +1,86 @@
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE OverloadedStrings #-}
module ViewTests where
import Data.Time
import Simplex.Chat.View
import Test.Hspec
viewTests :: Spec
viewTests = do
testRecent
testRecent :: Spec
testRecent = describe "recent" $ do
let tz = hoursToTimeZone 1
now1159 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 10 * 3600 + 59 * 60) -- 11:59 in tz
now1200 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 11 * 3600) -- 12:00 in tz
today0000 = UTCTime (fromGregorian 2023 6 6) (secondsToDiffTime $ 23 * 3600) -- 00:00 in tz
today0600 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 5 * 3600) -- 06:00 in tz
today1200 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 11 * 3600) -- 12:00 in tz
today1800 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 17 * 3600) -- 18:00 in tz
today2359 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 22 * 3600 + 59 * 60) -- 23:59 in tz
yesterday0000 = UTCTime (fromGregorian 2023 6 5) (secondsToDiffTime $ 23 * 3600) -- 00:00 in tz
yesterday1759 = UTCTime (fromGregorian 2023 6 6) (secondsToDiffTime $ 16 * 3600 + 59 * 60) -- 17:59 in tz
yesterday1800 = UTCTime (fromGregorian 2023 6 6) (secondsToDiffTime $ 17 * 3600) -- 18:00 in tz
yesterday2359 = UTCTime (fromGregorian 2023 6 6) (secondsToDiffTime $ 22 * 3600 + 59 * 60) -- 23:59 in tz
sameDayLastMonth1900 = UTCTime (fromGregorian 2023 5 7) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
prevDayLastMonth1900 = UTCTime (fromGregorian 2023 5 6) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
sameDayLastYear1900 = UTCTime (fromGregorian 2022 6 7) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
prevDayLastYear1900 = UTCTime (fromGregorian 2022 6 6) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
tomorrow0000 = UTCTime (fromGregorian 2023 6 7) (secondsToDiffTime $ 23 * 3600) -- 00:00 in tz
tomorrow1759 = UTCTime (fromGregorian 2023 6 8) (secondsToDiffTime $ 16 * 3600 + 59 * 60) -- 17:59 in tz
tomorrow1800 = UTCTime (fromGregorian 2023 6 8) (secondsToDiffTime $ 17 * 3600) -- 18:00 in tz
tomorrow2359 = UTCTime (fromGregorian 2023 6 8) (secondsToDiffTime $ 22 * 3600 + 59 * 60) -- 23:59 in tz
sameDayNextMonth1900 = UTCTime (fromGregorian 2023 7 7) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
prevDayNextMonth1900 = UTCTime (fromGregorian 2023 7 6) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
sameDayNextYear1900 = UTCTime (fromGregorian 2024 6 7) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
prevDayNextYear1900 = UTCTime (fromGregorian 2024 6 6) (secondsToDiffTime $ 18 * 3600) -- 19:00 in tz
test tz now1159 today0000 True
test tz now1159 today0600 True
test tz now1159 today1200 True
test tz now1159 today1800 True
test tz now1159 today2359 True
test tz now1159 yesterday0000 False
test tz now1159 yesterday1759 False
test tz now1159 yesterday1800 True
test tz now1159 yesterday2359 True
test tz now1159 sameDayLastMonth1900 False
test tz now1159 prevDayLastMonth1900 False
test tz now1159 sameDayLastYear1900 False
test tz now1159 prevDayLastYear1900 False
test tz now1159 tomorrow0000 False
test tz now1159 tomorrow1759 False
test tz now1159 tomorrow1800 False
test tz now1159 tomorrow2359 False
test tz now1159 sameDayNextMonth1900 False
test tz now1159 prevDayNextMonth1900 False
test tz now1159 sameDayNextYear1900 False
test tz now1159 prevDayNextYear1900 False
test tz now1200 today0000 True
test tz now1200 today0600 True
test tz now1200 today1200 True
test tz now1200 today1800 True
test tz now1200 today2359 True
test tz now1200 yesterday0000 False
test tz now1200 yesterday1759 False
test tz now1200 yesterday1800 False
test tz now1200 yesterday2359 False
test tz now1200 sameDayLastMonth1900 False
test tz now1200 prevDayLastMonth1900 False
test tz now1200 sameDayLastYear1900 False
test tz now1200 prevDayLastYear1900 False
test tz now1200 tomorrow0000 False
test tz now1200 tomorrow1759 False
test tz now1200 tomorrow1800 False
test tz now1200 tomorrow2359 False
test tz now1200 sameDayNextMonth1900 False
test tz now1200 prevDayNextMonth1900 False
test tz now1200 sameDayNextYear1900 False
test tz now1200 prevDayNextYear1900 False
where
test tz now time expected =
it ("returns " <> show expected <> " for time " <> show time <> " when time zone is " <> show tz <> " and current time is " <> show now) $
recent now tz time `shouldBe` expected