{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}

module Matterhorn.Types.Channels
  ( ClientChannel(..)
  , ChannelContents(..)
  , ChannelInfo(..)
  , ClientChannels -- constructor remains internal
  , NewMessageIndicator(..)
  , EphemeralEditState(..)
  , EditMode(..)
  , eesMultiline, eesInputHistoryPosition, eesLastInput
  , defaultEphemeralEditState
  -- * Lenses created for accessing ClientChannel fields
  , ccContents, ccInfo, ccEditState
  -- * Lenses created for accessing ChannelInfo fields
  , cdViewed, cdNewMessageIndicator, cdEditedMessageThreshold, cdUpdated
  , cdName, cdDisplayName, cdHeader, cdPurpose, cdType
  , cdMentionCount, cdTypingUsers, cdDMUserId, cdChannelId
  , cdSidebarShowOverride, cdNotifyProps, cdTeamId
  -- * Lenses created for accessing ChannelContents fields
  , cdMessages, cdFetchPending
  -- * Creating ClientChannel objects
  , makeClientChannel
  -- * Managing ClientChannel collections
  , noChannels, addChannel, removeChannel, findChannelById, modifyChannelById
  , channelByIdL, maybeChannelByIdL
  , allTeamIds
  , filteredChannelIds
  , filteredChannels
  -- * Creating ChannelInfo objects
  , channelInfoFromChannelWithData
  -- * Channel State management
  , clearNewMessageIndicator
  , clearEditedThreshold
  , adjustUpdated
  , adjustEditedThreshold
  , updateNewMessageIndicator
  , addChannelTypingUser
  -- * Notification settings
  , notifyPreference
  , isMuted
  , channelNotifyPropsMarkUnreadL
  , channelNotifyPropsIgnoreChannelMentionsL
  , channelNotifyPropsDesktopL
  , channelNotifyPropsPushL
  -- * Miscellaneous channel-related operations
  , canLeaveChannel
  , preferredChannelName
  , isTownSquare
  , channelDeleted
  , getDmChannelFor
  , allDmChannelMappings
  , getChannelNameSet
  )
where

import           Prelude ()
import           Matterhorn.Prelude

import qualified Data.HashMap.Strict as HM
import qualified Data.Set as S
import qualified Data.Text as T
import           Lens.Micro.Platform ( (%~), (.~), Traversal', Lens'
                                     , makeLenses, ix, at
                                     , to, non )

import           Network.Mattermost.Lenses hiding ( Lens' )
import           Network.Mattermost.Types ( Channel(..), UserId, ChannelId
                                          , ChannelMember(..)
                                          , Type(..)
                                          , Post
                                          , User(userNotifyProps)
                                          , ChannelNotifyProps
                                          , NotifyOption(..)
                                          , WithDefault(..)
                                          , ServerTime
                                          , TeamId
                                          , emptyChannelNotifyProps
                                          )

import           Matterhorn.Types.Messages ( Messages, noMessages, addMessage
                                           , clientMessageToMessage, Message, MessageType )
import           Matterhorn.Types.Posts ( ClientMessageType(UnknownGapBefore)
                                        , newClientMessage )
import           Matterhorn.Types.Users ( TypingUsers, noTypingUsers, addTypingUser )
import           Matterhorn.Types.Common


-- * Channel representations

-- | A 'ClientChannel' contains both the message
--   listing and the metadata about a channel
data ClientChannel = ClientChannel
  { ClientChannel -> ChannelContents
_ccContents :: ChannelContents
    -- ^ A list of 'Message's in the channel
  , ClientChannel -> ChannelInfo
_ccInfo :: ChannelInfo
    -- ^ The 'ChannelInfo' for the channel
  , ClientChannel -> EphemeralEditState
_ccEditState :: EphemeralEditState
    -- ^ Editor state that we swap in and out as the current channel is
    -- changed.
  }

-- | The input state associated with the message editor.
data EditMode =
    NewPost
    -- ^ The input is for a new post.
    | Editing Post MessageType
    -- ^ The input is ultimately to replace the body of an existing post
    -- of the specified type.
    | Replying Message Post
    -- ^ The input is to be used as a new post in reply to the specified
    -- 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
showList :: [EditMode] -> ShowS
$cshowList :: [EditMode] -> ShowS
show :: EditMode -> String
$cshow :: EditMode -> String
showsPrec :: Int -> EditMode -> ShowS
$cshowsPrec :: Int -> EditMode -> ShowS
Show)

data EphemeralEditState =
    EphemeralEditState { EphemeralEditState -> Bool
_eesMultiline :: Bool
                       -- ^ Whether the editor is in multiline mode
                       , EphemeralEditState -> Maybe Int
_eesInputHistoryPosition :: Maybe Int
                       -- ^ The input history position, if any
                       , EphemeralEditState -> (Text, EditMode)
_eesLastInput :: (T.Text, EditMode)
                       -- ^ The input entered into the text editor last
                       -- time the user was focused on the channel
                       -- associated with this state.
                       }

-- Get a channel's name, depending on its type
preferredChannelName :: Channel -> Text
preferredChannelName :: Channel -> Text
preferredChannelName Channel
ch
    | Channel -> Type
channelType Channel
ch Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type
Group = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelDisplayName Channel
ch
    | Bool
otherwise               = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelName Channel
ch

data NewMessageIndicator =
    Hide
    | NewPostsAfterServerTime ServerTime
    | NewPostsStartingAt ServerTime
    deriving (NewMessageIndicator -> NewMessageIndicator -> Bool
(NewMessageIndicator -> NewMessageIndicator -> Bool)
-> (NewMessageIndicator -> NewMessageIndicator -> Bool)
-> Eq NewMessageIndicator
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NewMessageIndicator -> NewMessageIndicator -> Bool
$c/= :: NewMessageIndicator -> NewMessageIndicator -> Bool
== :: NewMessageIndicator -> NewMessageIndicator -> Bool
$c== :: NewMessageIndicator -> NewMessageIndicator -> Bool
Eq, Int -> NewMessageIndicator -> ShowS
[NewMessageIndicator] -> ShowS
NewMessageIndicator -> String
(Int -> NewMessageIndicator -> ShowS)
-> (NewMessageIndicator -> String)
-> ([NewMessageIndicator] -> ShowS)
-> Show NewMessageIndicator
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NewMessageIndicator] -> ShowS
$cshowList :: [NewMessageIndicator] -> ShowS
show :: NewMessageIndicator -> String
$cshow :: NewMessageIndicator -> String
showsPrec :: Int -> NewMessageIndicator -> ShowS
$cshowsPrec :: Int -> NewMessageIndicator -> ShowS
Show)

initialChannelInfo :: UserId -> Channel -> ChannelInfo
initialChannelInfo :: UserId -> Channel -> ChannelInfo
initialChannelInfo UserId
myId Channel
chan =
    let updated :: ServerTime
updated  = Channel
chan Channel -> Getting ServerTime Channel ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^. Getting ServerTime Channel ServerTime
Lens' Channel ServerTime
channelLastPostAtL
    in ChannelInfo :: ChannelId
