{-# LANGUAGE RankNTypes #-}
module Matterhorn.State.ListOverlay
  ( listOverlayActivateCurrent
  , listOverlayActivate
  , listOverlaySearchString
  , listOverlayMove
  , exitListOverlay
  , enterListOverlayMode
  , resetListOverlaySearch
  , onEventListOverlay
  )
where

import           Prelude ()
import           Matterhorn.Prelude

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 )
import qualified Graphics.Vty as Vty

import           Matterhorn.Types
import           Matterhorn.State.Common
import           Matterhorn.State.Editing ( editingKeybindings )
import           Matterhorn.Events.Keybindings ( KeyConfig, KeyHandlerMap, handleKeyboardEvent )


-- | Activate the specified list overlay's selected item by invoking the
-- overlay's configured enter keypress handler function.
listOverlayActivateCurrent :: Lens' ChatState (ListOverlayState a b) -> MH ()
listOverlayActivateCurrent :: Lens' ChatState (ListOverlayState a b) -> MH ()
listOverlayActivateCurrent Lens' ChatState (ListOverlayState a b)
which = do
  Maybe (Int, a)
mItem <- GenericList Name Vector a -> Maybe (Int, a)
forall (t :: * -> *) n e.
(Splittable t, Foldable t) =>
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 ((ListOverlayState a b
 -> Const (GenericList Name Vector a) (ListOverlayState a b))
-> ChatState -> Const (GenericList Name Vector a) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (GenericList Name Vector a) (ListOverlayState a b))
 -> ChatState -> Const (GenericList Name Vector a) ChatState)
-> ((GenericList Name Vector a
     -> Const (GenericList Name Vector a) (GenericList Name Vector a))
    -> ListOverlayState a b
    -> Const (GenericList Name Vector a) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (GenericList Name Vector a) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (List Name a)
listOverlaySearchResults)
  case Maybe (Int, a)
mItem of
      Maybe (Int, a)
Nothing -> () -> MH ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      Just (Int
_, a
val) -> Lens' ChatState (ListOverlayState a b) -> a -> MH ()
forall a b. Lens' ChatState (ListOverlayState a b) -> a -> MH ()
listOverlayActivate Lens' ChatState (ListOverlayState a b)
which a
val

-- | Activate the specified list overlay's selected item by invoking the
-- overlay's configured enter keypress handler function.
listOverlayActivate :: Lens' ChatState (ListOverlayState a b) -> a -> MH ()
listOverlayActivate :: Lens' ChatState (ListOverlayState a b) -> a -> MH ()
listOverlayActivate Lens' ChatState (ListOverlayState 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 ((ListOverlayState a b
 -> Const (a -> MH Bool) (ListOverlayState a b))
-> ChatState -> Const (a -> MH Bool) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (a -> MH Bool) (ListOverlayState a b))
 -> ChatState -> Const (a -> MH Bool) ChatState)
-> (((a -> MH Bool) -> Const (a -> MH Bool) (a -> MH Bool))
    -> ListOverlayState a b
    -> Const (a -> MH Bool) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (a -> MH Bool) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (a -> MH Bool)
listOverlayEnterHandler)
    Bool
activated <- a -> MH Bool
handler a
val
    if Bool
activated
       then Mode -> MH ()
setMode Mode
Main
       else () -> MH ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

-- | Get the current search string for the specified overlay.
listOverlaySearchString :: Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString :: Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString Lens' ChatState (ListOverlayState a b)
which =
    ([Text] -> Text
forall a. [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 ((ListOverlayState a b
 -> Const (Editor Text Name) (ListOverlayState a b))
-> ChatState -> Const (Editor Text Name) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (Editor Text Name) (ListOverlayState a b))
 -> ChatState -> Const (Editor Text Name) ChatState)
-> ((Editor Text Name
     -> Const (Editor Text Name) (Editor Text Name))
    -> ListOverlayState a b
    -> Const (Editor Text Name) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (Editor Text Name) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Editor Text Name)
listOverlaySearchInput)

-- | Move the list cursor in the specified overlay.
listOverlayMove :: Lens' ChatState (ListOverlayState a b)
                -- ^ Which overlay
                -> (L.List Name a -> L.List Name a)
                -- ^ How to transform the list in the overlay
                -> MH ()
