{-# LANGUAGE TemplateHaskell #-}
module Matterhorn.Types.EditState
( EditMode(..)
, AttachmentData(..)
, AutocompletionType(..)
, CompletionSource(..)
, SpecialMention(..)
, specialMentionName
, isSpecialMention
, EditState(..)
, newEditState
, unsafeEsFileBrowser
, esAttachmentList
, esFileBrowser
, esMisspellings
, esEditMode
, esEphemeral
, esEditor
, esAutocomplete
, esAutocompletePending
, esResetEditMode
, esJustCompleted
, esShowReplyPrompt
, esSpellCheckTimerReset
, esTeamId
, esChannelId
, EphemeralEditState(..)
, defaultEphemeralEditState
, eesMultiline
, eesInputHistoryPosition
, eesLastInput
, eesTypingUsers
, addEphemeralStateTypingUser
, AutocompleteState(..)
, acPreviousSearchString
, acCompletionList
, acCachedResponses
, acType
, AutocompleteAlternative(..)
, autocompleteAlternativeReplacement
, autocompleteAlternativeText
)
where
import Prelude ()
import Matterhorn.Prelude
import Brick.Widgets.Edit ( Editor, editor )
import Brick.Widgets.List ( List, list )
import qualified Brick.Widgets.FileBrowser as FB
import qualified Data.ByteString as BS
import qualified Data.HashMap.Strict as HM
import qualified Data.Text as T
import Lens.Micro.Platform ( Lens', makeLenses, (.~), (^?!), lens, _Just
, (%~) )
import Network.Mattermost.Types
import Matterhorn.Types.Common
import Matterhorn.Types.Messages ( Message, MessageType )
import Matterhorn.Types.Users ( TypingUsers, noTypingUsers, addTypingUser
, addUserSigil, trimUserSigil )
import Matterhorn.Constants
data SpecialMention =
MentionAll
| MentionChannel
data AutocompleteAlternative =
UserCompletion User Bool
| SpecialMention SpecialMention
| ChannelCompletion Bool Channel
| SyntaxCompletion Text
| CommandCompletion CompletionSource Text Text Text
| EmojiCompletion Text
autocompleteAlternativeText :: AutocompleteAlternative -> Text
autocompleteAlternativeText :: AutocompleteAlternative -> Text
autocompleteAlternativeText (UserCompletion User
u Bool
_) =
User -> Text
userUsername User
u
autocompleteAlternativeText (SpecialMention SpecialMention
MentionChannel) =
Text
"channel"
autocompleteAlternativeText (SpecialMention SpecialMention
MentionAll) =
Text
"all"
autocompleteAlternativeText (ChannelCompletion Bool
_ Channel
c) =
UserText -> Text
unsafeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelName Channel
c
autocompleteAlternativeText (SyntaxCompletion Text
n) =
Text
n
autocompleteAlternativeText (CommandCompletion CompletionSource
_ Text
t Text
_ Text
_) =
Text
t
autocompleteAlternativeText (EmojiCompletion Text
t) =
Text
t
data CompletionSource = Server | Client
deriving (CompletionSource -> CompletionSource -> Bool
(CompletionSource -> CompletionSource -> Bool)
-> (CompletionSource -> CompletionSource -> Bool)
-> Eq CompletionSource
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CompletionSource -> CompletionSource -> Bool
== :: CompletionSource -> CompletionSource -> Bool
$c/= :: CompletionSource -> CompletionSource -> Bool
/= :: CompletionSource -> CompletionSource -> Bool
Eq, Int -> CompletionSource -> ShowS
[CompletionSource] -> ShowS
CompletionSource -> String
(Int -> CompletionSource -> ShowS)
-> (CompletionSource -> String)
-> ([CompletionSource] -> ShowS)
-> Show CompletionSource
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CompletionSource -> ShowS
showsPrec :: Int -> CompletionSource -> ShowS
$cshow :: CompletionSource -> String
show :: CompletionSource -> String
$cshowList :: [CompletionSource] -> ShowS
showList :: [CompletionSource] -> ShowS
Show)
specialMentionName :: SpecialMention -> Text
specialMentionName :: SpecialMention -> Text
specialMentionName SpecialMention
MentionChannel = Text
"channel"
specialMentionName SpecialMention
MentionAll = Text
"all"
isSpecialMention :: T.Text -> Bool
isSpecialMention :: Text -> Bool
isSpecialMention Text
n = Maybe SpecialMention -> Bool
forall a. Maybe a -> Bool
isJust (Maybe SpecialMention -> Bool) -> Maybe SpecialMention -> Bool
forall a b. (a -> b) -> a -> b
$ Text -> [(Text, SpecialMention)] -> Maybe SpecialMention
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
trimUserSigil Text
n) [(Text, SpecialMention)]
pairs
where
pairs :: [(Text, SpecialMention)]
pairs = SpecialMention -> (Text, SpecialMention)
mkPair (SpecialMention -> (Text, SpecialMention))
-> [SpecialMention] -> [(Text, SpecialMention)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [SpecialMention]
mentions
mentions :: [SpecialMention]
mentions = [ SpecialMention
MentionChannel
, SpecialMention
MentionAll
]
mkPair :: SpecialMention -> (Text, SpecialMention)
mkPair SpecialMention
v = (SpecialMention -> Text
specialMentionName SpecialMention
v, SpecialMention
v)
autocompleteAlternativeReplacement :: AutocompleteAlternative -> Text
autocompleteAlternativeReplacement :: AutocompleteAlternative -> Text
autocompleteAlternativeReplacement (EmojiCompletion Text
e) =
Text
":" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
e Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
":"
autocompleteAlternativeReplacement (SpecialMention SpecialMention
m) =
Text -> Text
addUserSigil (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ SpecialMention -> Text
specialMentionName SpecialMention
m
autocompleteAlternativeReplacement (UserCompletion User
u Bool
_) =
Text -> Text
addUserSigil (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ User -> Text
userUsername User
u
autocompleteAlternativeReplacement (ChannelCompletion Bool
_ Channel
c) =
Text
normalChannelSigil Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelName Channel
c)
autocompleteAlternativeReplacement (SyntaxCompletion Text
t) =
Text
"```" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t
autocompleteAlternativeReplacement (CommandCompletion CompletionSource
_ Text
t Text
_ Text
_) =
Text
"/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t
data AutocompletionType =
ACUsers
| ACChannels
| ACCodeBlockLanguage
| ACEmoji
| ACCommands
deriving (AutocompletionType -> AutocompletionType -> Bool
(AutocompletionType -> AutocompletionType -> Bool)
-> (AutocompletionType -> AutocompletionType -> Bool)
-> Eq AutocompletionType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AutocompletionType -> AutocompletionType -> Bool
== :: AutocompletionType -> AutocompletionType -> Bool
$c/= :: AutocompletionType -> AutocompletionType -> Bool
/= :: AutocompletionType -> AutocompletionType -> Bool
Eq, Int -> AutocompletionType -> ShowS
[AutocompletionType] -> ShowS
AutocompletionType -> String
(Int -> AutocompletionType -> ShowS)
-> (AutocompletionType -> String)
-> ([AutocompletionType] -> ShowS)
-> Show AutocompletionType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AutocompletionType -> ShowS
showsPrec :: Int -> AutocompletionType -> ShowS
$cshow :: AutocompletionType -> String
show :: AutocompletionType -> String
$cshowList :: [AutocompletionType] -> ShowS
showList :: [AutocompletionType] -> ShowS
Show)
data AttachmentData =
AttachmentData { AttachmentData -> FileInfo
attachmentDataFileInfo :: FB.FileInfo
, AttachmentData -> ByteString
attachmentDataBytes :: BS.ByteString
}
deriving (AttachmentData -> AttachmentData -> Bool
(AttachmentData -> AttachmentData -> Bool)
-> (AttachmentData -> AttachmentData -> Bool) -> Eq AttachmentData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AttachmentData -> AttachmentData -> Bool
== :: AttachmentData -> AttachmentData -> Bool
$c/= :: AttachmentData -> AttachmentData -> Bool
/= :: AttachmentData -> AttachmentData -> Bool
Eq, Int -> AttachmentData -> ShowS
[AttachmentData] -> ShowS
AttachmentData -> String
(Int -> AttachmentData -> ShowS)
-> (AttachmentData -> String)
-> ([AttachmentData] -> ShowS)
-> Show AttachmentData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AttachmentData -> ShowS
showsPrec :: Int -> AttachmentData -> ShowS
$cshow :: AttachmentData -> String
show :: AttachmentData -> String
$cshowList :: [AttachmentData] -> ShowS
showList :: [AttachmentData] -> ShowS
Show)
data EditMode =
NewPost
| Editing Post MessageType
| Replying Message Post
deriving (Int -> EditMode -> ShowS
[EditMode] -> ShowS
EditMode -> String
(Int -> EditMode -> ShowS)
-> (EditMode -> String) -> ([EditMode] -> ShowS) -> Show EditMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EditMode -> ShowS
showsPrec :: Int -> EditMode -> ShowS
$cshow :: EditMode -> String
show :: EditMode -> String
$cshowList :: [EditMode] -> ShowS
showList :: [EditMode] -> ShowS
Show, EditMode -> EditMode -> Bool
(EditMode -> EditMode -> Bool)
-> (EditMode -> EditMode -> Bool) -> Eq EditMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EditMode -> EditMode -> Bool
== :: EditMode -> EditMode -> Bool
$c/= :: EditMode -> EditMode -> Bool
/= :: EditMode -> EditMode -> Bool
Eq)
data AutocompleteState n =
AutocompleteState { forall n. AutocompleteState n -> Text
_acPreviousSearchString :: Text
, forall n. AutocompleteState n -> List n AutocompleteAlternative
_acCompletionList :: List n AutocompleteAlternative
, forall n. AutocompleteState n -> AutocompletionType
_acType :: AutocompletionType
, forall n.
AutocompleteState n -> HashMap Text [AutocompleteAlternative]
_acCachedResponses :: HM.HashMap Text [AutocompleteAlternative]
}
data EditState n =
EditState { forall n. EditState n -> Editor Text n
_esEditor :: Editor Text n
, forall n. EditState n -> EditMode
_esEditMode :: EditMode
, forall n. EditState n -> EphemeralEditState
_esEphemeral :: EphemeralEditState
, forall n. EditState n -> Set Text
_esMisspellings :: Set Text
, forall n. EditState n -> Maybe (AutocompleteState n)
_esAutocomplete :: Maybe (AutocompleteState n)
, forall n. EditState n -> EditMode
_esResetEditMode :: EditMode
, forall n. EditState n -> Maybe Text
_esAutocompletePending :: Maybe Text
, forall n. EditState n -> List n AttachmentData
_esAttachmentList :: List n AttachmentData
, forall n. EditState n -> Maybe (FileBrowser n)
_esFileBrowser :: Maybe (FB.FileBrowser n)
, forall n. EditState n -> Bool
_esJustCompleted :: Bool
, forall n. EditState n -> Bool
_esShowReplyPrompt :: Bool
, forall n. EditState n -> Maybe (IO ())
_esSpellCheckTimerReset :: Maybe (IO ())
, forall n. EditState n -> ChannelId
_esChannelId :: ChannelId
, forall n. EditState n -> Maybe TeamId
_esTeamId :: Maybe TeamId
}
newEditState :: n -> n -> Maybe TeamId -> ChannelId -> EditMode -> Bool -> Maybe (IO ()) -> EditState n
newEditState :: forall n.
n
-> n
-> Maybe TeamId
-> ChannelId
-> EditMode
-> Bool
-> Maybe (IO ())
-> EditState n
newEditState n
editorName n
attachmentListName Maybe TeamId
tId ChannelId
cId EditMode
initialEditMode Bool
showReplyPrompt Maybe (IO ())
reset =
EditState { _esEditor :: Editor Text n
_esEditor = n -> Maybe Int -> Text -> Editor Text n
forall a n.
GenericTextZipper a =>
n -> Maybe Int -> a -> Editor a n
editor n
editorName Maybe Int
forall a. Maybe a
Nothing Text
""
, _esEphemeral :: EphemeralEditState
_esEphemeral = EphemeralEditState
defaultEphemeralEditState
, _esEditMode :: EditMode
_esEditMode = EditMode
initialEditMode
, _esResetEditMode :: EditMode
_esResetEditMode = EditMode
initialEditMode
, _esMisspellings :: Set Text
_esMisspellings = Set Text
forall a. Monoid a => a
mempty
, _esAutocomplete :: Maybe (AutocompleteState n)
_esAutocomplete = Maybe (AutocompleteState n)
forall a. Maybe a
Nothing
, _esAutocompletePending :: Maybe Text
_esAutocompletePending = Maybe Text
forall a. Maybe a
Nothing
, _esAttachmentList :: List n AttachmentData
_esAttachmentList = n -> Vector AttachmentData -> Int -> List n AttachmentData
forall (t :: * -> *) n e.
Foldable t =>
n -> t e -> Int -> GenericList n t e
list n
attachmentListName Vector AttachmentData
forall a. Monoid a => a
mempty Int
1
, _esFileBrowser :: Maybe (FileBrowser n)
_esFileBrowser = Maybe (FileBrowser n)
forall a. Maybe a
Nothing
, _esJustCompleted :: Bool
_esJustCompleted = Bool
False
, _esShowReplyPrompt :: Bool
_esShowReplyPrompt = Bool
showReplyPrompt
, _esSpellCheckTimerReset :: Maybe (IO ())
_esSpellCheckTimerReset = Maybe (IO ())
reset
, _esChannelId :: ChannelId
_esChannelId = ChannelId
cId
, _esTeamId :: Maybe TeamId
_esTeamId = Maybe TeamId
tId
}
data EphemeralEditState =
EphemeralEditState { EphemeralEditState -> Bool
_eesMultiline :: Bool
, EphemeralEditState -> Maybe Int
_eesInputHistoryPosition :: Maybe Int
, EphemeralEditState -> (Text, EditMode)
_eesLastInput :: (T.Text, EditMode)
, EphemeralEditState -> TypingUsers
_eesTypingUsers :: TypingUsers
}
defaultEphemeralEditState :: EphemeralEditState
defaultEphemeralEditState :: EphemeralEditState
defaultEphemeralEditState =
EphemeralEditState { _eesMultiline :: Bool
_eesMultiline = Bool
False
, _eesInputHistoryPosition :: Maybe Int
_eesInputHistoryPosition = Maybe Int
forall a. Maybe a
Nothing
, _eesLastInput :: (Text, EditMode)
_eesLastInput = (Text
"", EditMode
NewPost)
, _eesTypingUsers :: TypingUsers
_eesTypingUsers = TypingUsers
noTypingUsers
}
makeLenses ''EphemeralEditState
addEphemeralStateTypingUser :: UserId -> UTCTime -> EphemeralEditState -> EphemeralEditState
addEphemeralStateTypingUser :: UserId -> UTCTime -> EphemeralEditState -> EphemeralEditState
addEphemeralStateTypingUser UserId
uId UTCTime
ts = (TypingUsers -> Identity TypingUsers)
-> EphemeralEditState -> Identity EphemeralEditState
Lens' EphemeralEditState TypingUsers
eesTypingUsers ((TypingUsers -> Identity TypingUsers)
-> EphemeralEditState -> Identity EphemeralEditState)
-> (TypingUsers -> TypingUsers)
-> EphemeralEditState
-> EphemeralEditState
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (UserId -> UTCTime -> TypingUsers -> TypingUsers
addTypingUser UserId
uId UTCTime
ts)
makeLenses ''EditState
makeLenses ''AutocompleteState
unsafeEsFileBrowser :: Lens' (EditState n) (FB.FileBrowser n)
unsafeEsFileBrowser :: forall n (f :: * -> *).
Functor f =>
(FileBrowser n -> f (FileBrowser n))
-> EditState n -> f (EditState n)
unsafeEsFileBrowser =
(EditState n -> FileBrowser n)
-> (EditState n -> FileBrowser n -> EditState n)
-> Lens (EditState n) (EditState n) (FileBrowser n) (FileBrowser n)
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\EditState n
st -> EditState n
stEditState n
-> Getting
(Maybe (FileBrowser n)) (EditState n) (Maybe (FileBrowser n))
-> Maybe (FileBrowser n)
forall s a. s -> Getting a s a -> a
^.Getting
(Maybe (FileBrowser n)) (EditState n) (Maybe (FileBrowser n))
forall n (f :: * -> *).
Functor f =>
(Maybe (FileBrowser n) -> f (Maybe (FileBrowser n)))
-> EditState n -> f (EditState n)
esFileBrowser Maybe (FileBrowser n)
-> Getting
(Endo (FileBrowser n)) (Maybe (FileBrowser n)) (FileBrowser n)
-> FileBrowser n
forall s a. HasCallStack => s -> Getting (Endo a) s a -> a
^?! Getting
(Endo (FileBrowser n)) (Maybe (FileBrowser n)) (FileBrowser n)
forall a a' (f :: * -> *).
Applicative f =>
(a -> f a') -> Maybe a -> f (Maybe a')
_Just)
(\EditState n
st FileBrowser n
t -> EditState n
st EditState n -> (EditState n -> EditState n) -> EditState n
forall a b. a -> (a -> b) -> b
& (Maybe (FileBrowser n) -> Identity (Maybe (FileBrowser n)))
-> EditState n -> Identity (EditState n)
forall n (f :: * -> *).
Functor f =>
(Maybe (FileBrowser n) -> f (Maybe (FileBrowser n)))
-> EditState n -> f (EditState n)
esFileBrowser ((Maybe (FileBrowser n) -> Identity (Maybe (FileBrowser n)))
-> EditState n -> Identity (EditState n))
-> Maybe (FileBrowser n) -> EditState n -> EditState n
forall s t a b. ASetter s t a b -> b -> s -> t
.~ FileBrowser n -> Maybe (FileBrowser n)
forall a. a -> Maybe a
Just FileBrowser n
t)