-> Maybe TeamId
-> Maybe ServerTime
-> NewMessageIndicator
-> Maybe ServerTime
-> Int
-> ServerTime
-> Text
-> Text
-> Text
-> Text
-> Type
-> ChannelNotifyProps
-> TypingUsers
-> Maybe UserId
-> Maybe UTCTime
-> ChannelInfo
ChannelInfo { _cdChannelId :: ChannelId
_cdChannelId              = Channel
chanChannel -> Getting ChannelId Channel ChannelId -> ChannelId
forall s a. s -> Getting a s a -> a
^.Getting ChannelId Channel ChannelId
Lens' Channel ChannelId
channelIdL
                   , _cdTeamId :: Maybe TeamId
_cdTeamId                 = Channel
chanChannel
-> Getting (Maybe TeamId) Channel (Maybe TeamId) -> Maybe TeamId
forall s a. s -> Getting a s a -> a
^.Getting (Maybe TeamId) Channel (Maybe TeamId)
Lens' Channel (Maybe TeamId)
channelTeamIdL
                   , _cdViewed :: Maybe ServerTime
_cdViewed                 = Maybe ServerTime
forall a. Maybe a
Nothing
                   , _cdNewMessageIndicator :: NewMessageIndicator
_cdNewMessageIndicator    = NewMessageIndicator
Hide
                   , _cdEditedMessageThreshold :: Maybe ServerTime
_cdEditedMessageThreshold = Maybe ServerTime
forall a. Maybe a
Nothing
                   , _cdMentionCount :: Int
_cdMentionCount           = Int
0
                   , _cdUpdated :: ServerTime
_cdUpdated                = ServerTime
updated
                   , _cdName :: Text
_cdName                   = Channel -> Text
preferredChannelName Channel
chan
                   , _cdDisplayName :: Text
_cdDisplayName            = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelDisplayName Channel
chan
                   , _cdHeader :: Text
_cdHeader                 = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel
chanChannel -> Getting UserText Channel UserText -> UserText
forall s a. s -> Getting a s a -> a
^.Getting UserText Channel UserText
Lens' Channel UserText
channelHeaderL
                   , _cdPurpose :: Text
_cdPurpose                = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel
chanChannel -> Getting UserText Channel UserText -> UserText
forall s a. s -> Getting a s a -> a
^.Getting UserText Channel UserText
Lens' Channel UserText
channelPurposeL
                   , _cdType :: Type
_cdType                   = Channel
chanChannel -> Getting Type Channel Type -> Type
forall s a. s -> Getting a s a -> a
^.Getting Type Channel Type
Lens' Channel Type
channelTypeL
                   , _cdNotifyProps :: ChannelNotifyProps
_cdNotifyProps            = ChannelNotifyProps
emptyChannelNotifyProps
                   , _cdTypingUsers :: TypingUsers
_cdTypingUsers            = TypingUsers
noTypingUsers
                   , _cdDMUserId :: Maybe UserId
_cdDMUserId               = if Channel
chanChannel -> Getting Type Channel Type -> Type
forall s a. s -> Getting a s a -> a
^.Getting Type Channel Type
Lens' Channel Type
channelTypeL Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type
Direct
                                                 then UserId -> Text -> Maybe UserId
userIdForDMChannel UserId
myId (Text -> Maybe UserId) -> Text -> Maybe UserId
forall a b. (a -> b) -> a -> b
$
                                                      UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelName Channel
chan
                                                 else Maybe UserId
forall a. Maybe a
Nothing
                   , _cdSidebarShowOverride :: Maybe UTCTime
_cdSidebarShowOverride    = Maybe UTCTime
forall a. Maybe a
Nothing
                   }

channelInfoFromChannelWithData :: Channel -> ChannelMember -> ChannelInfo -> ChannelInfo
channelInfoFromChannelWithData :: Channel -> ChannelMember -> ChannelInfo -> ChannelInfo
channelInfoFromChannelWithData Channel
chan ChannelMember
chanMember ChannelInfo
ci =
    let viewed :: ServerTime
viewed   = ChannelMember
chanMember ChannelMember
-> Getting ServerTime ChannelMember ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^. (ChannelMember -> ServerTime)
-> SimpleGetter ChannelMember ServerTime
forall s a. (s -> a) -> SimpleGetter s a
to ChannelMember -> ServerTime
channelMemberLastViewedAt
        updated :: ServerTime
updated  = Channel
chan Channel -> Getting ServerTime Channel ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^. Getting ServerTime Channel ServerTime
Lens' Channel ServerTime
channelLastPostAtL
    in ChannelInfo
ci { _cdViewed :: Maybe ServerTime
_cdViewed           = ServerTime -> Maybe ServerTime
forall a. a -> Maybe a
Just ServerTime
viewed
          , _cdNewMessageIndicator :: NewMessageIndicator
_cdNewMessageIndicator = case ChannelInfo -> NewMessageIndicator
_cdNewMessageIndicator ChannelInfo
ci of
              NewMessageIndicator
Hide -> if ServerTime
updated ServerTime -> ServerTime -> Bool
forall a. Ord a => a -> a -> Bool
> ServerTime
viewed then ServerTime -> NewMessageIndicator
NewPostsAfterServerTime ServerTime
viewed else NewMessageIndicator
Hide
              NewMessageIndicator
v -> NewMessageIndicator
v
          , _cdUpdated :: ServerTime
_cdUpdated          = ServerTime
updated
          , _cdName :: Text
_cdName             = Channel -> Text
preferredChannelName Channel
chan
          , _cdDisplayName :: Text
_cdDisplayName      = UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel -> UserText
channelDisplayName Channel
chan
          , _cdHeader :: Text
_cdHeader           = (UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel
chanChannel -> Getting UserText Channel UserText -> UserText
forall s a. s -> Getting a s a -> a
^.Getting UserText Channel UserText
Lens' Channel UserText
channelHeaderL)
          , _cdPurpose :: Text
_cdPurpose          = (UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel
chanChannel -> Getting UserText Channel UserText -> UserText
forall s a. s -> Getting a s a -> a
^.Getting UserText Channel UserText
Lens' Channel UserText
channelPurposeL)
          , _cdType :: Type
_cdType             = (Channel
chanChannel -> Getting Type Channel Type -> Type
forall s a. s -> Getting a s a -> a
^.Getting Type Channel Type
Lens' Channel Type
channelTypeL)
          , _cdMentionCount :: Int
_cdMentionCount     = ChannelMember
chanMemberChannelMember -> Getting Int ChannelMember Int -> Int
forall s a. s -> Getting a s a -> a
^.(ChannelMember -> Int) -> SimpleGetter ChannelMember Int
forall s a. (s -> a) -> SimpleGetter s a
to ChannelMember -> Int
channelMemberMentionCount
          , _cdNotifyProps :: ChannelNotifyProps
_cdNotifyProps      = ChannelMember
chanMemberChannelMember
-> Getting ChannelNotifyProps ChannelMember ChannelNotifyProps
-> ChannelNotifyProps
forall s a. s -> Getting a s a -> a
^.(ChannelMember -> ChannelNotifyProps)
-> SimpleGetter ChannelMember ChannelNotifyProps
forall s a. (s -> a) -> SimpleGetter s a
to ChannelMember -> ChannelNotifyProps
channelMemberNotifyProps
          }

-- | The 'ChannelContents' is a wrapper for a list of
--   'Message' values
data ChannelContents = ChannelContents
  { ChannelContents -> Messages
_cdMessages :: Messages
  , ChannelContents -> Bool
_cdFetchPending :: Bool
  }

-- | An initial empty 'ChannelContents' value.  This also contains an
-- UnknownGapBefore, which is a signal that causes actual content fetching.
-- The initial Gap's timestamp is the local client time, but
-- subsequent fetches will synchronize with the server (and eventually
-- eliminate this Gap as well).
emptyChannelContents :: MonadIO m => m ChannelContents
emptyChannelContents :: m ChannelContents
emptyChannelContents = do
  Message
gapMsg <- ClientMessage -> Message
clientMessageToMessage (ClientMessage -> Message) -> m ClientMessage -> m Message
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ClientMessageType -> Text -> m ClientMessage
forall (m :: * -> *).
MonadIO m =>
ClientMessageType -> Text -> m ClientMessage
newClientMessage ClientMessageType
UnknownGapBefore Text
"--Fetching messages--"
  ChannelContents -> m ChannelContents
forall (m :: * -> *) a. Monad m => a -> m a
return (ChannelContents -> m ChannelContents)
-> ChannelContents -> m ChannelContents
forall a b. (a -> b) -> a -> b
$ ChannelContents :: Messages -> Bool -> ChannelContents
ChannelContents { _cdMessages :: Messages
_cdMessages = Message -> Messages -> Messages
forall a. MessageOps a => Message -> a -> a
addMessage Message
gapMsg Messages
noMessages
                           , _cdFetchPending :: Bool
_cdFetchPending = Bool
False
                           }


------------------------------------------------------------------------