listOverlayMove :: Lens' ChatState (ListOverlayState a b)
-> (List Name a -> List Name a) -> MH ()
listOverlayMove Lens' ChatState (ListOverlayState a b)
which List Name a -> List Name a
how = (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (List Name a)
listOverlaySearchResults ((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 overlay and return to the
-- Main mode.
exitListOverlay :: Lens' ChatState (ListOverlayState a b)
                -- ^ Which overlay to reset
                -> MH ()
exitListOverlay :: Lens' ChatState (ListOverlayState a b) -> MH ()
exitListOverlay Lens' ChatState (ListOverlayState a b)
which = do
    ListOverlayState a b
st <- Getting (ListOverlayState a b) ChatState (ListOverlayState a b)
-> MH (ListOverlayState a b)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting (ListOverlayState a b) ChatState (ListOverlayState a b)
Lens' ChatState (ListOverlayState a b)
which
    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 ((ListOverlayState a b
 -> Const (Vector a -> List Name a) (ListOverlayState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (Vector a -> List Name a) (ListOverlayState 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))
    -> ListOverlayState a b
    -> Const (Vector a -> List Name a) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (Vector a -> List Name a) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Vector a -> List Name a)
listOverlayNewList)
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (List Name a)
listOverlaySearchResults ((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
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> (((a -> MH Bool) -> Identity (a -> MH Bool))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (a -> MH Bool)
listOverlayEnterHandler (((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 (m :: * -> *) a. Monad m => a -> m a
return Bool
False)
    Mode -> MH ()
setMode (ListOverlayState a b
stListOverlayState a b
-> Getting Mode (ListOverlayState a b) Mode -> Mode
forall s a. s -> Getting a s a -> a
^.Getting Mode (ListOverlayState a b) Mode
forall a b. Lens' (ListOverlayState a b) Mode
listOverlayReturnMode)

-- | Initialize a list overlay with the specified arguments and switch
-- to the specified mode.
enterListOverlayMode :: (Lens' ChatState (ListOverlayState a b))
                     -- ^ Which overlay to initialize
                     -> Mode
                     -- ^ The mode to change to
                     -> b
                     -- ^ The overlay's initial search scope
                     -> (a -> MH Bool)
                     -- ^ The overlay's enter keypress handler
                     -> (b -> Session -> Text -> IO (Vec.Vector a))
                     -- ^ The overlay's results fetcher function
                     -> MH ()
enterListOverlayMode :: Lens' ChatState (ListOverlayState a b)
-> Mode
-> b
-> (a -> MH Bool)
-> (b -> Session -> Text -> IO (Vector a))
-> MH ()
enterListOverlayMode Lens' ChatState (ListOverlayState a b)
which Mode
mode b
scope a -> MH Bool
enterHandler b -> Session -> Text -> IO (Vector a)
fetcher = do
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((b -> Identity b)
    -> ListOverlayState a b -> Identity (ListOverlayState a b))
-> (b -> Identity b)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(b -> Identity b)
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) b
listOverlaySearchScope ((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
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((TextZipper Text -> Identity (TextZipper Text))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Editor Text Name)
listOverlaySearchInput((Editor Text Name -> Identity (Editor Text Name))
 -> ListOverlayState a b -> Identity (ListOverlayState a b))
-> ((TextZipper Text -> Identity (TextZipper Text))
    -> Editor Text Name -> Identity (Editor Text Name))
-> (TextZipper Text -> Identity (TextZipper Text))
-> ListOverlayState a b
-> Identity (ListOverlayState 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.
Lens (Editor t1 n) (Editor t2 n) (TextZipper t1) (TextZipper t2)
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
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> (((a -> MH Bool) -> Identity (a -> MH Bool))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (a -> MH Bool)
listOverlayEnterHandler (((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
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> (((b -> Session -> Text -> IO (Vector a))
     -> Identity (b -> Session -> Text -> IO (Vector a)))
    -> ListOverlayState a b -> Identity (ListOverlayState 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)))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b.
Lens'
  (ListOverlayState a b) (b -> Session -> Text -> IO (Vector a))
listOverlayFetchResults (((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
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListOverlayState a b -> Identity (ListOverlayState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) Bool
listOverlaySearching ((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 ((ListOverlayState a b
 -> Const (Vector a -> List Name a) (ListOverlayState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (Vector a -> List Name a) (ListOverlayState 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))
    -> ListOverlayState a b
    -> Const (Vector a -> List Name a) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (Vector a -> List Name a) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Vector a -> List Name a)
listOverlayNewList)
    (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (List Name a)
listOverlaySearchResults ((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
    Mode -> MH ()
setMode Mode
mode
    Lens' ChatState (ListOverlayState a b) -> MH ()
forall a b. Lens' ChatState (ListOverlayState a b) -> MH ()
resetListOverlaySearch Lens' ChatState (ListOverlayState a b)
which

-- | Reset the overlay's search by initiating a new search request for
-- the string that is currently in the overlay's editor. This does
-- nothing if a search for this overlay is already in progress.
resetListOverlaySearch :: Lens' ChatState (ListOverlayState a b) -> MH ()
resetListOverlaySearch :: Lens' ChatState (ListOverlayState a b) -> MH ()
resetListOverlaySearch Lens' ChatState (ListOverlayState 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 ((ListOverlayState a b -> Const Bool (ListOverlayState a b))
-> ChatState -> Const Bool ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Const Bool (ListOverlayState a b))
 -> ChatState -> Const Bool ChatState)
-> ((Bool -> Const Bool Bool)
    -> ListOverlayState a b -> Const Bool (ListOverlayState a b))
-> Getting Bool ChatState Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Const Bool Bool)
-> ListOverlayState a b -> Const Bool (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) Bool
listOverlaySearching)

    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 (ListOverlayState a b) -> MH Text
forall a b. Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString Lens' ChatState (ListOverlayState a b)
which
        (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListOverlayState a b -> Identity (ListOverlayState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) Bool
listOverlaySearching ((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 ((ListOverlayState a b
 -> Const (Vector a -> List Name a) (ListOverlayState a b))
-> ChatState -> Const (Vector a -> List Name a) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const (Vector a -> List Name a) (ListOverlayState 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))
    -> ListOverlayState a b
    -> Const (Vector a -> List Name a) (ListOverlayState 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))
-> ListOverlayState a b
-> Const (Vector a -> List Name a) (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Vector a -> List Name a)
listOverlayNewList)
        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 ((ListOverlayState a b -> Const b (ListOverlayState a b))
-> ChatState -> Const b ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Const b (ListOverlayState a b))
 -> ChatState -> Const b ChatState)
-> ((b -> Const b b)
    -> ListOverlayState a b -> Const b (ListOverlayState a b))
-> Getting b ChatState b
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(b -> Const b b)
-> ListOverlayState a b -> Const b (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) b
listOverlaySearchScope)
        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 ((ListOverlayState a b
 -> Const
      (b -> Session -> Text -> IO (Vector a)) (ListOverlayState a b))
-> ChatState
-> Const (b -> Session -> Text -> IO (Vector a)) ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b
  -> Const
       (b -> Session -> Text -> IO (Vector a)) (ListOverlayState 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)))
    -> ListOverlayState a b
    -> Const
         (b -> Session -> Text -> IO (Vector a)) (ListOverlayState 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)))
-> ListOverlayState a b
-> Const
     (b -> Session -> Text -> IO (Vector a)) (ListOverlayState a b)
forall a b.
Lens'
  (ListOverlayState a b) (b -> Session -> Text -> IO (Vector a))
listOverlayFetchResults)
        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 (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
                (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((List Name a -> Identity (List Name a))
    -> ListOverlayState a b -> Identity (ListOverlayState 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))
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (List Name a)
listOverlaySearchResults ((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
                (ListOverlayState a b -> Identity (ListOverlayState a b))
-> ChatState -> Identity ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> Identity (ListOverlayState a b))
 -> ChatState -> Identity ChatState)
-> ((Bool -> Identity Bool)
    -> ListOverlayState a b -> Identity (ListOverlayState a b))
-> (Bool -> Identity Bool)
-> ChatState
-> Identity ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Bool -> Identity Bool)
-> ListOverlayState a b -> Identity (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) Bool
listOverlaySearching ((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 (ListOverlayState a b) -> MH Text
forall a b. Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString Lens' ChatState (ListOverlayState 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 (ListOverlayState a b) -> MH ()
forall a b. Lens' ChatState (ListOverlayState a b) -> MH ()
resetListOverlaySearch Lens' ChatState (ListOverlayState a b)
which

-- | Generically handle an event for the list overlay state targeted
-- by the specified lens. Automatically dispatches new searches in the
-- overlay's editor if the editor contents change.
onEventListOverlay :: Lens' ChatState (ListOverlayState a b)
                   -- ^ Which overlay to dispatch to?
                   -> (KeyConfig -> KeyHandlerMap)
                   -- ^ The keybinding builder
                   -> Vty.Event
                   -- ^ The event
                   -> MH Bool
onEventListOverlay :: Lens' ChatState (ListOverlayState a b)
-> (KeyConfig -> KeyHandlerMap) -> Event -> MH Bool
onEventListOverlay Lens' ChatState (ListOverlayState a b)
which KeyConfig -> KeyHandlerMap
keybindings =
    (KeyConfig -> KeyHandlerMap)
-> (Event -> MH ()) -> Event -> MH Bool
handleKeyboardEvent KeyConfig -> KeyHandlerMap
keybindings ((Event -> MH ()) -> Event -> MH Bool)
-> (Event -> MH ()) -> Event -> MH Bool
forall a b. (a -> b) -> a -> b
$ \Event
e -> do
        -- Get the editor content before the event.
        Text
before <- Lens' ChatState (ListOverlayState a b) -> MH Text
forall a b. Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString Lens' ChatState (ListOverlayState a b)
which

        -- First find a matching keybinding in the keybinding list.
        Bool
handled <- (KeyConfig -> KeyHandlerMap)
-> (Event -> MH ()) -> Event -> MH Bool
handleKeyboardEvent (Lens' ChatState (Editor Text Name) -> KeyConfig -> KeyHandlerMap
editingKeybindings ((ListOverlayState a b -> f (ListOverlayState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> f (ListOverlayState a b))
 -> ChatState -> f ChatState)
-> ((Editor Text Name -> f (Editor Text Name))
    -> ListOverlayState a b -> f (ListOverlayState 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))
-> ListOverlayState a b -> f (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Editor Text Name)
listOverlaySearchInput)) (MH () -> Event -> MH ()
forall a b. a -> b -> a
const (MH () -> Event -> MH ()) -> MH () -> Event -> MH ()
forall a b. (a -> b) -> a -> b
$ () -> MH ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) 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)
-> (Event -> Editor Text Name -> EventM Name (Editor Text Name))
-> Event
-> MH ()
forall b e.
Lens' ChatState b -> (e -> b -> EventM Name b) -> e -> MH ()
mhHandleEventLensed ((ListOverlayState a b -> f (ListOverlayState a b))
-> ChatState -> f ChatState
Lens' ChatState (ListOverlayState a b)
which((ListOverlayState a b -> f (ListOverlayState a b))
 -> ChatState -> f ChatState)
-> ((Editor Text Name -> f (Editor Text Name))
    -> ListOverlayState a b -> f (ListOverlayState 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))
-> ListOverlayState a b -> f (ListOverlayState a b)
forall a b. Lens' (ListOverlayState a b) (Editor Text Name)
listOverlaySearchInput) Event -> Editor Text Name -> EventM Name (Editor Text Name)
forall t n.
(DecodeUtf8 t, Eq t, GenericTextZipper t) =>
Event -> Editor t n -> EventM n (Editor t n)
E.handleEditorEvent Event
e

        -- Get the editor content after the event. If the string changed,
        -- start a new search.
        Text
after <- Lens' ChatState (ListOverlayState a b) -> MH Text
forall a b. Lens' ChatState (ListOverlayState a b) -> MH Text
listOverlaySearchString Lens' ChatState (ListOverlayState 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 (ListOverlayState a b) -> MH ()
forall a b. Lens' ChatState (ListOverlayState a b) -> MH ()
resetListOverlaySearch Lens' ChatState (ListOverlayState a b)
which