glirc-2.15: src/Client/View/Mentions.hs
{-# Language BangPatterns #-}
{-|
Module : Client.View.Mentions
Description : Mentions view
Copyright : (c) Eric Mertens, 2016
License : ISC
Maintainer : emertens@gmail.com
This module provides the lines that have been highlighted
across the client in sorted order.
-}
module Client.View.Mentions
( mentionsViewLines
) where
import Client.Image.Palette
import Client.State
import Client.State.Focus
import Client.State.Window
import qualified Data.Map as Map
import Control.Lens
import Data.Text (Text)
import Data.Time (UTCTime)
import Irc.Identifier (idText)
import Graphics.Vty.Image
-- | Generate the list of message lines marked important ordered by
-- time. Each run of lines from the same channel will be grouped
-- together. Messages are headed by their window, network, and channel.
mentionsViewLines :: ClientState -> [Image]
mentionsViewLines st = addMarkers pal entries
where
pal = clientPalette st
names = clientWindowNames st ++ repeat '?'
detail = view clientDetailView st
entries = merge
[windowEntries detail n net (idText chan) v
| (n,(ChannelFocus net chan, v))
<- names `zip` Map.toList (view clientWindows st) ]
data MentionLine = MentionLine
{ mlTimestamp :: UTCTime
, mlWindowName :: Char
, mlNetwork :: Text
, mlChannel :: Text
, mlImage :: Image
}
addMarkers ::
Palette {- ^ palette -} ->
[MentionLine] {- ^ list of mentions in time order -} ->
[Image] {- ^ mention images and channel labels -}
addMarkers _ [] = []
addMarkers !pal (!ml : xs) =
mlImage ml : map mlImage same ++ windowMarker : addMarkers pal rest
where
isSame ml' = mlWindowName ml == mlWindowName ml'
&& mlNetwork ml == mlNetwork ml'
&& mlChannel ml == mlChannel ml'
(same,rest) = span isSame xs
windowMarker = char (view palWindowName pal) (mlWindowName ml) <|>
char defAttr ':' <|>
text' (view palLabel pal) (mlNetwork ml) <|>
char defAttr ':' <|>
text' (view palLabel pal) (mlChannel ml)
windowEntries ::
Bool {- ^ detailed view -} ->
Char {- ^ window name -} ->
Text {- ^ network name -} ->
Text {- ^ channel name -} ->
Window {- ^ window -} ->
[MentionLine]
windowEntries !detailed name net chan w =
[ MentionLine
{ mlTimestamp = view wlTimestamp l
, mlWindowName = name
, mlNetwork = net
, mlChannel = chan
, mlImage = if detailed then view wlFullImage l else view wlImage l
}
| l <- view winMessages w
, WLImportant == view wlImportance l
]
-- | Merge a list of sorted lists of mention lines into a single sorted list
-- in descending order.
merge :: [[MentionLine]] -> [MentionLine]
merge [] = []
merge [x] = x
merge xss = merge (merge2s xss)
merge2s :: [[MentionLine]] -> [[MentionLine]]
merge2s (x:y:z) = merge2 x y : merge2s z
merge2s xs = xs
merge2 :: [MentionLine] -> [MentionLine] -> [MentionLine]
merge2 [] ys = ys
merge2 xs [] = xs
merge2 xxs@(x:xs) yys@(y:ys)
| mlTimestamp x >= mlTimestamp y = x : merge2 xs yys
| otherwise = y : merge2 xxs ys