-- | The 'ChannelInfo' record represents metadata
--   about a channel
data ChannelInfo = ChannelInfo
  { ChannelInfo -> ChannelId
_cdChannelId        :: ChannelId
    -- ^ The channel's ID
  , ChannelInfo -> Maybe TeamId
_cdTeamId           :: Maybe TeamId
    -- ^ The channel's team ID
  , ChannelInfo -> Maybe ServerTime
_cdViewed           :: Maybe ServerTime
    -- ^ The last time we looked at a channel
  , ChannelInfo -> NewMessageIndicator
_cdNewMessageIndicator :: NewMessageIndicator
    -- ^ The state of the channel's new message indicator.
  , ChannelInfo -> Maybe ServerTime
_cdEditedMessageThreshold :: Maybe ServerTime
    -- ^ The channel's edited message threshold.
  , ChannelInfo -> Int
_cdMentionCount     :: Int
    -- ^ The current number of unread mentions
  , ChannelInfo -> ServerTime
_cdUpdated          :: ServerTime
    -- ^ The last time a message showed up in the channel
  , ChannelInfo -> Text
_cdName             :: Text
    -- ^ The name of the channel
  , ChannelInfo -> Text
_cdDisplayName      :: Text
    -- ^ The display name of the channel
  , ChannelInfo -> Text
_cdHeader           :: Text
    -- ^ The header text of a channel
  , ChannelInfo -> Text
_cdPurpose          :: Text
    -- ^ The stated purpose of the channel
  , ChannelInfo -> Type
_cdType             :: Type
    -- ^ The type of a channel: public, private, or DM
  , ChannelInfo -> ChannelNotifyProps
_cdNotifyProps      :: ChannelNotifyProps
    -- ^ The user's notification settings for this channel
  , ChannelInfo -> TypingUsers
_cdTypingUsers      :: TypingUsers
    -- ^ The users who are currently typing in this channel
  , ChannelInfo -> Maybe UserId
_cdDMUserId         :: Maybe UserId
    -- ^ The user associated with this channel, if it is a DM channel
  , ChannelInfo -> Maybe UTCTime
_cdSidebarShowOverride :: Maybe UTCTime
    -- ^ If set, show this channel in the sidebar regardless of other
    -- considerations as long as the specified timestamp meets a cutoff.
    -- Otherwise fall back to other application policy to determine
    -- whether to show the channel.
  }

-- ** Channel-related Lenses

makeLenses ''ChannelContents
makeLenses ''ChannelInfo
makeLenses ''ClientChannel
makeLenses ''EphemeralEditState

isMuted :: ClientChannel -> Bool
isMuted :: ClientChannel -> Bool
isMuted ClientChannel
cc = ClientChannel
ccClientChannel
-> Getting
     (WithDefault NotifyOption) ClientChannel (WithDefault NotifyOption)
-> WithDefault NotifyOption
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> ClientChannel -> Const (WithDefault NotifyOption) ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
 -> ClientChannel -> Const (WithDefault NotifyOption) ClientChannel)
