glirc-2.40: src/Client/View/Who.hs
{-# Language OverloadedStrings #-}
{-|
Module : Client.View.Who
Description : Line renderer for /who replies
Copyright : (c) TheDaemoness, 2023
License : ISC
Maintainer : emertens@gmail.com
This module renders the lines used in /who replies.
-}
module Client.View.Who ( whoLines ) where
import Client.Image.LineWrap (lineWrapPrefix)
import Client.Image.Message (IdentifierColorMode(NormalIdentifier), coloredIdentifier, coloredUserInfo, RenderMode (DetailedRender), prettyTime)
import Client.Image.PackedImage
import Client.Image.Palette
import Client.State
import Client.State.Network
import Client.WhoReply
import Control.Lens
import Data.Text (Text)
import qualified Data.Text as Text
import Graphics.Vty.Attributes (defAttr)
import Irc.Identifier
import qualified Data.HashMap.Strict as HashMap
import Client.Image.MircFormatting (parseIrcText')
import Client.State.Focus (Focus(NetworkFocus))
-- |
-- | Render the lines used by the @/who@ command in normal mode.
whoLines ::
Text {- ^ network -} ->
Int {- ^ window width -} ->
ClientState {- ^ client state -} ->
[Image']
whoLines network width st =
-- TODO: This pattern exists in a few other views. Maybe deduplicate?
case preview (clientConnection network) st of
Just cs -> whoLines' cs width st
Nothing -> [text' (view palError pal) "No connection"]
where
pal = clientPalette st
whoLines' :: NetworkState -> Int -> ClientState -> [Image']
whoLines' cs width st
| Text.null $ view (csWhoReply . whoQuery . _1) cs = [text' (view palError pal) "No previous WHO query"]
| whorpl^.whoDone = countImage <> queryPart : images
| otherwise = countImagePending <> queryPart : images
where
pal = clientPalette st
whorpl = view csWhoReply cs
(query, arg) = view whoQuery whorpl
entries = view whoItems whorpl
entries' = clientFilter st whoFilterText entries
images = concatMap renderEntry entries'
renderEntry :: WhoReplyItem -> [Image']
renderEntry entry = reverse $ lineWrapPrefix width (renderPrefix entry) (renderSuffix entry)
-- Skipping rendering the channel because it doesn't add anything most of the time.
renderPrefix entry = coloredUserInfo pal DetailedRender hilites (view whoUserInfo entry)
where hilites = clientHighlightsFocus (NetworkFocus (view csNetwork cs)) st
renderSuffix :: WhoReplyItem -> Image'
renderSuffix entry = mconcat $ mapJoinWhoFields entry
(const mempty)
(label "$a:" . identifier)
(label "ip: " . text' defAttr)
(label "server: " . identifier)
(label "away" $ text' defAttr "")
(label "flags: " . text' (view palSigil pal))
(label "hops: " . string defAttr . show)
(label "idle: " . string defAttr . prettyTime 1)
(label "oplvl: " . text' defAttr)
(label "gecos: " . parseIrcText' False pal)
countImagePending = countImage <> text' (view palLabel pal) "..."
countImage = text' (view palLabel pal) "Users in " <>
coloredIdentifier pal NormalIdentifier HashMap.empty (mkId query) <>
text' (view palLabel pal) " (visible/total): " <>
string defAttr (show (length entries')) <>
char (view palLabel pal) '/' <>
string defAttr (show (length entries))
queryPart = case arg of
Just txt | not (Text.null txt) -> label " Options: " $ text' defAttr txt
_ -> text' defAttr ""
label txt image = text' (view palLabel pal) txt <> image <> text' defAttr " "
-- Don't use hilites here; the identifiers are never the user's nick.
identifier = coloredIdentifier pal NormalIdentifier HashMap.empty