{-# LANGUAGE RankNTypes #-}
module Matterhorn.State.ListWindow
  ( listWindowActivateCurrent
  , listWindowActivate
  , listWindowSearchString
  , listWindowMove
  , exitListWindow
  , enterListWindowMode
  , resetListWindowSearch
  , onEventListWindow
  )
where

import           Prelude ()
import           Matterhorn.Prelude

import           Brick ( BrickEvent(VtyEvent) )
import qualified Brick.Widgets.List as L
import qualified Brick.Widgets.Edit as E
import qualified Data.Text.Zipper as Z
import qualified Data.Vector as Vec
import           Lens.Micro.Platform ( Lens', (%=), (.=) )
import           Network.Mattermost.Types ( Session, TeamId )
import qualified Graphics.Vty as Vty

import           Matterhorn.Types
import           Brick.Keybindings
import           Matterhorn.State.Common
import           Matterhorn.State.Editing ( editingKeybindings )


-- | Activate the specified list window's selected item by invoking the
-- window's configured enter keypress handler function.
listWindowActivateCurrent :: TeamId -> Lens' ChatState (ListWindowState a b) -> MH ()
listWindowActivateCurrent :: forall a b.
TeamId -> Lens' ChatState (ListWindowState a b) -> MH ()
listWindowActivateCurrent TeamId
tId Lens' ChatState (ListWindowState a b)
which = do
  Maybe (Int, a)
mItem <- GenericList Name Vector a -> Maybe (Int, a)
forall (t :: * -> *) e n.
(Splittable t, Traversable t, Semigroup (t e)) =>
GenericList n t e -> Maybe (Int, e)
L.listSelectedElement (GenericList Name Vector a -> Maybe (Int, a))
-> MH (GenericList Name Vector a) -> MH (Maybe (Int, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting
  (GenericList Name Vector a) ChatState (GenericList Name Vector a)
-> MH (GenericList Name Vector a)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const (GenericList Name Vector a) (ListWindowState a b))
-> ChatState -> Const (GenericList Name Vector a) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (GenericList Name Vector a) (ListWindowState a b))
 -> ChatState -> Const (GenericList Name Vector a) ChatState)
-> ((GenericList Name Vector a
     -> Const (GenericList Name Vector a) (GenericList Name Vector a))
    -> ListWindowState a b
    -> Const (GenericList Name Vector a) (ListWindowState a b))
-> Getting
     (GenericList Name Vector a) ChatState (GenericList Name Vector a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(GenericList Name Vector a
 -> Const (GenericList Name Vector a) (GenericList Name Vector a))
-> ListWindowState a b
-> Const (GenericList Name Vector a) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(List Name a -> f (List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchResults)
  case Maybe (Int, a)
mItem of
      Maybe (Int, a)
Nothing -> () -> MH ()
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      Just (Int
_, a
val) -> TeamId -> Lens' ChatState (ListWindowState a b) -> a -> MH ()
forall a b.
TeamId -> Lens' ChatState (ListWindowState a b) -> a -> MH ()
listWindowActivate TeamId
tId (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which a
val

-- | Activate the specified list window's selected item by invoking the
-- window's configured enter keypress handler function.
listWindowActivate :: TeamId -> Lens' ChatState (ListWindowState a b) -> a -> MH ()
listWindowActivate :: forall a b.
TeamId -> Lens' ChatState (ListWindowState a b) -> a -> MH ()
listWindowActivate TeamId
tId Lens' ChatState (ListWindowState a b)
which a
val = do
    a -> MH Bool
handler <- Getting (a -> MH Bool) ChatState (a -> MH Bool)
-> MH (a -> MH Bool)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b -> Const (a -> MH Bool) (ListWindowState a b))
-> ChatState -> Const (a -> MH Bool) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (a -> MH Bool) (ListWindowState a b))
 -> ChatState -> Const (a -> MH Bool) ChatState)
-> (((a -> MH Bool) -> Const (a -> MH Bool) (a -> MH Bool))
    -> ListWindowState a b
    -> Const (a -> MH Bool) (ListWindowState a b))
-> Getting (a -> MH Bool) ChatState (a -> MH Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((a -> MH Bool) -> Const (a -> MH Bool) (a -> MH Bool))
-> ListWindowState a b
-> Const (a -> MH Bool) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((a -> MH Bool) -> f (a -> MH Bool))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowEnterHandler)
    Bool
activated <- a -> MH Bool
handler a
val
    if Bool
activated
       then TeamId -> MH ()
popMode TeamId
tId
       else () -> MH ()
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | Get the current search string for the specified window.
listWindowSearchString :: Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString :: forall a b. Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString Lens' ChatState (ListWindowState a b)
which =
    ([Text] -> Text
forall a. HasCallStack => [a] -> a
head ([Text] -> Text)
-> (Editor Text Name -> [Text]) -> Editor Text Name -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Editor Text Name -> [Text]
forall t n. Monoid t => Editor t n -> [t]
E.getEditContents) (Editor Text Name -> Text) -> MH (Editor Text Name) -> MH Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Getting (Editor Text Name) ChatState (Editor Text Name)
-> MH (Editor Text Name)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const (Editor Text Name) (ListWindowState a b))
-> ChatState -> Const (Editor Text Name) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (Editor Text Name) (ListWindowState a b))
 -> ChatState -> Const (Editor Text Name) ChatState)