-> ((WithDefault NotifyOption
     -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
    -> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> Getting
     (WithDefault NotifyOption) ClientChannel (WithDefault NotifyOption)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ChannelNotifyProps
 -> Const (WithDefault NotifyOption) ChannelNotifyProps)
-> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo
Lens' ChannelInfo ChannelNotifyProps
cdNotifyProps((ChannelNotifyProps
  -> Const (WithDefault NotifyOption) ChannelNotifyProps)
 -> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> ((WithDefault NotifyOption
     -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
    -> ChannelNotifyProps
    -> Const (WithDefault NotifyOption) ChannelNotifyProps)
-> (WithDefault NotifyOption
    -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
-> ChannelInfo
-> Const (WithDefault NotifyOption) ChannelInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(WithDefault NotifyOption
 -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
-> ChannelNotifyProps
-> Const (WithDefault NotifyOption) ChannelNotifyProps
Lens' ChannelNotifyProps (WithDefault NotifyOption)
channelNotifyPropsMarkUnreadL WithDefault NotifyOption -> WithDefault NotifyOption -> Bool
forall a. Eq a => a -> a -> Bool
==
             NotifyOption -> WithDefault NotifyOption
forall a. a -> WithDefault a
IsValue NotifyOption
NotifyOptionMention

notifyPreference :: User -> ClientChannel -> NotifyOption
notifyPreference :: User -> ClientChannel -> NotifyOption
notifyPreference User
u ClientChannel
cc =
    if ClientChannel -> Bool
isMuted ClientChannel
cc then NotifyOption
NotifyOptionNone
    else case ClientChannel
ccClientChannel
-> Getting
     (WithDefault NotifyOption) ClientChannel (WithDefault NotifyOption)
-> WithDefault NotifyOption
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> ClientChannel -> Const (WithDefault NotifyOption) ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
 -> ClientChannel -> Const (WithDefault NotifyOption) ClientChannel)
-> ((WithDefault NotifyOption
     -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
    -> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> Getting
     (WithDefault NotifyOption) ClientChannel (WithDefault NotifyOption)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ChannelNotifyProps
 -> Const (WithDefault NotifyOption) ChannelNotifyProps)
-> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo
Lens' ChannelInfo ChannelNotifyProps
cdNotifyProps((ChannelNotifyProps
  -> Const (WithDefault NotifyOption) ChannelNotifyProps)
 -> ChannelInfo -> Const (WithDefault NotifyOption) ChannelInfo)
-> ((WithDefault NotifyOption
     -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
    -> ChannelNotifyProps
    -> Const (WithDefault NotifyOption) ChannelNotifyProps)
-> (WithDefault NotifyOption
    -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
-> ChannelInfo
-> Const (WithDefault NotifyOption) ChannelInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(WithDefault NotifyOption
 -> Const (WithDefault NotifyOption) (WithDefault NotifyOption))
-> ChannelNotifyProps
-> Const (WithDefault NotifyOption) ChannelNotifyProps
Lens' ChannelNotifyProps (WithDefault NotifyOption)
channelNotifyPropsDesktopL of
             IsValue NotifyOption
v -> NotifyOption
v
             WithDefault NotifyOption
Default   -> (User -> UserNotifyProps
userNotifyProps User
u)UserNotifyProps
-> Getting NotifyOption UserNotifyProps NotifyOption
-> NotifyOption
forall s a. s -> Getting a s a -> a
^.Getting NotifyOption UserNotifyProps NotifyOption
Lens' UserNotifyProps NotifyOption
userNotifyPropsDesktopL

-- ** Miscellaneous channel operations

makeClientChannel :: (MonadIO m) => UserId -> Channel -> m ClientChannel
makeClientChannel :: UserId -> Channel -> m ClientChannel
makeClientChannel UserId
myId Channel
nc = m ChannelContents
forall (m :: * -> *). MonadIO m => m ChannelContents
emptyChannelContents m ChannelContents
-> (ChannelContents -> m ClientChannel) -> m ClientChannel
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ChannelContents
contents ->
  ClientChannel -> m ClientChannel
forall (m :: * -> *) a. Monad m => a -> m a
return ClientChannel :: ChannelContents
-> ChannelInfo -> EphemeralEditState -> ClientChannel
ClientChannel
  { _ccContents :: ChannelContents
_ccContents = ChannelContents
contents
  , _ccInfo :: ChannelInfo
_ccInfo = UserId -> Channel -> ChannelInfo
initialChannelInfo UserId
myId Channel
nc
  , _ccEditState :: EphemeralEditState
_ccEditState = EphemeralEditState
defaultEphemeralEditState
  }

defaultEphemeralEditState :: EphemeralEditState
defaultEphemeralEditState :: EphemeralEditState
defaultEphemeralEditState =
    EphemeralEditState :: Bool -> Maybe Int -> (Text, EditMode) -> EphemeralEditState
EphemeralEditState { _eesMultiline :: Bool
_eesMultiline = Bool
False
                       , _eesInputHistoryPosition :: Maybe Int
_eesInputHistoryPosition = Maybe Int
forall a. Maybe a
Nothing
                       , _eesLastInput :: (Text, EditMode)
_eesLastInput = (Text
"", EditMode
NewPost)
                       }

canLeaveChannel :: ChannelInfo -> Bool
canLeaveChannel :: ChannelInfo -> Bool
canLeaveChannel ChannelInfo
cInfo = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ChannelInfo
cInfoChannelInfo -> Getting Type ChannelInfo Type -> Type
forall s a. s -> Getting a s a -> a
^.Getting Type ChannelInfo Type
Lens' ChannelInfo Type
cdType Type -> [Type] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Type
Direct]

-- ** Manage the collection of all Channels

-- | Define a binary kinded type to allow derivation of functor.
data AllMyChannels a =
    AllChannels { AllMyChannels a -> HashMap ChannelId a
_chanMap :: HashMap ChannelId a
                , AllMyChannels a -> HashMap TeamId (Set Text)
_channelNameSet :: HashMap TeamId (S.Set Text)
                , AllMyChannels a -> HashMap UserId ChannelId
_userChannelMap :: HashMap UserId ChannelId
                }
                deriving (a -> AllMyChannels b -> AllMyChannels a
(a -> b) -> AllMyChannels a -> AllMyChannels b
(forall a b. (a -> b) -> AllMyChannels a -> AllMyChannels b)
-> (forall a b. a -> AllMyChannels b -> AllMyChannels a)
-> Functor AllMyChannels
forall a b. a -> AllMyChannels b -> AllMyChannels a
forall a b. (a -> b) -> AllMyChannels a -> AllMyChannels b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> AllMyChannels b -> AllMyChannels a
$c<$ :: forall a b. a -> AllMyChannels b -> AllMyChannels a
fmap :: (a -> b) -> AllMyChannels a -> AllMyChannels b
$cfmap :: forall a b. (a -> b) -> AllMyChannels a -> AllMyChannels b
Functor, AllMyChannels a -> Bool
(a -> m) -> AllMyChannels a -> m
(a -> b -> b) -> b -> AllMyChannels a -> b
(forall m. Monoid m => AllMyChannels m -> m)
-> (forall m a. Monoid m => (a -> m) -> AllMyChannels a -> m)
-> (forall m a. Monoid m => (a -> m) -> AllMyChannels a -> m)
-> (forall a b. (a -> b -> b) -> b -> AllMyChannels a -> b)
-> (forall a b. (a -> b -> b) -> b -> AllMyChannels a -> b)
-> (forall b a. (b -> a -> b) -> b -> AllMyChannels a -> b)
-> (forall b a. (b -> a -> b) -> b -> AllMyChannels a -> b)
-> (forall a. (a -> a -> a) -> AllMyChannels a -> a)
-> (forall a. (a -> a -> a) -> AllMyChannels a -> a)
-> (forall a. AllMyChannels a -> [a])
-> (forall a. AllMyChannels a -> Bool)
-> (forall a. AllMyChannels a -> Int)
-> (forall a. Eq a => a -> AllMyChannels a -> Bool)
-> (forall a. Ord a => AllMyChannels a -> a)
-> (forall a. Ord a => AllMyChannels a -> a)
-> (forall a. Num a => AllMyChannels a -> a)
-> (forall a. Num a => AllMyChannels a -> a)
-> Foldable AllMyChannels
forall a. Eq a => a -> AllMyChannels a -> Bool
forall a. Num a => AllMyChannels a -> a
forall a. Ord a => AllMyChannels a -> a
forall m. Monoid m => AllMyChannels m -> m
forall a. AllMyChannels a -> Bool
forall a. AllMyChannels a -> Int
forall a. AllMyChannels a -> [a]
forall a. (a -> a -> a) -> AllMyChannels a -> a
forall m a. Monoid m => (a -> m) -> AllMyChannels a -> m
forall b a. (b -> a -> b) -> b -> AllMyChannels a -> b
forall a b. (a -> b -> b) -> b -> AllMyChannels a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: AllMyChannels a -> a
$cproduct :: forall a. Num a => AllMyChannels a -> a
sum :: AllMyChannels a -> a
$csum :: forall a. Num a => AllMyChannels a -> a
minimum :: AllMyChannels a -> a
$cminimum :: forall a. Ord a => AllMyChannels a -> a
maximum :: AllMyChannels a -> a
$cmaximum :: forall a. Ord a => AllMyChannels a -> a
elem :: a -> AllMyChannels a -> Bool
$celem :: forall a. Eq a => a -> AllMyChannels a -> Bool
length :: AllMyChannels a -> Int
$clength :: forall a. AllMyChannels a -> Int
null :: AllMyChannels a -> Bool
$cnull :: forall a. AllMyChannels a -> Bool
toList :: AllMyChannels a -> [a]
$ctoList :: forall a. AllMyChannels a -> [a]
foldl1 :: (a -> a -> a) -> AllMyChannels a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> AllMyChannels a -> a
foldr1 :: (a -> a -> a) -> AllMyChannels a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> AllMyChannels a -> a
foldl' :: (b -> a -> b) -> b -> AllMyChannels a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> AllMyChannels a -> b
foldl :: (b -> a -> b) -> b -> AllMyChannels a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> AllMyChannels a -> b
foldr' :: (a -> b -> b) -> b -> AllMyChannels a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> AllMyChannels a -> b
foldr :: (a -> b -> b) -> b -> AllMyChannels a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> AllMyChannels a -> b
foldMap' :: (a -> m) -> AllMyChannels a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> AllMyChannels a -> m
foldMap :: (a -> m) -> AllMyChannels a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> AllMyChannels a -> m
fold :: AllMyChannels m -> m
$cfold :: forall m. Monoid m => AllMyChannels m -> m
Foldable, Functor AllMyChannels
Foldable AllMyChannels
Functor AllMyChannels
-> Foldable AllMyChannels
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> AllMyChannels a -> f (AllMyChannels b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    AllMyChannels (f a) -> f (AllMyChannels a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> AllMyChannels a -> m (AllMyChannels b))
-> (forall (m :: * -> *) a.
    Monad m =>
    AllMyChannels (m a) -> m (AllMyChannels a))
-> Traversable AllMyChannels
(a -> f b) -> AllMyChannels a -> f (AllMyChannels b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
AllMyChannels (m a) -> m (AllMyChannels a)
forall (f :: * -> *) a.
Applicative f =>
AllMyChannels (f a) -> f (AllMyChannels a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> AllMyChannels a -> m (AllMyChannels b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> AllMyChannels a -> f (AllMyChannels b)
sequence :: AllMyChannels (m a) -> m (AllMyChannels a)
$csequence :: forall (m :: * -> *) a.
Monad m =>
AllMyChannels (m a) -> m (AllMyChannels a)
mapM :: (a -> m b) -> AllMyChannels a -> m (AllMyChannels b)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> AllMyChannels a -> m (AllMyChannels b)
sequenceA :: AllMyChannels (f a) -> f (AllMyChannels a)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
AllMyChannels (f a) -> f (AllMyChannels a)
traverse :: (a -> f b) -> AllMyChannels a -> f (AllMyChannels b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> AllMyChannels a -> f (AllMyChannels b)
$cp2Traversable :: Foldable AllMyChannels
$cp1Traversable :: Functor AllMyChannels
Traversable)

-- | Define the exported typename which universally binds the
-- collection to the ChannelInfo type.
type ClientChannels = AllMyChannels ClientChannel

makeLenses ''AllMyChannels

getChannelNameSet :: TeamId -> ClientChannels -> S.Set Text
getChannelNameSet :: TeamId -> ClientChannels -> Set Text
getChannelNameSet TeamId
tId ClientChannels
cs = case ClientChannels
csClientChannels
-> Getting (Maybe (Set Text)) ClientChannels (Maybe (Set Text))
-> Maybe (Set Text)
forall s a. s -> Getting a s a -> a
^.(HashMap TeamId (Set Text)
 -> Const (Maybe (Set Text)) (HashMap TeamId (Set Text)))
-> ClientChannels -> Const (Maybe (Set Text)) ClientChannels
forall a. Lens' (AllMyChannels a) (HashMap TeamId (Set Text))
channelNameSet((HashMap TeamId (Set Text)
  -> Const (Maybe (Set Text)) (HashMap TeamId (Set Text)))
 -> ClientChannels -> Const (Maybe (Set Text)) ClientChannels)
-> ((Maybe (Set Text)
     -> Const (Maybe (Set Text)) (Maybe (Set Text)))
    -> HashMap TeamId (Set Text)
    -> Const (Maybe (Set Text)) (HashMap TeamId (Set Text)))
-> Getting (Maybe (Set Text)) ClientChannels (Maybe (Set Text))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Index (HashMap TeamId (Set Text))
-> Lens'
     (HashMap TeamId (Set Text))
     (Maybe (IxValue (HashMap TeamId (Set Text))))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at TeamId
Index (HashMap TeamId (Set Text))
tId of
    Maybe (Set Text)
Nothing -> Set Text
forall a. Monoid a => a
mempty
    Just Set Text
s -> Set Text
s

-- | Initial collection of Channels with no members
noChannels :: ClientChannels
noChannels :: ClientChannels
noChannels = HashMap ChannelId ClientChannel
-> HashMap TeamId (Set Text)
-> HashMap UserId ChannelId
-> ClientChannels
forall a.
HashMap ChannelId a
-> HashMap TeamId (Set Text)
-> HashMap UserId ChannelId
-> AllMyChannels a
AllChannels HashMap ChannelId ClientChannel
forall k v. HashMap k v
HM.empty HashMap TeamId (Set Text)
forall k v. HashMap k v
HM.empty HashMap UserId ChannelId
forall k v. HashMap k v
HM.empty

-- | Add a channel to the existing collection.
addChannel :: ChannelId -> ClientChannel -> ClientChannels -> ClientChannels
addChannel :: ChannelId -> ClientChannel -> ClientChannels -> ClientChannels
addChannel ChannelId
cId ClientChannel
cinfo =
    ((HashMap ChannelId ClientChannel
 -> Identity (HashMap ChannelId ClientChannel))
-> ClientChannels -> Identity ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap ((HashMap ChannelId ClientChannel
  -> Identity (HashMap ChannelId ClientChannel))
 -> ClientChannels -> Identity ClientChannels)
-> (HashMap ChannelId ClientChannel
    -> HashMap ChannelId ClientChannel)
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ ChannelId
-> ClientChannel
-> HashMap ChannelId ClientChannel
-> HashMap ChannelId ClientChannel
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert ChannelId
cId ClientChannel
cinfo) (ClientChannels -> ClientChannels)
-> (ClientChannels -> ClientChannels)
-> ClientChannels
-> ClientChannels
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (if ClientChannel
cinfoClientChannel -> Getting Type ClientChannel Type -> Type
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const Type ChannelInfo)
-> ClientChannel -> Const Type ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const Type ChannelInfo)
 -> ClientChannel -> Const Type ClientChannel)
-> Getting Type ChannelInfo Type -> Getting Type ClientChannel Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Getting Type ChannelInfo Type
Lens' ChannelInfo Type
cdType Type -> [Type] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Type
Direct, Type
Group]
     then case ClientChannel
cinfoClientChannel
-> Getting (Maybe TeamId) ClientChannel (Maybe TeamId)
-> Maybe TeamId
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
-> ClientChannel -> Const (Maybe TeamId) ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
 -> ClientChannel -> Const (Maybe TeamId) ClientChannel)
-> ((Maybe TeamId -> Const (Maybe TeamId) (Maybe TeamId))
    -> ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
-> Getting (Maybe TeamId) ClientChannel (Maybe TeamId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe TeamId -> Const (Maybe TeamId) (Maybe TeamId))
-> ChannelInfo -> Const (Maybe TeamId) ChannelInfo
Lens' ChannelInfo (Maybe TeamId)
cdTeamId of
         Maybe TeamId
Nothing -> ClientChannels -> ClientChannels
forall a. a -> a
id
         Just TeamId
tId -> (HashMap TeamId (Set Text) -> Identity (HashMap TeamId (Set Text)))
-> ClientChannels -> Identity ClientChannels
forall a. Lens' (AllMyChannels a) (HashMap TeamId (Set Text))
channelNameSet ((HashMap TeamId (Set Text)
  -> Identity (HashMap TeamId (Set Text)))
 -> ClientChannels -> Identity ClientChannels)
-> (HashMap TeamId (Set Text) -> HashMap TeamId (Set Text))
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (Set Text -> Set Text -> Set Text)
-> TeamId
-> Set Text
-> HashMap TeamId (Set Text)
-> HashMap TeamId (Set Text)
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
HM.insertWith Set Text -> Set Text -> Set Text
forall a. Ord a => Set a -> Set a -> Set a
S.union TeamId
tId (Text -> Set Text
forall a. a -> Set a
S.singleton (Text -> Set Text) -> Text -> Set Text
forall a b. (a -> b) -> a -> b
$ ClientChannel
cinfoClientChannel -> Getting Text ClientChannel Text -> Text
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const Text ChannelInfo)
-> ClientChannel -> Const Text ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const Text ChannelInfo)
 -> ClientChannel -> Const Text ClientChannel)
-> ((Text -> Const Text Text)
    -> ChannelInfo -> Const Text ChannelInfo)
-> Getting Text ClientChannel Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Text -> Const Text Text) -> ChannelInfo -> Const Text ChannelInfo
Lens' ChannelInfo Text
cdName)
     else ClientChannels -> ClientChannels
forall a. a -> a
id) (ClientChannels -> ClientChannels)
-> (ClientChannels -> ClientChannels)
-> ClientChannels
-> ClientChannels
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (case ClientChannel
cinfoClientChannel
-> Getting (Maybe UserId) ClientChannel (Maybe UserId)
-> Maybe UserId
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const (Maybe UserId) ChannelInfo)
-> ClientChannel -> Const (Maybe UserId) ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const (Maybe UserId) ChannelInfo)
 -> ClientChannel -> Const (Maybe UserId) ClientChannel)
-> ((Maybe UserId -> Const (Maybe UserId) (Maybe UserId))
    -> ChannelInfo -> Const (Maybe UserId) ChannelInfo)
-> Getting (Maybe UserId) ClientChannel (Maybe UserId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe UserId -> Const (Maybe UserId) (Maybe UserId))
-> ChannelInfo -> Const (Maybe UserId) ChannelInfo
Lens' ChannelInfo (Maybe UserId)
cdDMUserId of
         Maybe UserId
Nothing -> ClientChannels -> ClientChannels
forall a. a -> a
id
         Just UserId
uId -> (HashMap UserId ChannelId -> Identity (HashMap UserId ChannelId))
-> ClientChannels -> Identity ClientChannels
forall a. Lens' (AllMyChannels a) (HashMap UserId ChannelId)
userChannelMap ((HashMap UserId ChannelId -> Identity (HashMap UserId ChannelId))
 -> ClientChannels -> Identity ClientChannels)
-> (HashMap UserId ChannelId -> HashMap UserId ChannelId)
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ UserId
-> ChannelId
-> HashMap UserId ChannelId
-> HashMap UserId ChannelId
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert UserId
uId ChannelId
cId
    )

