module Matterhorn.Draw.Util ( withBrackets , renderTime , renderDate , renderKeybindingHelp , insertDateMarkers , getDateFormat , mkChannelName , userSigilFromInfo , multilineHeightLimit , keyEventBindings ) where import Prelude () import Matterhorn.Prelude import Brick import Brick.Keybindings import Data.List ( intersperse ) import qualified Data.Set as Set import qualified Data.Text as T import Network.Mattermost.Types import Matterhorn.Constants ( userSigil, normalChannelSigil ) import Matterhorn.Themes import Matterhorn.TimeUtils import Matterhorn.Types defaultTimeFormat :: Text defaultTimeFormat = "%R" defaultDateFormat :: Text defaultDateFormat = "%Y-%m-%d" multilineHeightLimit :: Int multilineHeightLimit = 5 getTimeFormat :: ChatState -> Text getTimeFormat st = maybe defaultTimeFormat id (st^.csResources.crConfiguration.configTimeFormatL) getDateFormat :: ChatState -> Text getDateFormat st = maybe defaultDateFormat id (st^.csResources.crConfiguration.configDateFormatL) renderTime :: ChatState -> UTCTime -> Widget Name renderTime st = renderUTCTime (getTimeFormat st) (st^.timeZone) renderDate :: ChatState -> UTCTime -> Widget Name renderDate st = renderUTCTime (getDateFormat st) (st^.timeZone) renderUTCTime :: Text -> TimeZoneSeries -> UTCTime -> Widget a renderUTCTime fmt tz t = if T.null fmt then emptyWidget else withDefAttr timeAttr (txt $ localTimeText fmt $ asLocalTime tz t) renderKeybindingHelp :: ChatState -> Text -> [KeyEvent] -> Widget Name renderKeybindingHelp st label evs = let ppEv ev = withDefAttr clientEmphAttr $ txt (ppMaybeBinding (firstActiveBinding kc ev)) kc = st^.csResources.crConfiguration.configUserKeysL in hBox $ (intersperse (txt "/") $ ppEv <$> evs) <> [txt (":" <> label)] -- | Modifies a message sequence by inserting date transition markers -- in between messages with different creation dates. Server dates from -- messages are converted to local time (via the current timezone) -- and midnight of that timezone used to generate date markers. insertDateMarkers :: Messages -> Text -> TimeZoneSeries -> Messages insertDateMarkers ms datefmt tz = foldr (addMessage . dateMsg) ms dateRange where dateRange = foldr checkDateChange Set.empty ms checkDateChange m = let msgDay = startOfDay (Just tz) (withServerTime (m^.mDate)) in if m^.mDeleted then id else Set.insert msgDay dateMsg d = let t = localTimeText datefmt $ asLocalTime tz d in newMessageOfType t (C DateTransition) (ServerTime d) withBrackets :: Widget a -> Widget a withBrackets w = hBox [str "[", w, str "]"] userSigilFromInfo :: UserInfo -> Char userSigilFromInfo u = case u^.uiStatus of Offline -> ' ' Online -> '+' Away -> '-' DoNotDisturb -> '×' Other _ -> '?' mkChannelName :: ChatState -> ChannelInfo -> Text mkChannelName st c = T.append sigil t where t = case c^.cdDMUserId >>= flip userById st of Nothing -> c^.cdName Just u -> u^.uiName sigil = case c^.cdType of Private -> mempty Ordinary -> normalChannelSigil Group -> mempty Direct -> userSigil Unknown _ -> mempty -- | Resolve the specified key event into a pretty-printed -- representation of the active bindings for that event, using the -- specified key handler map builder. If the event has more than one -- active binding, the bindings are comma-delimited in the resulting -- string. keyEventBindings :: ChatState -- ^ The current application state -> (KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH) -- ^ The function to obtain the relevant key handler -- map -> KeyEvent -- ^ The key event to look up -> T.Text keyEventBindings st mkBindingsMap e = let keyconf = st^.csResources.crConfiguration.configUserKeysL keymap = mkBindingsMap keyconf in T.intercalate "," [ ppBinding b | KeyHandler { khBinding = b , khHandler = h } <- snd <$> keyDispatcherToList keymap , kehEventTrigger h == ByEvent e ]