mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
directory: list groups with group member counts (#2855)
* directory: list groups with group member counts * list groups, test * superuser can list all groups * rename command * remove type synonym * add member count to search results * fix test
This commit is contained in:
committed by
GitHub
parent
8f72328136
commit
4826a62d36
+9
-1
@@ -1144,6 +1144,9 @@ processChatCommand = \case
|
||||
incognitoProfile <- forM customUserProfileId $ \profileId -> withStore (\db -> getProfileById db userId profileId)
|
||||
connectionStats <- withAgent (`getConnectionServers` contactConnId ct)
|
||||
pure $ CRContactInfo user ct connectionStats (fmap fromLocalProfile incognitoProfile)
|
||||
APIGroupInfo gId -> withUser $ \user -> do
|
||||
(g, s) <- withStore $ \db -> (,) <$> getGroupInfo db user gId <*> liftIO (getGroupSummary db user gId)
|
||||
pure $ CRGroupInfo user g s
|
||||
APIGroupMemberInfo gId gMemberId -> withUser $ \user -> do
|
||||
(g, m) <- withStore $ \db -> (,) <$> getGroupInfo db user gId <*> getGroupMember db user gId gMemberId
|
||||
connectionStats <- mapM (withAgent . flip getConnectionServers) (memberConnId m)
|
||||
@@ -1230,6 +1233,9 @@ processChatCommand = \case
|
||||
SetShowMessages cName ntfOn -> updateChatSettings cName (\cs -> cs {enableNtfs = ntfOn})
|
||||
SetSendReceipts cName rcptsOn_ -> updateChatSettings cName (\cs -> cs {sendRcpts = rcptsOn_})
|
||||
ContactInfo cName -> withContactName cName APIContactInfo
|
||||
ShowGroupInfo gName -> withUser $ \user -> do
|
||||
groupId <- withStore $ \db -> getGroupIdByName db user gName
|
||||
processChatCommand $ APIGroupInfo groupId
|
||||
GroupMemberInfo gName mName -> withMemberName gName mName APIGroupMemberInfo
|
||||
SwitchContact cName -> withContactName cName APISwitchContact
|
||||
SwitchGroupMember gName mName -> withMemberName gName mName APISwitchGroupMember
|
||||
@@ -1493,7 +1499,7 @@ processChatCommand = \case
|
||||
groupId <- withStore $ \db -> getGroupIdByName db user gName
|
||||
processChatCommand $ APIListMembers groupId
|
||||
APIListGroups userId contactId_ search_ -> withUserId userId $ \user ->
|
||||
CRGroupsList user <$> withStore' (\db -> getUserGroupDetails db user contactId_ search_)
|
||||
CRGroupsList user <$> withStore' (\db -> getUserGroupsWithSummary db user contactId_ search_)
|
||||
ListGroups cName_ search_ -> withUser $ \user@User {userId} -> do
|
||||
ct_ <- forM cName_ $ \cName -> withStore $ \db -> getContactByName db user cName
|
||||
processChatCommand $ APIListGroups userId (contactId' <$> ct_) search_
|
||||
@@ -5092,8 +5098,10 @@ chatCommandP =
|
||||
"/reconnect" $> ReconnectAllServers,
|
||||
"/_settings " *> (APISetChatSettings <$> chatRefP <* A.space <*> jsonP),
|
||||
"/_info #" *> (APIGroupMemberInfo <$> A.decimal <* A.space <*> A.decimal),
|
||||
"/_info #" *> (APIGroupInfo <$> A.decimal),
|
||||
"/_info @" *> (APIContactInfo <$> A.decimal),
|
||||
("/info #" <|> "/i #") *> (GroupMemberInfo <$> displayName <* A.space <* char_ '@' <*> displayName),
|
||||
("/info #" <|> "/i #") *> (ShowGroupInfo <$> displayName),
|
||||
("/info " <|> "/i ") *> char_ '@' *> (ContactInfo <$> displayName),
|
||||
"/_switch #" *> (APISwitchGroupMember <$> A.decimal <* A.space <*> A.decimal),
|
||||
"/_switch @" *> (APISwitchContact <$> A.decimal),
|
||||
|
||||
@@ -291,6 +291,7 @@ data ChatCommand
|
||||
| ReconnectAllServers
|
||||
| APISetChatSettings ChatRef ChatSettings
|
||||
| APIContactInfo ContactId
|
||||
| APIGroupInfo GroupId
|
||||
| APIGroupMemberInfo GroupId GroupMemberId
|
||||
| APISwitchContact ContactId
|
||||
| APISwitchGroupMember GroupId GroupMemberId
|
||||
@@ -307,6 +308,7 @@ data ChatCommand
|
||||
| SetShowMessages ChatName Bool
|
||||
| SetSendReceipts ChatName (Maybe Bool)
|
||||
| ContactInfo ContactName
|
||||
| ShowGroupInfo GroupName
|
||||
| GroupMemberInfo GroupName ContactName
|
||||
| SwitchContact ContactName
|
||||
| SwitchGroupMember GroupName ContactName
|
||||
@@ -424,6 +426,7 @@ data ChatResponse
|
||||
| CRChatItemTTL {user :: User, chatItemTTL :: Maybe Int64}
|
||||
| CRNetworkConfig {networkConfig :: NetworkConfig}
|
||||
| CRContactInfo {user :: User, contact :: Contact, connectionStats :: ConnectionStats, customUserProfile :: Maybe Profile}
|
||||
| CRGroupInfo {user :: User, groupInfo :: GroupInfo, groupSummary :: GroupSummary}
|
||||
| CRGroupMemberInfo {user :: User, groupInfo :: GroupInfo, member :: GroupMember, connectionStats_ :: Maybe ConnectionStats}
|
||||
| CRContactSwitchStarted {user :: User, contact :: Contact, connectionStats :: ConnectionStats}
|
||||
| CRGroupMemberSwitchStarted {user :: User, groupInfo :: GroupInfo, member :: GroupMember, connectionStats :: ConnectionStats}
|
||||
@@ -461,7 +464,7 @@ data ChatResponse
|
||||
| CRContactRequestRejected {user :: User, contactRequest :: UserContactRequest}
|
||||
| CRUserAcceptedGroupSent {user :: User, groupInfo :: GroupInfo, hostContact :: Maybe Contact}
|
||||
| CRUserDeletedMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember}
|
||||
| CRGroupsList {user :: User, groups :: [GroupInfo]}
|
||||
| CRGroupsList {user :: User, groups :: [(GroupInfo, GroupSummary)]}
|
||||
| CRSentGroupInvitation {user :: User, groupInfo :: GroupInfo, contact :: Contact, member :: GroupMember}
|
||||
| CRFileTransferStatus User (FileTransfer, [Integer]) -- TODO refactor this type to FileTransferStatus
|
||||
| CRFileTransferStatusXFTP User AChatItem
|
||||
|
||||
@@ -45,6 +45,8 @@ module Simplex.Chat.Store.Groups
|
||||
deleteGroup,
|
||||
getUserGroups,
|
||||
getUserGroupDetails,
|
||||
getUserGroupsWithSummary,
|
||||
getGroupSummary,
|
||||
getContactGroupPreferences,
|
||||
checkContactHasGroups,
|
||||
getGroupInvitation,
|
||||
@@ -468,6 +470,30 @@ getUserGroupDetails db User {userId, userContactId} _contactId_ search_ =
|
||||
where
|
||||
search = fromMaybe "" search_
|
||||
|
||||
getUserGroupsWithSummary :: DB.Connection -> User -> Maybe ContactId -> Maybe String -> IO [(GroupInfo, GroupSummary)]
|
||||
getUserGroupsWithSummary db user _contactId_ search_ =
|
||||
getUserGroupDetails db user _contactId_ search_
|
||||
>>= mapM (\g@GroupInfo {groupId} -> (g,) <$> getGroupSummary db user groupId)
|
||||
|
||||
-- the statuses on non-current members should match memberCurrent' function
|
||||
getGroupSummary :: DB.Connection -> User -> GroupId -> IO GroupSummary
|
||||
getGroupSummary db User {userId} groupId = do
|
||||
currentMembers_ <- maybeFirstRow fromOnly $
|
||||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT count (m.group_member_id)
|
||||
FROM groups g
|
||||
JOIN group_members m USING (group_id)
|
||||
WHERE g.user_id = ?
|
||||
AND g.group_id = ?
|
||||
AND m.member_status != ?
|
||||
AND m.member_status != ?
|
||||
AND m.member_status != ?
|
||||
|]
|
||||
(userId, groupId, GSMemRemoved, GSMemLeft, GSMemInvited)
|
||||
pure GroupSummary {currentMembers = fromMaybe 0 currentMembers_}
|
||||
|
||||
getContactGroupPreferences :: DB.Connection -> User -> Contact -> IO [FullGroupPreferences]
|
||||
getContactGroupPreferences db User {userId} Contact {contactId} = do
|
||||
map (mergeGroupPreferences . fromOnly)
|
||||
|
||||
@@ -318,6 +318,13 @@ instance ToJSON GroupInfo where toEncoding = J.genericToEncoding J.defaultOption
|
||||
groupName' :: GroupInfo -> GroupName
|
||||
groupName' GroupInfo {localDisplayName = g} = g
|
||||
|
||||
data GroupSummary = GroupSummary
|
||||
{ currentMembers :: Int
|
||||
}
|
||||
deriving (Show, Generic)
|
||||
|
||||
instance ToJSON GroupSummary where toEncoding = J.genericToEncoding J.defaultOptions
|
||||
|
||||
data ContactOrGroup = CGContact Contact | CGGroup Group
|
||||
|
||||
contactAndGroupIds :: ContactOrGroup -> (Maybe ContactId, Maybe GroupId)
|
||||
@@ -784,6 +791,7 @@ memberActive m = case memberStatus m of
|
||||
memberCurrent :: GroupMember -> Bool
|
||||
memberCurrent = memberCurrent' . memberStatus
|
||||
|
||||
-- update getGroupSummary if this is changed
|
||||
memberCurrent' :: GroupMemberStatus -> Bool
|
||||
memberCurrent' = \case
|
||||
GSMemRemoved -> False
|
||||
|
||||
@@ -79,6 +79,7 @@ responseToView user_ ChatConfig {logLevel, showReactions, showReceipts, testView
|
||||
CRChatItemTTL u ttl -> ttyUser u $ viewChatItemTTL ttl
|
||||
CRNetworkConfig cfg -> viewNetworkConfig cfg
|
||||
CRContactInfo u ct cStats customUserProfile -> ttyUser u $ viewContactInfo ct cStats customUserProfile
|
||||
CRGroupInfo u g s -> ttyUser u $ viewGroupInfo g s
|
||||
CRGroupMemberInfo u g m cStats -> ttyUser u $ viewGroupMemberInfo g m cStats
|
||||
CRContactSwitchStarted {} -> ["switch started"]
|
||||
CRGroupMemberSwitchStarted {} -> ["switch started"]
|
||||
@@ -811,12 +812,12 @@ viewContactConnected ct@Contact {localDisplayName} userIncognitoProfile testView
|
||||
Nothing ->
|
||||
[ttyFullContact ct <> ": contact is connected"]
|
||||
|
||||
viewGroupsList :: [GroupInfo] -> [StyledString]
|
||||
viewGroupsList :: [(GroupInfo, GroupSummary)] -> [StyledString]
|
||||
viewGroupsList [] = ["you have no groups!", "to create: " <> highlight' "/g <name>"]
|
||||
viewGroupsList gs = map groupSS $ sortOn ldn_ gs
|
||||
where
|
||||
ldn_ = T.toLower . (localDisplayName :: GroupInfo -> GroupName)
|
||||
groupSS g@GroupInfo {localDisplayName = ldn, groupProfile = GroupProfile {fullName}, membership, chatSettings} =
|
||||
ldn_ = T.toLower . (localDisplayName :: GroupInfo -> GroupName) . fst
|
||||
groupSS (g@GroupInfo {localDisplayName = ldn, groupProfile = GroupProfile {fullName}, membership, chatSettings}, GroupSummary {currentMembers}) =
|
||||
case memberStatus membership of
|
||||
GSMemInvited -> groupInvitation' g
|
||||
s -> membershipIncognito g <> ttyGroup ldn <> optFullName ldn fullName <> viewMemberStatus s
|
||||
@@ -826,9 +827,10 @@ viewGroupsList gs = map groupSS $ sortOn ldn_ gs
|
||||
GSMemLeft -> delete "you left"
|
||||
GSMemGroupDeleted -> delete "group deleted"
|
||||
_
|
||||
| enableNtfs chatSettings -> ""
|
||||
| otherwise -> " (muted, you can " <> highlight ("/unmute #" <> ldn) <> ")"
|
||||
| enableNtfs chatSettings -> " (" <> memberCount <> ")"
|
||||
| otherwise -> " (" <> memberCount <> ", muted, you can " <> highlight ("/unmute #" <> ldn) <> ")"
|
||||
delete reason = " (" <> reason <> ", delete local copy: " <> highlight ("/d #" <> ldn) <> ")"
|
||||
memberCount = sShow currentMembers <> " member" <> if currentMembers == 1 then "" else "s"
|
||||
|
||||
groupInvitation' :: GroupInfo -> StyledString
|
||||
groupInvitation' GroupInfo {localDisplayName = ldn, groupProfile = GroupProfile {fullName}, membership = membership@GroupMember {memberProfile}} =
|
||||
@@ -935,6 +937,12 @@ viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, conta
|
||||
<> ["alias: " <> plain localAlias | localAlias /= ""]
|
||||
<> [viewConnectionVerified (contactSecurityCode ct)]
|
||||
|
||||
viewGroupInfo :: GroupInfo -> GroupSummary -> [StyledString]
|
||||
viewGroupInfo GroupInfo {groupId} s =
|
||||
[ "group ID: " <> sShow groupId,
|
||||
"current members: " <> sShow (currentMembers s)
|
||||
]
|
||||
|
||||
viewGroupMemberInfo :: GroupInfo -> GroupMember -> Maybe ConnectionStats -> [StyledString]
|
||||
viewGroupMemberInfo GroupInfo {groupId} m@GroupMember {groupMemberId, memberProfile = LocalProfile {localAlias}} stats =
|
||||
[ "group ID: " <> sShow groupId,
|
||||
|
||||
Reference in New Issue
Block a user