-- | Remove a channel from the collection.
removeChannel :: ChannelId -> ClientChannels -> ClientChannels
removeChannel :: ChannelId -> ClientChannels -> ClientChannels
removeChannel ChannelId
cId ClientChannels
cs =
    let mChan :: Maybe ClientChannel
mChan = ChannelId -> ClientChannels -> Maybe ClientChannel
findChannelById ChannelId
cId ClientChannels
cs
        removeChannelName :: AllMyChannels a -> AllMyChannels a
removeChannelName = case Maybe ClientChannel
mChan of
            Maybe ClientChannel
Nothing -> AllMyChannels a -> AllMyChannels a
forall a. a -> a
id
            Just ClientChannel
ch -> case ClientChannel
chClientChannel
-> Getting (Maybe TeamId) ClientChannel (Maybe TeamId)
-> Maybe TeamId
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
-> ClientChannel -> Const (Maybe TeamId) ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
 -> ClientChannel -> Const (Maybe TeamId) ClientChannel)
-> ((Maybe TeamId -> Const (Maybe TeamId) (Maybe TeamId))
    -> ChannelInfo -> Const (Maybe TeamId) ChannelInfo)
-> Getting (Maybe TeamId) ClientChannel (Maybe TeamId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe TeamId -> Const (Maybe TeamId) (Maybe TeamId))
-> ChannelInfo -> Const (Maybe TeamId) ChannelInfo
Lens' ChannelInfo (Maybe TeamId)
cdTeamId of
                Maybe TeamId
Nothing -> AllMyChannels a -> AllMyChannels a
forall a. a -> a
id
                Just TeamId
tId -> (HashMap TeamId (Set Text) -> Identity (HashMap TeamId (Set Text)))
-> AllMyChannels a -> Identity (AllMyChannels a)
forall a. Lens' (AllMyChannels a) (HashMap TeamId (Set Text))
channelNameSet ((HashMap TeamId (Set Text)
  -> Identity (HashMap TeamId (Set Text)))
 -> AllMyChannels a -> Identity (AllMyChannels a))
-> (HashMap TeamId (Set Text) -> HashMap TeamId (Set Text))
-> AllMyChannels a
-> AllMyChannels a
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (Set Text -> Set Text)
-> TeamId -> HashMap TeamId (Set Text) -> HashMap TeamId (Set Text)
forall k v.
(Eq k, Hashable k) =>
(v -> v) -> k -> HashMap k v -> HashMap k v
HM.adjust (Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
S.delete (ClientChannel
chClientChannel -> Getting Text ClientChannel Text -> Text
forall s a. s -> Getting a s a -> a
^.(ChannelInfo -> Const Text ChannelInfo)
-> ClientChannel -> Const Text ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Const Text ChannelInfo)
 -> ClientChannel -> Const Text ClientChannel)
-> ((Text -> Const Text Text)
    -> ChannelInfo -> Const Text ChannelInfo)