-> ((Editor Text Name
     -> Const (Editor Text Name) (Editor Text Name))
    -> ListWindowState a b
    -> Const (Editor Text Name) (ListWindowState a b))
-> Getting (Editor Text Name) ChatState (Editor Text Name)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Editor Text Name -> Const (Editor Text Name) (Editor Text Name))
-> ListWindowState a b
-> Const (Editor Text Name) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchInput)

-- | Move the list cursor in the specified window.
listWindowMove :: Lens' ChatState (ListWindowState a b)
                -- ^ Which window
                -> (L.List Name a -> L.List Name a)
                -- ^ How to transform the list in the window
                -> MH ()
listWindowMove :: forall a b.
Lens' ChatState (ListWindowState a b)
-> (List Name a -> List Name a) -> MH ()
listWindowMove Lens' ChatState (ListWindowState a b)
which List Name a -> List Name a
how = (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (List Name a -> Identity (List Name a))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(List Name a -> Identity (List Name a))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(List Name a -> f (List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchResults ((List Name a -> Identity (List Name a))
 -> ChatState -> Identity ChatState)
-> (List Name a -> List Name a) -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= List Name a -> List Name a
how

-- | Clear the state of the specified list window and return to the
-- Main mode.
exitListWindow :: TeamId
                -> Lens' ChatState (ListWindowState a b)
                -- ^ Which window to reset
                -> MH ()
exitListWindow :: forall a b.
TeamId -> Lens' ChatState (ListWindowState a b) -> MH ()
exitListWindow TeamId
tId Lens' ChatState (ListWindowState a b)
which = do
    Vector a -> List Name a
newList <- Getting
  (Vector a -> List Name a) ChatState (Vector a -> List Name a)
-> MH (Vector a -> List Name a)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const (Vector a -> List Name a) (ListWindowState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (Vector a -> List Name a) (ListWindowState a b))
 -> ChatState -> Const (Vector a -> List Name a) ChatState)
-> (((Vector a -> List Name a)
     -> Const (Vector a -> List Name a) (Vector a -> List Name a))
    -> ListWindowState a b
    -> Const (Vector a -> List Name a) (ListWindowState a b))
-> Getting
     (Vector a -> List Name a) ChatState (Vector a -> List Name a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((Vector a -> List Name a)
 -> Const (Vector a -> List Name a) (Vector a -> List Name a))
-> ListWindowState a b
-> Const (Vector a -> List Name a) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((Vector a -> List Name a) -> f (Vector a -> List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowNewList)
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (List Name a -> Identity (List Name a))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(List Name a -> Identity (List Name a))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(List Name a -> f (List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchResults ((List Name a -> Identity (List Name a))
 -> ChatState -> Identity ChatState)
-> List Name a -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Vector a -> List Name a
newList Vector a
forall a. Monoid a => a
mempty
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> (((a -> MH Bool) -> Identity (a -> MH Bool))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> ((a -> MH Bool) -> Identity (a -> MH Bool))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((a -> MH Bool) -> Identity (a -> MH Bool))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((a -> MH Bool) -> f (a -> MH Bool))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowEnterHandler (((a -> MH Bool) -> Identity (a -> MH Bool))
 -> ChatState -> Identity ChatState)
-> (a -> MH Bool) -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= (MH Bool -> a -> MH Bool
forall a b. a -> b -> a
const (MH Bool -> a -> MH Bool) -> MH Bool -> a -> MH Bool
forall a b. (a -> b) -> a -> b
$ Bool -> MH Bool
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False)
    TeamId -> MH ()
popMode TeamId
tId

-- | Initialize a list window with the specified arguments and switch
-- to the specified mode.
enterListWindowMode :: TeamId
                     -> (Lens' ChatState (ListWindowState a b))
                     -- ^ Which window to initialize
                     -> Mode
                     -- ^ The mode to change to
                     -> b
                     -- ^ The window's initial search scope
                     -> (a -> MH Bool)
                     -- ^ The window's enter keypress handler
                     -> (b -> Session -> Text -> IO (Vec.Vector a))
                     -- ^ The window's results fetcher function
                     -> MH ()
enterListWindowMode :: forall a b.
TeamId
-> Lens' ChatState (ListWindowState a b)
-> Mode
-> b
-> (a -> MH Bool)
-> (b -> Session -> Text -> IO (Vector a))
-> MH ()
enterListWindowMode TeamId
tId Lens' ChatState (ListWindowState a b)
which Mode
mode b
scope a -> MH Bool
enterHandler b -> Session -> Text -> IO (Vector a)
fetcher = do
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((b -> Identity b)
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (b -> Identity b)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(b -> Identity b)
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(b -> f b) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchScope ((b -> Identity b) -> ChatState -> Identity ChatState)
-> b -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= b
scope
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((TextZipper Text -> Identity (TextZipper Text))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (TextZipper Text -> Identity (TextZipper Text))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Editor Text Name -> Identity (Editor Text Name))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchInput((Editor Text Name -> Identity (Editor Text Name))
 -> ListWindowState a b -> Identity (ListWindowState a b))
-> ((TextZipper Text -> Identity (TextZipper Text))
    -> Editor Text Name -> Identity (Editor Text Name))
-> (TextZipper Text -> Identity (TextZipper Text))
-> ListWindowState a b
-> Identity (ListWindowState a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(TextZipper Text -> Identity (TextZipper Text))
-> Editor Text Name -> Identity (Editor Text Name)
forall t1 n t2 (f :: * -> *).
Functor f =>
(TextZipper t1 -> f (TextZipper t2))
-> Editor t1 n -> f (Editor t2 n)
E.editContentsL ((TextZipper Text -> Identity (TextZipper Text))
 -> ChatState -> Identity ChatState)
-> (TextZipper Text -> TextZipper Text) -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= TextZipper Text -> TextZipper Text
forall a. Monoid a => TextZipper a -> TextZipper a
Z.clearZipper
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> (((a -> MH Bool) -> Identity (a -> MH Bool))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> ((a -> MH Bool) -> Identity (a -> MH Bool))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((a -> MH Bool) -> Identity (a -> MH Bool))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((a -> MH Bool) -> f (a -> MH Bool))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowEnterHandler (((a -> MH Bool) -> Identity (a -> MH Bool))
 -> ChatState -> Identity ChatState)
-> (a -> MH Bool) -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= a -> MH Bool
enterHandler
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> (((b -> Session -> Text -> IO (Vector a))
     -> Identity (b -> Session -> Text -> IO (Vector a)))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> ((b -> Session -> Text -> IO (Vector a))
    -> Identity (b -> Session -> Text -> IO (Vector a)))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((b -> Session -> Text -> IO (Vector a))
 -> Identity (b -> Session -> Text -> IO (Vector a)))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((b -> Session -> Text -> IO (Vector a))
 -> f (b -> Session -> Text -> IO (Vector a)))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowFetchResults (((b -> Session -> Text -> IO (Vector a))
  -> Identity (b -> Session -> Text -> IO (Vector a)))
 -> ChatState -> Identity ChatState)
-> (b -> Session -> Text -> IO (Vector a)) -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= b -> Session -> Text -> IO (Vector a)
fetcher
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearching ((Bool -> Identity Bool) -> ChatState -> Identity ChatState)
-> Bool -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False
    Vector a -> List Name a
newList <- Getting
  (Vector a -> List Name a) ChatState (Vector a -> List Name a)
-> MH (Vector a -> List Name a)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const (Vector a -> List Name a) (ListWindowState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (Vector a -> List Name a) (ListWindowState a b))
 -> ChatState -> Const (Vector a -> List Name a) ChatState)
-> (((Vector a -> List Name a)
     -> Const (Vector a -> List Name a) (Vector a -> List Name a))
    -> ListWindowState a b
    -> Const (Vector a -> List Name a) (ListWindowState a b))
-> Getting
     (Vector a -> List Name a) ChatState (Vector a -> List Name a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((Vector a -> List Name a)
 -> Const (Vector a -> List Name a) (Vector a -> List Name a))
-> ListWindowState a b
-> Const (Vector a -> List Name a) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((Vector a -> List Name a) -> f (Vector a -> List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowNewList)
    (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (List Name a -> Identity (List Name a))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(List Name a -> Identity (List Name a))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(List Name a -> f (List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchResults ((List Name a -> Identity (List Name a))
 -> ChatState -> Identity ChatState)
-> List Name a -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Vector a -> List Name a
newList Vector a
forall a. Monoid a => a
mempty
    TeamId -> Mode -> MH ()
pushMode TeamId
tId Mode
mode
    Lens' ChatState (ListWindowState a b) -> MH ()
forall a b. Lens' ChatState (ListWindowState a b) -> MH ()
resetListWindowSearch (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which

-- | Reset the window's search by initiating a new search request for
-- the string that is currently in the window's editor. This does
-- nothing if a search for this window is already in progress.
resetListWindowSearch :: Lens' ChatState (ListWindowState a b) -> MH ()
resetListWindowSearch :: forall a b. Lens' ChatState (ListWindowState a b) -> MH ()
resetListWindowSearch Lens' ChatState (ListWindowState a b)
which = do
    Bool
searchPending <- Getting Bool ChatState Bool -> MH Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b -> Const Bool (ListWindowState a b))
-> ChatState -> Const Bool ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Const Bool (ListWindowState a b))
 -> ChatState -> Const Bool ChatState)
-> ((Bool -> Const Bool Bool)
    -> ListWindowState a b -> Const Bool (ListWindowState a b))
-> Getting Bool ChatState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Const Bool Bool)
-> ListWindowState a b -> Const Bool (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearching)

    Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
searchPending) (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$ do
        Text
searchString <- Lens' ChatState (ListWindowState a b) -> MH Text
forall a b. Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which
        (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearching ((Bool -> Identity Bool) -> ChatState -> Identity ChatState)
-> Bool -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
True
        Vector a -> List Name a
newList <- Getting
  (Vector a -> List Name a) ChatState (Vector a -> List Name a)
-> MH (Vector a -> List Name a)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const (Vector a -> List Name a) (ListWindowState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const (Vector a -> List Name a) (ListWindowState a b))
 -> ChatState -> Const (Vector a -> List Name a) ChatState)
-> (((Vector a -> List Name a)
     -> Const (Vector a -> List Name a) (Vector a -> List Name a))
    -> ListWindowState a b
    -> Const (Vector a -> List Name a) (ListWindowState a b))
-> Getting
     (Vector a -> List Name a) ChatState (Vector a -> List Name a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((Vector a -> List Name a)
 -> Const (Vector a -> List Name a) (Vector a -> List Name a))
-> ListWindowState a b
-> Const (Vector a -> List Name a) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((Vector a -> List Name a) -> f (Vector a -> List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowNewList)
        Session
session <- MH Session
getSession
        b
scope <- Getting b ChatState b -> MH b
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b -> Const b (ListWindowState a b))
-> ChatState -> Const b ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Const b (ListWindowState a b))
 -> ChatState -> Const b ChatState)
-> ((b -> Const b b)
    -> ListWindowState a b -> Const b (ListWindowState a b))
-> Getting b ChatState b
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(b -> Const b b)
-> ListWindowState a b -> Const b (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(b -> f b) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchScope)
        b -> Session -> Text -> IO (Vector a)
fetcher <- Getting
  (b -> Session -> Text -> IO (Vector a))
  ChatState
  (b -> Session -> Text -> IO (Vector a))
-> MH (b -> Session -> Text -> IO (Vector a))
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ListWindowState a b
 -> Const
      (b -> Session -> Text -> IO (Vector a)) (ListWindowState a b))
-> ChatState
-> Const (b -> Session -> Text -> IO (Vector a)) ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b
  -> Const
       (b -> Session -> Text -> IO (Vector a)) (ListWindowState a b))
 -> ChatState
 -> Const (b -> Session -> Text -> IO (Vector a)) ChatState)
-> (((b -> Session -> Text -> IO (Vector a))
     -> Const
          (b -> Session -> Text -> IO (Vector a))
          (b -> Session -> Text -> IO (Vector a)))
    -> ListWindowState a b
    -> Const
         (b -> Session -> Text -> IO (Vector a)) (ListWindowState a b))
-> Getting
     (b -> Session -> Text -> IO (Vector a))
     ChatState
     (b -> Session -> Text -> IO (Vector a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((b -> Session -> Text -> IO (Vector a))
 -> Const
      (b -> Session -> Text -> IO (Vector a))
      (b -> Session -> Text -> IO (Vector a)))
-> ListWindowState a b
-> Const
     (b -> Session -> Text -> IO (Vector a)) (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
((b -> Session -> Text -> IO (Vector a))
 -> f (b -> Session -> Text -> IO (Vector a)))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowFetchResults)
        AsyncPriority -> IO (Maybe (MH ())) -> MH ()
doAsyncWith AsyncPriority
Preempt (IO (Maybe (MH ())) -> MH ()) -> IO (Maybe (MH ())) -> MH ()
forall a b. (a -> b) -> a -> b
$ do
            Vector a
results <- b -> Session -> Text -> IO (Vector a)
fetcher b
scope Session
session Text
searchString
            Maybe (MH ()) -> IO (Maybe (MH ()))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (MH ()) -> IO (Maybe (MH ())))
-> Maybe (MH ()) -> IO (Maybe (MH ()))
forall a b. (a -> b) -> a -> b
$ MH () -> Maybe (MH ())
forall a. a -> Maybe a
Just (MH () -> Maybe (MH ())) -> MH () -> Maybe (MH ())
forall a b. (a -> b) -> a -> b
$ do
                (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (List Name a -> Identity (List Name a))
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(List Name a -> Identity (List Name a))
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(List Name a -> f (List Name a))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchResults ((List Name a -> Identity (List Name a))
 -> ChatState -> Identity ChatState)
-> List Name a -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Vector a -> List Name a
newList Vector a
results
                (ListWindowState a b -> Identity (ListWindowState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> Identity (ListWindowState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListWindowState a b -> Identity (ListWindowState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListWindowState a b -> Identity (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> ListWindowState a b -> f (ListWindowState a b)
listWindowSearching ((Bool -> Identity Bool) -> ChatState -> Identity ChatState)
-> Bool -> MH ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
False

                -- Now that the results are available, check to see if the
                -- search string changed since this request was submitted.
                -- If so, issue another search.
                Text
afterSearchString <- Lens' ChatState (ListWindowState a b) -> MH Text
forall a b. Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which
                Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text
searchString Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
afterSearchString) (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$ Lens' ChatState (ListWindowState a b) -> MH ()
forall a b. Lens' ChatState (ListWindowState a b) -> MH ()
resetListWindowSearch (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which

-- | Generically handle an event for the list window state targeted
-- by the specified lens. Automatically dispatches new searches in the
-- window's editor if the editor contents change.
onEventListWindow :: Lens' ChatState (ListWindowState a b)
                   -- ^ Which window to dispatch to?
                   -> (KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH)
                   -- ^ The keybinding builder
                   -> Vty.Event
                   -- ^ The event
                   -> MH Bool
onEventListWindow :: forall a b.
Lens' ChatState (ListWindowState a b)
-> (KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH)
-> Event
-> MH Bool
onEventListWindow Lens' ChatState (ListWindowState a b)
which KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH
keybindings =
    [Event -> MH Bool] -> Event -> MH Bool
handleEventWith [ (KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH)
-> Event -> MH Bool
mhHandleKeyboardEvent KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH
keybindings
                    , Lens' ChatState (ListWindowState a b) -> Event -> MH Bool
forall a b.
Lens' ChatState (ListWindowState a b) -> Event -> MH Bool
handleEditorEvent (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which
                    ]

handleEditorEvent :: Lens' ChatState (ListWindowState a b) -> Vty.Event -> MH Bool
handleEditorEvent :: forall a b.
Lens' ChatState (ListWindowState a b) -> Event -> MH Bool
handleEditorEvent Lens' ChatState (ListWindowState a b)
which Event
e = do
    -- Get the editor content before the event.
    Text
before <- Lens' ChatState (ListWindowState a b) -> MH Text
forall a b. Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which

    -- First find a matching keybinding in the keybinding list.
    Bool
handled <- (KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH)
-> Event -> MH Bool
mhHandleKeyboardEvent (Lens' ChatState (Editor Text Name)
-> KeyConfig KeyEvent -> KeyDispatcher KeyEvent MH
editingKeybindings ((ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> f (ListWindowState a b))
 -> ChatState -> f ChatState)
-> ((Editor Text Name -> f (Editor Text Name))
    -> ListWindowState a b -> f (ListWindowState a b))
-> (Editor Text Name -> f (Editor Text Name))
-> ChatState
-> f ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchInput)) Event
e

    -- If we didn't find a matching binding, just handle the event as a
    -- normal editor input event.
    Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
handled) (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$
        Lens' ChatState (Editor Text Name)
-> (BrickEvent Name Any -> EventM Name (Editor Text Name) ())
-> BrickEvent Name Any
-> MH ()
forall b e.
Lens' ChatState b -> (e -> EventM Name b ()) -> e -> MH ()
mhZoom ((ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which((ListWindowState a b -> f (ListWindowState a b))
 -> ChatState -> f ChatState)
-> ((Editor Text Name -> f (Editor Text Name))
    -> ListWindowState a b -> f (ListWindowState a b))
-> (Editor Text Name -> f (Editor Text Name))
-> ChatState
-> f ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
forall a b (f :: * -> *).
Functor f =>
(Editor Text Name -> f (Editor Text Name))
-> ListWindowState a b -> f (ListWindowState a b)
listWindowSearchInput) BrickEvent Name Any -> EventM Name (Editor Text Name) ()
forall n t e.
(Eq n, DecodeUtf8 t, Eq t, GenericTextZipper t) =>
BrickEvent n e -> EventM n (Editor t n) ()
E.handleEditorEvent (Event -> BrickEvent Name Any
forall n e. Event -> BrickEvent n e
VtyEvent Event
e)

    -- Get the editor content after the event. If the string changed,
    -- start a new search.
    Text
after <- Lens' ChatState (ListWindowState a b) -> MH Text
forall a b. Lens' ChatState (ListWindowState a b) -> MH Text
listWindowSearchString (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which
    Bool -> MH () -> MH ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text
before Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
after) (MH () -> MH ()) -> MH () -> MH ()
forall a b. (a -> b) -> a -> b
$ Lens' ChatState (ListWindowState a b) -> MH ()
forall a b. Lens' ChatState (ListWindowState a b) -> MH ()
resetListWindowSearch (ListWindowState a b -> f (ListWindowState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListWindowState a b)
which

    Bool -> MH Bool
forall a. a -> MH a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True