Human readable time title attribute

This commit is contained in:
towards-a-new-leftypol 2024-02-14 11:40:25 -05:00
parent 9f9ee7d857
commit e2ce096289
4 changed files with 42 additions and 10 deletions

View File

@ -18,18 +18,19 @@ import Miso
import GHCJS.DOM.Types (JSString) import GHCJS.DOM.Types (JSString)
import Data.Foldable (toList) import Data.Foldable (toList)
import Miso.String (toMisoString) import Miso.String (toMisoString)
import Data.Time.Clock (UTCTime) import Data.Time.Clock (UTCTime, diffUTCTime)
import Data.Time.Format (formatTime, defaultTimeLocale) import Data.Time.Format (formatTime, defaultTimeLocale)
import Network.PostType (Post) import Network.PostType (Post)
import qualified Network.PostType as Post import qualified Network.PostType as Post
formatUTC :: UTCTime -> JSString formatUTC :: UTCTime -> JSString
formatUTC time = toMisoString $ formatUTC time = toMisoString $
formatTime defaultTimeLocale "%Y-%m-%d (%a) %T" time formatTime defaultTimeLocale "%Y-%m-%d (%a) %T" time
intro :: Post -> View a intro :: Post -> UTCTime -> View a
intro post = span_ intro post current_time = span_
[ class_ "intro" ] [ class_ "intro" ]
( subject ++ ( subject ++
[ " " [ " "
@ -40,7 +41,7 @@ intro post = span_
, time_ , time_
[ textProp "datetime" $ toMisoString $ show $ creation_time [ textProp "datetime" $ toMisoString $ show $ creation_time
, textProp "data-local" "true" , textProp "data-local" "true"
-- , title_ "14 days ago" , title_ $ toMisoString $ timeAgo current_time creation_time
][ text $ formatUTC creation_time ] ][ text $ formatUTC creation_time ]
, " " , " "
, a_ , a_
@ -68,3 +69,27 @@ intro post = span_
mkSubject s = span_ mkSubject s = span_
[ class_ "subject" ] [ class_ "subject" ]
[ text s ] [ text s ]
-- Convert UTCTime to a human-readable string
timeAgo :: UTCTime -> UTCTime -> String
timeAgo currentTime pastTime =
let diff = realToFrac $ diffUTCTime currentTime pastTime
in humanReadableTimeDiff diff
-- Helper function to correctly format singular and plural units
formatTimeUnit :: (Integral a, Show a) => a -> String -> String
formatTimeUnit value unit
| value == 1 = show value ++ " " ++ unit ++ " ago"
| otherwise = show value ++ " " ++ unit ++ "s ago"
-- Convert time difference in seconds to a human-readable format
humanReadableTimeDiff :: Double -> String
humanReadableTimeDiff diff
| diff < 60 = "Just now"
| diff < 3600 = formatTimeUnit (truncate (diff / 60) :: Int) "minute"
| diff < 86400 = formatTimeUnit (truncate (diff / 3600) :: Int) "hour"
| diff < 604800 = formatTimeUnit (truncate (diff / 86400) :: Int) "day"
| diff < 2592000 = formatTimeUnit (truncate (diff / 604800) :: Int) "week"
| diff < 31536000 = formatTimeUnit (truncate (diff / 2592000) :: Int) "month"
| otherwise = formatTimeUnit (truncate (diff / 31536000) :: Int) "year"

View File

@ -4,6 +4,7 @@ import GHCJS.DOM.Types (JSString)
import Network.SiteType (Site) import Network.SiteType (Site)
import Network.PostType (Post) import Network.PostType (Post)
import BodyParser (PostPart) import BodyParser (PostPart)
import Data.Time.Clock (UTCTime)
type PostWithBody = (Post, [ PostPart ]) type PostWithBody = (Post, [ PostPart ])
@ -11,5 +12,6 @@ data Model = Model
{ site :: Site { site :: Site
, media_root :: JSString , media_root :: JSString
, post_bodies :: [ PostWithBody ] , post_bodies :: [ PostWithBody ]
, current_time :: UTCTime
} deriving Eq } deriving Eq

View File

@ -27,6 +27,8 @@ import Miso
import Data.Text (Text) import Data.Text (Text)
import Miso.String (toMisoString) import Miso.String (toMisoString)
import GHCJS.DOM.Types (JSString) import GHCJS.DOM.Types (JSString)
import Data.Time.Clock (UTCTime (..), secondsToDiffTime, getCurrentTime)
import Data.Time.Calendar (Day (..))
import Network.SiteType (Site) import Network.SiteType (Site)
import qualified Network.SiteType as Site import qualified Network.SiteType as Site
@ -45,11 +47,12 @@ initialModel mroot s = Model
{ site = s { site = s
, post_bodies = [] , post_bodies = []
, media_root = mroot , media_root = mroot
, current_time = UTCTime (ModifiedJulianDay 0) (secondsToDiffTime 0)
} }
data Action data Action
= RenderSite Site = RenderSite Site
| UpdatePostBodies [ PostWithBody ] | UpdatePostBodies UTCTime [ PostWithBody ]
data Interface a = Interface { passAction :: Action -> a } data Interface a = Interface { passAction :: Action -> a }
@ -59,7 +62,9 @@ update iface (RenderSite s) m = m { site = s } <# do
mapM_ (consoleLog . toMisoString . show) bodies mapM_ (consoleLog . toMisoString . show) bodies
return $ passAction iface $ UpdatePostBodies $ zip posts bodies now <- getCurrentTime
return $ passAction iface $ UpdatePostBodies now $ zip posts bodies
where where
getBody :: Maybe Text -> IO [ PostPart ] getBody :: Maybe Text -> IO [ PostPart ]
@ -70,7 +75,7 @@ update iface (RenderSite s) m = m { site = s } <# do
posts = Thread.posts $ head $ Board.threads $ head $ Site.boards s posts = Thread.posts $ head $ Board.threads $ head $ Site.boards s
--update (RenderSite s) m = noEff (m { site = s }) --update (RenderSite s) m = noEff (m { site = s })
update _ (UpdatePostBodies pwbs) m = noEff m { post_bodies = pwbs } update _ (UpdatePostBodies t pwbs) m = noEff m { post_bodies = pwbs, current_time = t }
view :: Model -> View a view :: Model -> View a
@ -113,7 +118,7 @@ op m op_post =
, id_ $ toMisoString $ show $ Post.board_post_id op_post , id_ $ toMisoString $ show $ Post.board_post_id op_post
] ++ multi op_post ] ++ multi op_post
) )
[ intro op_post [ intro op_post $ current_time m
, div_ , div_
[ class_ "body" ] [ class_ "body" ]
(body $ post_bodies m) (body $ post_bodies m)
@ -145,7 +150,7 @@ reply m (post, parts) = div_
[ class_ "post reply" [ class_ "post reply"
] ++ multi post ] ++ multi post
) )
[ intro post [ intro post $ current_time m
, files (media_root m) (site m) post , files (media_root m) (site m) post
, div_ , div_
[ class_ "body" ] [ class_ "body" ]

View File

@ -183,7 +183,7 @@ mainUpdate (HaveThread (Client.HttpResponse {..})) m = new_model <# do
where where
new_model = m new_model = m
{ thread_model = { thread_model =
body >>= Just . (Thread.initialModel (media_root_ m)) . head body >>= Just . (Thread.initialModel $ media_root_ m) . head
} }
mainUpdate GetLatest m = m <# Client.fetchLatest (client_model m) (iClient HaveLatest) mainUpdate GetLatest m = m <# Client.fetchLatest (client_model m) (iClient HaveLatest)