-> Getting Text ClientChannel Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Text -> Const Text Text) -> ChannelInfo -> Const Text ChannelInfo
Lens' ChannelInfo Text
cdName)) TeamId
tId
    in ClientChannels
cs ClientChannels
-> (ClientChannels -> ClientChannels) -> ClientChannels
forall a b. a -> (a -> b) -> b
& (HashMap ChannelId ClientChannel
 -> Identity (HashMap ChannelId ClientChannel))
-> ClientChannels -> Identity ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap ((HashMap ChannelId ClientChannel
  -> Identity (HashMap ChannelId ClientChannel))
 -> ClientChannels -> Identity ClientChannels)
-> (HashMap ChannelId ClientChannel
    -> HashMap ChannelId ClientChannel)
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ ChannelId
-> HashMap ChannelId ClientChannel
-> HashMap ChannelId ClientChannel
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete ChannelId
cId
          ClientChannels
-> (ClientChannels -> ClientChannels) -> ClientChannels
forall a b. a -> (a -> b) -> b
& ClientChannels -> ClientChannels
forall a. AllMyChannels a -> AllMyChannels a
removeChannelName
          ClientChannels
-> (ClientChannels -> ClientChannels) -> ClientChannels
forall a b. a -> (a -> b) -> b
& (HashMap UserId ChannelId -> Identity (HashMap UserId ChannelId))
-> ClientChannels -> Identity ClientChannels
forall a. Lens' (AllMyChannels a) (HashMap UserId ChannelId)
userChannelMap ((HashMap UserId ChannelId -> Identity (HashMap UserId ChannelId))
 -> ClientChannels -> Identity ClientChannels)
-> (HashMap UserId ChannelId -> HashMap UserId ChannelId)
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (ChannelId -> Bool)
-> HashMap UserId ChannelId -> HashMap UserId ChannelId
forall v k. (v -> Bool) -> HashMap k v -> HashMap k v
HM.filter (ChannelId -> ChannelId -> Bool
forall a. Eq a => a -> a -> Bool
/= ChannelId
cId)

instance Semigroup (AllMyChannels ClientChannel) where
    ClientChannels
a <> :: ClientChannels -> ClientChannels -> ClientChannels
<> ClientChannels
b =
        let pairs :: [(ChannelId, ClientChannel)]
pairs = HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)]
forall k v. HashMap k v -> [(k, v)]
HM.toList (HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)])
-> HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)]
forall a b. (a -> b) -> a -> b
$ ClientChannels -> HashMap ChannelId ClientChannel
forall a. AllMyChannels a -> HashMap ChannelId a
_chanMap ClientChannels
a
        in ((ChannelId, ClientChannel) -> ClientChannels -> ClientChannels)
-> ClientChannels -> [(ChannelId, ClientChannel)] -> ClientChannels
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((ChannelId -> ClientChannel -> ClientChannels -> ClientChannels)
-> (ChannelId, ClientChannel) -> ClientChannels -> ClientChannels
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ChannelId -> ClientChannel -> ClientChannels -> ClientChannels
addChannel) ClientChannels
b [(ChannelId, ClientChannel)]
pairs

instance Monoid (AllMyChannels ClientChannel) where
    mempty :: ClientChannels
mempty = ClientChannels
noChannels
#if !MIN_VERSION_base(4,11,0)
    mappend = (<>)
#endif

getDmChannelFor :: UserId -> ClientChannels -> Maybe ChannelId
getDmChannelFor :: UserId -> ClientChannels -> Maybe ChannelId
getDmChannelFor UserId
uId ClientChannels
cs = ClientChannels
csClientChannels
-> Getting (Maybe ChannelId) ClientChannels (Maybe ChannelId)
-> Maybe ChannelId
forall s a. s -> Getting a s a -> a
^.(HashMap UserId ChannelId
 -> Const (Maybe ChannelId) (HashMap UserId ChannelId))
-> ClientChannels -> Const (Maybe ChannelId) ClientChannels
forall a. Lens' (AllMyChannels a) (HashMap UserId ChannelId)
userChannelMap((HashMap UserId ChannelId
  -> Const (Maybe ChannelId) (HashMap UserId ChannelId))
 -> ClientChannels -> Const (Maybe ChannelId) ClientChannels)
-> ((Maybe ChannelId -> Const (Maybe ChannelId) (Maybe ChannelId))
    -> HashMap UserId ChannelId
    -> Const (Maybe ChannelId) (HashMap UserId ChannelId))
-> Getting (Maybe ChannelId) ClientChannels (Maybe ChannelId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Index (HashMap UserId ChannelId)
-> Lens'
     (HashMap UserId ChannelId)
     (Maybe (IxValue (HashMap UserId ChannelId)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at UserId
Index (HashMap UserId ChannelId)
uId

allDmChannelMappings :: ClientChannels -> [(UserId, ChannelId)]
allDmChannelMappings :: ClientChannels -> [(UserId, ChannelId)]
allDmChannelMappings = HashMap UserId ChannelId -> [(UserId, ChannelId)]
forall k v. HashMap k v -> [(k, v)]
HM.toList (HashMap UserId ChannelId -> [(UserId, ChannelId)])
-> (ClientChannels -> HashMap UserId ChannelId)
-> ClientChannels
-> [(UserId, ChannelId)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientChannels -> HashMap UserId ChannelId
forall a. AllMyChannels a -> HashMap UserId ChannelId
_userChannelMap

-- | Get the ChannelInfo information given the ChannelId
findChannelById :: ChannelId -> ClientChannels -> Maybe ClientChannel
findChannelById :: ChannelId -> ClientChannels -> Maybe ClientChannel
findChannelById ChannelId
cId = ChannelId -> HashMap ChannelId ClientChannel -> Maybe ClientChannel
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup ChannelId
cId (HashMap ChannelId ClientChannel -> Maybe ClientChannel)
-> (ClientChannels -> HashMap ChannelId ClientChannel)
-> ClientChannels
-> Maybe ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ClientChannels -> HashMap ChannelId ClientChannel
forall a. AllMyChannels a -> HashMap ChannelId a
_chanMap

-- | Transform the specified channel in place with provided function.
modifyChannelById :: ChannelId -> (ClientChannel -> ClientChannel)
                  -> ClientChannels -> ClientChannels
modifyChannelById :: ChannelId
-> (ClientChannel -> ClientChannel)
-> ClientChannels
-> ClientChannels
modifyChannelById ChannelId
cId ClientChannel -> ClientChannel
f = (HashMap ChannelId ClientChannel
 -> Identity (HashMap ChannelId ClientChannel))
-> ClientChannels -> Identity ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap((HashMap ChannelId ClientChannel
  -> Identity (HashMap ChannelId ClientChannel))
 -> ClientChannels -> Identity ClientChannels)
-> ((ClientChannel -> Identity ClientChannel)
    -> HashMap ChannelId ClientChannel
    -> Identity (HashMap ChannelId ClientChannel))
-> (ClientChannel -> Identity ClientChannel)
-> ClientChannels
-> Identity ClientChannels
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Index (HashMap ChannelId ClientChannel)
-> Traversal'
     (HashMap ChannelId ClientChannel)
     (IxValue (HashMap ChannelId ClientChannel))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix(ChannelId
Index (HashMap ChannelId ClientChannel)
cId) ((ClientChannel -> Identity ClientChannel)
 -> ClientChannels -> Identity ClientChannels)
-> (ClientChannel -> ClientChannel)
-> ClientChannels
-> ClientChannels
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ ClientChannel -> ClientChannel
f

-- | A 'Traversal' that will give us the 'ClientChannel' in a
-- 'ClientChannels' structure if it exists
channelByIdL :: ChannelId -> Traversal' ClientChannels ClientChannel
channelByIdL :: ChannelId -> Traversal' ClientChannels ClientChannel
channelByIdL ChannelId
cId = (HashMap ChannelId ClientChannel
 -> f (HashMap ChannelId ClientChannel))
-> ClientChannels -> f ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap ((HashMap ChannelId ClientChannel
  -> f (HashMap ChannelId ClientChannel))
 -> ClientChannels -> f ClientChannels)
-> ((ClientChannel -> f ClientChannel)
    -> HashMap ChannelId ClientChannel
    -> f (HashMap ChannelId ClientChannel))
-> (ClientChannel -> f ClientChannel)
-> ClientChannels
-> f ClientChannels
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap ChannelId ClientChannel)
-> Traversal'
     (HashMap ChannelId ClientChannel)
     (IxValue (HashMap ChannelId ClientChannel))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix ChannelId
Index (HashMap ChannelId ClientChannel)
cId

-- | A 'Lens' that will give us the 'ClientChannel' in a
-- 'ClientChannels' wrapped in a 'Maybe'
maybeChannelByIdL :: ChannelId -> Lens' ClientChannels (Maybe ClientChannel)
maybeChannelByIdL :: ChannelId -> Lens' ClientChannels (Maybe ClientChannel)
maybeChannelByIdL ChannelId
cId = (HashMap ChannelId ClientChannel
 -> f (HashMap ChannelId ClientChannel))
-> ClientChannels -> f ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap ((HashMap ChannelId ClientChannel
  -> f (HashMap ChannelId ClientChannel))
 -> ClientChannels -> f ClientChannels)
-> ((Maybe ClientChannel -> f (Maybe ClientChannel))
    -> HashMap ChannelId ClientChannel
    -> f (HashMap ChannelId ClientChannel))
-> (Maybe ClientChannel -> f (Maybe ClientChannel))
-> ClientChannels
-> f ClientChannels
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap ChannelId ClientChannel)
-> Lens'
     (HashMap ChannelId ClientChannel)
     (Maybe (IxValue (HashMap ChannelId ClientChannel)))
forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at ChannelId
Index (HashMap ChannelId ClientChannel)
cId

-- | Apply a filter to each ClientChannel and return a list of the
-- ChannelId values for which the filter matched.
filteredChannelIds :: (ClientChannel -> Bool) -> ClientChannels -> [ChannelId]
filteredChannelIds :: (ClientChannel -> Bool) -> ClientChannels -> [ChannelId]
filteredChannelIds ClientChannel -> Bool
f ClientChannels
cc = (ChannelId, ClientChannel) -> ChannelId
forall a b. (a, b) -> a
fst ((ChannelId, ClientChannel) -> ChannelId)
-> [(ChannelId, ClientChannel)] -> [ChannelId]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((ChannelId, ClientChannel) -> Bool)
-> [(ChannelId, ClientChannel)] -> [(ChannelId, ClientChannel)]
forall a. (a -> Bool) -> [a] -> [a]
filter (ClientChannel -> Bool
f (ClientChannel -> Bool)
-> ((ChannelId, ClientChannel) -> ClientChannel)
-> (ChannelId, ClientChannel)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ChannelId, ClientChannel) -> ClientChannel
forall a b. (a, b) -> b
snd) (HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)]
forall k v. HashMap k v -> [(k, v)]
HM.toList (ClientChannels
ccClientChannels
-> Getting
     (HashMap ChannelId ClientChannel)
     ClientChannels
     (HashMap ChannelId ClientChannel)
-> HashMap ChannelId ClientChannel
forall s a. s -> Getting a s a -> a
^.Getting
  (HashMap ChannelId ClientChannel)
  ClientChannels
  (HashMap ChannelId ClientChannel)
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap))

-- | Get all the team IDs in the channel collection.
allTeamIds :: ClientChannels -> [TeamId]
allTeamIds :: ClientChannels -> [TeamId]
allTeamIds ClientChannels
cc = HashMap TeamId (Set Text) -> [TeamId]
forall k v. HashMap k v -> [k]
HM.keys (HashMap TeamId (Set Text) -> [TeamId])
-> HashMap TeamId (Set Text) -> [TeamId]
forall a b. (a -> b) -> a -> b
$ ClientChannels
ccClientChannels
-> Getting
     (HashMap TeamId (Set Text))
     ClientChannels
     (HashMap TeamId (Set Text))
-> HashMap TeamId (Set Text)
forall s a. s -> Getting a s a -> a
^.Getting
  (HashMap TeamId (Set Text))
  ClientChannels
  (HashMap TeamId (Set Text))
forall a. Lens' (AllMyChannels a) (HashMap TeamId (Set Text))
channelNameSet

-- | Filter the ClientChannel collection, keeping only those for which
-- the provided filter test function returns True.
filteredChannels :: ((ChannelId, ClientChannel) -> Bool)
                 -> ClientChannels -> [(ChannelId, ClientChannel)]
filteredChannels :: ((ChannelId, ClientChannel) -> Bool)
-> ClientChannels -> [(ChannelId, ClientChannel)]
filteredChannels (ChannelId, ClientChannel) -> Bool
f ClientChannels
cc = ((ChannelId, ClientChannel) -> Bool)
-> [(ChannelId, ClientChannel)] -> [(ChannelId, ClientChannel)]
forall a. (a -> Bool) -> [a] -> [a]
filter (ChannelId, ClientChannel) -> Bool
f ([(ChannelId, ClientChannel)] -> [(ChannelId, ClientChannel)])
-> [(ChannelId, ClientChannel)] -> [(ChannelId, ClientChannel)]
forall a b. (a -> b) -> a -> b
$ ClientChannels
ccClientChannels
-> Getting
     [(ChannelId, ClientChannel)]
     ClientChannels
     [(ChannelId, ClientChannel)]
-> [(ChannelId, ClientChannel)]
forall s a. s -> Getting a s a -> a
^.(HashMap ChannelId ClientChannel
 -> Const
      [(ChannelId, ClientChannel)] (HashMap ChannelId ClientChannel))
-> ClientChannels
-> Const [(ChannelId, ClientChannel)] ClientChannels
forall a a.
Lens
  (AllMyChannels a)
  (AllMyChannels a)
  (HashMap ChannelId a)
  (HashMap ChannelId a)
chanMap((HashMap ChannelId ClientChannel
  -> Const
       [(ChannelId, ClientChannel)] (HashMap ChannelId ClientChannel))
 -> ClientChannels
 -> Const [(ChannelId, ClientChannel)] ClientChannels)
-> (([(ChannelId, ClientChannel)]
     -> Const [(ChannelId, ClientChannel)] [(ChannelId, ClientChannel)])
    -> HashMap ChannelId ClientChannel
    -> Const
         [(ChannelId, ClientChannel)] (HashMap ChannelId ClientChannel))
-> Getting
     [(ChannelId, ClientChannel)]
     ClientChannels
     [(ChannelId, ClientChannel)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)])
-> SimpleGetter
     (HashMap ChannelId ClientChannel) [(ChannelId, ClientChannel)]
forall s a. (s -> a) -> SimpleGetter s a
to HashMap ChannelId ClientChannel -> [(ChannelId, ClientChannel)]
forall k v. HashMap k v -> [(k, v)]
HM.toList

------------------------------------------------------------------------

-- * Channel State management


-- | Add user to the list of users in this channel who are currently typing.
addChannelTypingUser :: UserId -> UTCTime -> ClientChannel -> ClientChannel
addChannelTypingUser :: UserId -> UTCTime -> ClientChannel -> ClientChannel
addChannelTypingUser UserId
uId UTCTime
ts = (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((TypingUsers -> Identity TypingUsers)
    -> ChannelInfo -> Identity ChannelInfo)
-> (TypingUsers -> Identity TypingUsers)
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(TypingUsers -> Identity TypingUsers)
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo TypingUsers
cdTypingUsers ((TypingUsers -> Identity TypingUsers)
 -> ClientChannel -> Identity ClientChannel)
-> (TypingUsers -> TypingUsers) -> ClientChannel -> ClientChannel
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (UserId -> UTCTime -> TypingUsers -> TypingUsers
addTypingUser UserId
uId UTCTime
ts)

-- | Clear the new message indicator for the specified channel
clearNewMessageIndicator :: ClientChannel -> ClientChannel
clearNewMessageIndicator :: ClientChannel -> ClientChannel
clearNewMessageIndicator ClientChannel
c = ClientChannel
c ClientChannel -> (ClientChannel -> ClientChannel) -> ClientChannel
forall a b. a -> (a -> b) -> b
& (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((NewMessageIndicator -> Identity NewMessageIndicator)
    -> ChannelInfo -> Identity ChannelInfo)
-> (NewMessageIndicator -> Identity NewMessageIndicator)
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(NewMessageIndicator -> Identity NewMessageIndicator)
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo NewMessageIndicator
cdNewMessageIndicator ((NewMessageIndicator -> Identity NewMessageIndicator)
 -> ClientChannel -> Identity ClientChannel)
-> NewMessageIndicator -> ClientChannel -> ClientChannel
forall s t a b. ASetter s t a b -> b -> s -> t
.~ NewMessageIndicator
Hide

-- | Clear the edit threshold for the specified channel
clearEditedThreshold :: ClientChannel -> ClientChannel
clearEditedThreshold :: ClientChannel -> ClientChannel
clearEditedThreshold ClientChannel
c = ClientChannel
c ClientChannel -> (ClientChannel -> ClientChannel) -> ClientChannel
forall a b. a -> (a -> b) -> b
& (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((Maybe ServerTime -> Identity (Maybe ServerTime))
    -> ChannelInfo -> Identity ChannelInfo)
-> (Maybe ServerTime -> Identity (Maybe ServerTime))
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe ServerTime -> Identity (Maybe ServerTime))
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo (Maybe ServerTime)
cdEditedMessageThreshold ((Maybe ServerTime -> Identity (Maybe ServerTime))
 -> ClientChannel -> Identity ClientChannel)
-> Maybe ServerTime -> ClientChannel -> ClientChannel
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Maybe ServerTime
forall a. Maybe a
Nothing

-- | Adjust updated time based on a message, ensuring that the updated
-- time does not move backward.
adjustUpdated :: Post -> ClientChannel -> ClientChannel
adjustUpdated :: Post -> ClientChannel -> ClientChannel
adjustUpdated Post
m =
    (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((ServerTime -> Identity ServerTime)
    -> ChannelInfo -> Identity ChannelInfo)
-> (ServerTime -> Identity ServerTime)
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ServerTime -> Identity ServerTime)
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo ServerTime
cdUpdated ((ServerTime -> Identity ServerTime)
 -> ClientChannel -> Identity ClientChannel)
-> (ServerTime -> ServerTime) -> ClientChannel -> ClientChannel
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ ServerTime -> ServerTime -> ServerTime
forall a. Ord a => a -> a -> a
max (Post -> ServerTime
maxPostTimestamp Post
m)

adjustEditedThreshold :: Post -> ClientChannel -> ClientChannel
adjustEditedThreshold :: Post -> ClientChannel -> ClientChannel
adjustEditedThreshold Post
m ClientChannel
c =
    if Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postUpdateAtL ServerTime -> ServerTime -> Bool
forall a. Ord a => a -> a -> Bool
<= Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL
    then ClientChannel
c
    else ClientChannel
c ClientChannel -> (ClientChannel -> ClientChannel) -> ClientChannel
forall a b. a -> (a -> b) -> b
& (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((Maybe ServerTime -> Identity (Maybe ServerTime))
    -> ChannelInfo -> Identity ChannelInfo)
-> (Maybe ServerTime -> Identity (Maybe ServerTime))
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Maybe ServerTime -> Identity (Maybe ServerTime))
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo (Maybe ServerTime)
cdEditedMessageThreshold ((Maybe ServerTime -> Identity (Maybe ServerTime))
 -> ClientChannel -> Identity ClientChannel)
-> (Maybe ServerTime -> Maybe ServerTime)
-> ClientChannel
-> ClientChannel
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ (\Maybe ServerTime
mt -> case Maybe ServerTime
mt of
        Just ServerTime
t -> ServerTime -> Maybe ServerTime
forall a. a -> Maybe a
Just (ServerTime -> Maybe ServerTime) -> ServerTime -> Maybe ServerTime
forall a b. (a -> b) -> a -> b
$ ServerTime -> ServerTime -> ServerTime
forall a. Ord a => a -> a -> a
min (Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postUpdateAtL) ServerTime
t
        Maybe ServerTime
Nothing -> ServerTime -> Maybe ServerTime
forall a. a -> Maybe a
Just (ServerTime -> Maybe ServerTime) -> ServerTime -> Maybe ServerTime
forall a b. (a -> b) -> a -> b
$ Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postUpdateAtL
        )

maxPostTimestamp :: Post -> ServerTime
maxPostTimestamp :: Post -> ServerTime
maxPostTimestamp Post
m = ServerTime -> ServerTime -> ServerTime
forall a. Ord a => a -> a -> a
max (Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.(Maybe ServerTime -> Const ServerTime (Maybe ServerTime))
-> Post -> Const ServerTime Post
Lens' Post (Maybe ServerTime)
postDeleteAtL ((Maybe ServerTime -> Const ServerTime (Maybe ServerTime))
 -> Post -> Const ServerTime Post)
-> ((ServerTime -> Const ServerTime ServerTime)
    -> Maybe ServerTime -> Const ServerTime (Maybe ServerTime))
-> Getting ServerTime Post ServerTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ServerTime -> Lens' (Maybe ServerTime) ServerTime
forall a. Eq a => a -> Lens' (Maybe a) a
non (Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postUpdateAtL)) (Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL)

updateNewMessageIndicator :: Post -> ClientChannel -> ClientChannel
updateNewMessageIndicator :: Post -> ClientChannel -> ClientChannel
updateNewMessageIndicator Post
m =
    (ChannelInfo -> Identity ChannelInfo)
-> ClientChannel -> Identity ClientChannel
Lens' ClientChannel ChannelInfo
ccInfo((ChannelInfo -> Identity ChannelInfo)
 -> ClientChannel -> Identity ClientChannel)
-> ((NewMessageIndicator -> Identity NewMessageIndicator)
    -> ChannelInfo -> Identity ChannelInfo)
-> (NewMessageIndicator -> Identity NewMessageIndicator)
-> ClientChannel
-> Identity ClientChannel
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(NewMessageIndicator -> Identity NewMessageIndicator)
-> ChannelInfo -> Identity ChannelInfo
Lens' ChannelInfo NewMessageIndicator
cdNewMessageIndicator ((NewMessageIndicator -> Identity NewMessageIndicator)
 -> ClientChannel -> Identity ClientChannel)
-> (NewMessageIndicator -> NewMessageIndicator)
-> ClientChannel
-> ClientChannel
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~
        (\NewMessageIndicator
old ->
          case NewMessageIndicator
old of
              NewMessageIndicator
Hide ->
                  ServerTime -> NewMessageIndicator
NewPostsStartingAt (ServerTime -> NewMessageIndicator)
-> ServerTime -> NewMessageIndicator
forall a b. (a -> b) -> a -> b
$ Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL
              NewPostsStartingAt ServerTime
ts ->
                  ServerTime -> NewMessageIndicator
NewPostsStartingAt (ServerTime -> NewMessageIndicator)
-> ServerTime -> NewMessageIndicator
forall a b. (a -> b) -> a -> b
$ ServerTime -> ServerTime -> ServerTime
forall a. Ord a => a -> a -> a
min (Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL) ServerTime
ts
              NewPostsAfterServerTime ServerTime
ts ->
                  if Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL ServerTime -> ServerTime -> Bool
forall a. Ord a => a -> a -> Bool
<= ServerTime
ts
                  then ServerTime -> NewMessageIndicator
NewPostsStartingAt (ServerTime -> NewMessageIndicator)
-> ServerTime -> NewMessageIndicator
forall a b. (a -> b) -> a -> b
$ Post
mPost -> Getting ServerTime Post ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Post ServerTime
Lens' Post ServerTime
postCreateAtL
                  else ServerTime -> NewMessageIndicator
NewPostsAfterServerTime ServerTime
ts
              )

-- | Town Square is special in that its non-display name cannot be
-- changed and is a hard-coded constant server-side according to the
-- developers (as of 8/2/17). So this is a reliable way to check for
-- whether a channel is in fact that channel, even if the user has
-- changed its display name.
isTownSquare :: Channel -> Bool
isTownSquare :: Channel -> Bool
isTownSquare Channel
c = (UserText -> Text
sanitizeUserText (UserText -> Text) -> UserText -> Text
forall a b. (a -> b) -> a -> b
$ Channel
cChannel -> Getting UserText Channel UserText -> UserText
forall s a. s -> Getting a s a -> a
^.Getting UserText Channel UserText
Lens' Channel UserText
channelNameL) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"town-square"

channelDeleted :: Channel -> Bool
channelDeleted :: Channel -> Bool
channelDeleted Channel
c = Channel
cChannel -> Getting ServerTime Channel ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Channel ServerTime
Lens' Channel ServerTime
channelDeleteAtL ServerTime -> ServerTime -> Bool
forall a. Ord a => a -> a -> Bool
> Channel
cChannel -> Getting ServerTime Channel ServerTime -> ServerTime
forall s a. s -> Getting a s a -> a
^.Getting ServerTime Channel ServerTime
Lens' Channel ServerTime
channelCreateAtL