mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-19 11:46:26 +00:00
core: prepare and connect to group (#5964)
This commit is contained in:
@@ -688,6 +688,7 @@ data ChatResponse
|
||||
| CRSentConfirmation {user :: User, connection :: PendingContactConnection}
|
||||
| CRSentInvitation {user :: User, connection :: PendingContactConnection, customUserProfile :: Maybe Profile}
|
||||
| CRStartedConnectionToContact {user :: User, contact :: Contact}
|
||||
| CRStartedConnectionToGroup {user :: User, groupInfo :: GroupInfo}
|
||||
| CRSentInvitationToContact {user :: User, contact :: Contact, customUserProfile :: Maybe Profile}
|
||||
| CRItemsReadForChat {user :: User, chatInfo :: AChatInfo}
|
||||
| CRContactDeleted {user :: User, contact :: Contact}
|
||||
|
||||
@@ -1740,17 +1740,15 @@ processChatCommand' vr = \case
|
||||
pure conn'
|
||||
APIConnectPlan userId cLink -> withUserId userId $ \user ->
|
||||
uncurry (CRConnectionPlan user) <$> connectPlan user cLink
|
||||
APIPrepareContact userId link contactSLinkData -> withUserId userId $ \user -> do
|
||||
APIPrepareContact userId accLink contactSLinkData -> withUserId userId $ \user -> do
|
||||
let ContactShortLinkData {profile, welcomeMsg} = contactSLinkData
|
||||
ct <- withStore $ \db -> createPreparedContact db user profile link
|
||||
ct <- withStore $ \db -> createPreparedContact db user profile accLink
|
||||
forM_ welcomeMsg $ \msg ->
|
||||
createInternalChatItem user (CDDirectRcv ct) (CIRcvMsgContent $ MCText msg) Nothing
|
||||
pure $ CRNewPreparedContact user ct
|
||||
APIPrepareGroup userId link groupSLinkData -> withUserId userId $ \user -> do
|
||||
APIPrepareGroup userId accLink groupSLinkData -> withUserId userId $ \user -> do
|
||||
let GroupShortLinkData {groupProfile} = groupSLinkData
|
||||
-- TODO [short link] create host member for group connection on CONF, XGrpLinkInv (as in createGroupViaLink')
|
||||
-- TODO - see other problems in createPreparedGroup: invited member id (user member), business chats
|
||||
gInfo <- withStore $ \db -> createPreparedGroup db vr user groupProfile link
|
||||
gInfo <- withStore $ \db -> createPreparedGroup db vr user groupProfile accLink
|
||||
pure $ CRNewPreparedGroup user gInfo
|
||||
-- TODO [short links] change prepared entity user
|
||||
-- TODO - UI would call these APIs before APIConnectPrepared... APIs
|
||||
@@ -1759,42 +1757,44 @@ processChatCommand' vr = \case
|
||||
ok_
|
||||
APIChangeGroupUser groupId newUserId -> withUser $ \user -> do
|
||||
ok_
|
||||
-- Alternative to passing incognito to APIConnectPreparedContact, APIConnectPreparedGroup would be to
|
||||
-- create new APIs to set incognito on entity - APISetContactIncognito, APISetGroupIncognito.
|
||||
-- It would be more complex:
|
||||
-- - would require to persist incognito profile on entity opposing to connection as currently,
|
||||
-- - would require decomposing part of APIConnect.
|
||||
-- As it's an edge case / not a big issue that it's not persisted like a change of user,
|
||||
-- we're simply passing it to prepare here.
|
||||
APIConnectPreparedContact contactId incognito msgContent_ -> withUser $ \user@User {userId} -> do
|
||||
ct@Contact {connLinkToConnect} <- withFastStore $ \db -> getContact db vr user contactId
|
||||
APIConnectPreparedContact contactId incognito msgContent_ -> withUser $ \user -> do
|
||||
Contact {connLinkToConnect} <- withFastStore $ \db -> getContact db vr user contactId
|
||||
case connLinkToConnect of
|
||||
Nothing -> throwCmdError "contact doesn't have link to connect"
|
||||
Just link -> case link of
|
||||
(ACCL SCMInvitation ccLink) ->
|
||||
connectViaInvitation user incognito ccLink (Just contactId) >>= \case
|
||||
CRSentConfirmation {} -> do
|
||||
-- get updated contact with connection
|
||||
ct' <- withFastStore $ \db -> getContact db vr user contactId
|
||||
forM_ msgContent_ $ \mc -> do
|
||||
let evt = XMsgNew $ MCSimple (extMsgContent mc Nothing)
|
||||
(msg, _) <- sendDirectContactMessage user ct' evt
|
||||
ci <- saveSndChatItem user (CDDirectSnd ct') msg (CISndMsgContent mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDSnd (DirectChat ct') ci]
|
||||
pure $ CRStartedConnectionToContact user ct'
|
||||
cr -> pure cr
|
||||
(ACCL SCMContact ccLink) ->
|
||||
connectViaContact user incognito ccLink msgContent_ (Just $ CGMContactId contactId) >>= \case
|
||||
CRSentInvitation {} -> do
|
||||
-- get updated contact with connection
|
||||
ct' <- withFastStore $ \db -> getContact db vr user contactId
|
||||
forM_ msgContent_ $ \mc ->
|
||||
createInternalChatItem user (CDDirectSnd ct') (CISndMsgContent mc) Nothing
|
||||
pure $ CRStartedConnectionToContact user ct'
|
||||
cr -> pure cr
|
||||
-- TODO [short links] connect to prepared group
|
||||
Just (ACCL SCMInvitation ccLink) ->
|
||||
connectViaInvitation user incognito ccLink (Just contactId) >>= \case
|
||||
CRSentConfirmation {} -> do
|
||||
-- get updated contact with connection
|
||||
ct' <- withFastStore $ \db -> getContact db vr user contactId
|
||||
forM_ msgContent_ $ \mc -> do
|
||||
let evt = XMsgNew $ MCSimple (extMsgContent mc Nothing)
|
||||
(msg, _) <- sendDirectContactMessage user ct' evt
|
||||
ci <- saveSndChatItem user (CDDirectSnd ct') msg (CISndMsgContent mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDSnd (DirectChat ct') ci]
|
||||
pure $ CRStartedConnectionToContact user ct'
|
||||
cr -> pure cr
|
||||
Just (ACCL SCMContact ccLink) ->
|
||||
connectViaContact user incognito ccLink msgContent_ (Just $ CGMContactId contactId) >>= \case
|
||||
CRSentInvitation {} -> do
|
||||
-- get updated contact with connection
|
||||
ct' <- withFastStore $ \db -> getContact db vr user contactId
|
||||
forM_ msgContent_ $ \mc ->
|
||||
createInternalChatItem user (CDDirectSnd ct') (CISndMsgContent mc) Nothing
|
||||
pure $ CRStartedConnectionToContact user ct'
|
||||
cr -> pure cr
|
||||
APIConnectPreparedGroup groupId incognito -> withUser $ \user -> do
|
||||
ok_
|
||||
(gInfo, hostMember) <- withFastStore $ \db -> (,) <$> getGroupInfo db vr user groupId <*> getHostMember db vr user groupId
|
||||
let GroupInfo {connLinkToConnect} = gInfo
|
||||
case connLinkToConnect of
|
||||
Nothing -> throwCmdError "group doesn't have link to connect"
|
||||
Just ccLink ->
|
||||
connectViaContact user incognito ccLink Nothing (Just $ CGMGroupMemberId (groupMemberId' hostMember)) >>= \case
|
||||
CRSentInvitation {connection = PendingContactConnection {pccConnId}} -> do
|
||||
gInfo' <- withStore' $ \db -> do
|
||||
setViaGroupLinkHash db groupId pccConnId
|
||||
setGroupConnLinkStartedConnection db gInfo True
|
||||
pure $ CRStartedConnectionToGroup user gInfo'
|
||||
cr -> pure cr
|
||||
APIConnect userId incognito (Just (ACCL SCMInvitation ccLink)) mc_ -> withUserId userId $ \user -> do
|
||||
when (isJust mc_) $ throwChatError CEConnReqMessageProhibited
|
||||
connectViaInvitation user incognito ccLink Nothing
|
||||
@@ -2910,8 +2910,6 @@ processChatCommand' vr = \case
|
||||
( CRInvitationUri crData {crScheme = SSSimplex} e2e,
|
||||
CRInvitationUri crData {crScheme = simplexChat} e2e
|
||||
)
|
||||
-- TODO [short links] Maybe Int64 should be Maybe <entity id type> to differentiate between contact and group links;
|
||||
-- TODO link connection to entity in createConnReqConnection
|
||||
connectViaContact :: User -> IncognitoEnabled -> CreatedLinkContact -> Maybe MsgContent -> Maybe ContactOrGroupMemberId -> CM ChatResponse
|
||||
connectViaContact user@User {userId} incognito (CCLink cReq@(CRContactUri ConnReqUriData {crClientData}) sLnk) mc_ comId_ = withInvitationLock "connectViaContact" (strEncode cReq) $ do
|
||||
let groupLinkId = crClientData >>= decodeJSON >>= \(CRDataGroup gli) -> Just gli
|
||||
|
||||
@@ -677,7 +677,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
_ -> pure ()
|
||||
|
||||
processGroupMessage :: AEvent e -> ConnectionEntity -> Connection -> GroupInfo -> GroupMember -> CM ()
|
||||
processGroupMessage agentMsg connEntity conn@Connection {connId, connChatVersion, connectionCode} gInfo@GroupInfo {groupId, groupProfile, membership, chatSettings} m = case agentMsg of
|
||||
processGroupMessage agentMsg connEntity conn@Connection {connId, connChatVersion, customUserProfileId, connectionCode} gInfo@GroupInfo {groupId, groupProfile, membership, chatSettings} m = case agentMsg of
|
||||
INV (ACR _ cReq) ->
|
||||
withCompletedCommand conn agentMsg $ \CommandData {cmdFunction} ->
|
||||
case cReq of
|
||||
@@ -735,6 +735,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
allowAgentConnectionAsync user conn' confId XOk
|
||||
| otherwise -> messageError "x.grp.acpt: memberId is different from expected"
|
||||
_ -> messageError "CONF from invited member must have x.grp.acpt"
|
||||
GCHostMember ->
|
||||
case chatMsgEvent of
|
||||
XGrpLinkInv glInv -> do
|
||||
-- XGrpLinkInv here means we are connecting via prepared group, and we have to update user and host member records
|
||||
(gInfo', m') <- withStore $ \db -> updatePreparedUserAndHostMembersInvited db vr user gInfo m glInv
|
||||
-- [incognito] send saved profile
|
||||
incognitoProfile <- forM customUserProfileId $ \pId -> withStore (\db -> getProfileById db userId pId)
|
||||
let profileToSend = userProfileToSend user (fromLocalProfile <$> incognitoProfile) Nothing True
|
||||
allowAgentConnectionAsync user conn' confId $ XInfo profileToSend
|
||||
toView $ CEvtGroupLinkConnecting user gInfo' m'
|
||||
XGrpLinkReject glRjct@GroupLinkRejection {rejectionReason} -> do
|
||||
(gInfo', m') <- withStore $ \db -> updatePreparedUserAndHostMembersRejected db vr user gInfo m glRjct
|
||||
toView $ CEvtGroupLinkConnecting user gInfo' m'
|
||||
toViewTE $ TEGroupLinkRejected user gInfo' rejectionReason
|
||||
_ -> messageError "CONF from host member in prepared group must have x.grp.link.inv or x.grp.link.reject"
|
||||
_ ->
|
||||
case chatMsgEvent of
|
||||
XGrpMemInfo memId _memProfile
|
||||
|
||||
@@ -139,7 +139,8 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
|
||||
@@ -169,7 +169,7 @@ createConnReqConnection db userId acId cReqHash sLnk comId_ xContactId incognito
|
||||
created_at, updated_at, to_subscribe, conn_chat_version, pq_support, pq_encryption
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
( (userId, acId, pccConnStatus, ConnContact, BI True)
|
||||
( (userId, acId, pccConnStatus, connType, BI True)
|
||||
:. (cReqHash, sLnk, contactId_, groupMemberId_)
|
||||
:. (xContactId, customUserProfileId, BI (isJust groupLinkId), groupLinkId)
|
||||
:. (createdAt, createdAt, BI (subMode == SMOnlyCreate), chatV, pqSup, pqSup)
|
||||
@@ -177,10 +177,10 @@ createConnReqConnection db userId acId cReqHash sLnk comId_ xContactId incognito
|
||||
pccConnId <- insertedRowId db
|
||||
pure PendingContactConnection {pccConnId, pccAgentConnId = AgentConnId acId, pccConnStatus, viaContactUri = True, viaUserContactLink = Nothing, groupLinkId, customUserProfileId, connLinkInv = Nothing, localAlias = "", createdAt, updatedAt = createdAt}
|
||||
where
|
||||
(contactId_, groupMemberId_) = case comId_ of
|
||||
Just (CGMContactId ctId) -> (Just ctId, Nothing)
|
||||
Just (CGMGroupMemberId gmId) -> (Nothing, Just gmId)
|
||||
Nothing -> (Nothing, Nothing)
|
||||
(connType, contactId_, groupMemberId_) = case comId_ of
|
||||
Just (CGMContactId ctId) -> (ConnContact, Just ctId, Nothing)
|
||||
Just (CGMGroupMemberId gmId) -> (ConnMember, Nothing, Just gmId)
|
||||
Nothing -> (ConnContact, Nothing, Nothing)
|
||||
|
||||
getConnReqContactXContactId :: DB.Connection -> VersionRangeChat -> User -> ConnReqUriHash -> IO (Maybe Contact, Maybe XContactId)
|
||||
getConnReqContactXContactId db vr user@User {userId} cReqHash = do
|
||||
|
||||
@@ -33,6 +33,9 @@ module Simplex.Chat.Store.Groups
|
||||
createGroupInvitation,
|
||||
deleteContactCardKeepConn,
|
||||
createPreparedGroup,
|
||||
setGroupConnLinkStartedConnection,
|
||||
updatePreparedUserAndHostMembersInvited,
|
||||
updatePreparedUserAndHostMembersRejected,
|
||||
createGroupInvitedViaLink,
|
||||
createGroupRejectedViaLink,
|
||||
setViaGroupLinkHash,
|
||||
@@ -50,6 +53,7 @@ module Simplex.Chat.Store.Groups
|
||||
getActiveMembersByName,
|
||||
getGroupInfoByName,
|
||||
getGroupMember,
|
||||
getHostMember,
|
||||
getMentionedGroupMember,
|
||||
getMentionedMemberByMemberId,
|
||||
getGroupMemberById,
|
||||
@@ -156,6 +160,7 @@ import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)
|
||||
import Data.Ord (Down (..))
|
||||
import Data.Text (Text)
|
||||
import Data.Time.Clock (UTCTime (..), getCurrentTime)
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Protocol (MsgMention (..), groupForwardVersion)
|
||||
import Simplex.Chat.Store.Direct
|
||||
@@ -284,7 +289,8 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
@@ -367,6 +373,7 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc
|
||||
chatTs = Just currentTs,
|
||||
userMemberProfileSentAt = Just currentTs,
|
||||
connLinkToConnect = Nothing,
|
||||
connLinkStartedConnection = False,
|
||||
chatTags = [],
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
@@ -439,6 +446,7 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
|
||||
chatTs = Just currentTs,
|
||||
userMemberProfileSentAt = Just currentTs,
|
||||
connLinkToConnect = Nothing,
|
||||
connLinkStartedConnection = False,
|
||||
chatTags = [],
|
||||
chatItemTTL = Nothing,
|
||||
uiThemes = Nothing,
|
||||
@@ -537,22 +545,102 @@ deleteContactCardKeepConn db connId Contact {contactId, profile = LocalProfile {
|
||||
DB.execute db "DELETE FROM contact_profiles WHERE contact_profile_id = ?" (Only profileId)
|
||||
|
||||
createPreparedGroup :: DB.Connection -> VersionRangeChat -> User -> GroupProfile -> ACreatedConnLink -> ExceptT StoreError IO GroupInfo
|
||||
createPreparedGroup db vr user@User {userId} groupProfile connLinkToConnect = do
|
||||
createPreparedGroup db vr user@User {userId, userContactId} groupProfile connLinkToConnect = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
-- TODO [short links] support preparing business chats
|
||||
let business = Nothing
|
||||
groupId <- createGroup_ db userId groupProfile (Just connLinkToConnect) business currentTs
|
||||
-- TODO [short links] create "unknown" host member here? set invitedByGroupMemberId later?
|
||||
-- TODO - same for invitedMember
|
||||
-- TODO - for membershipStatus - new status GSMemNew?
|
||||
-- TODO - customUserProfileId - pass on APIConnectPreparedGroup, update member; or separate apis for switching before joining?
|
||||
let invitedByGroupMemberId = Nothing
|
||||
invitedMember = MemberIdRole (MemberId "unknown") GRMember
|
||||
membershipStatus = GSMemAccepted
|
||||
customUserProfileId = Nothing
|
||||
void $ createContactMemberInv_ db user groupId invitedByGroupMemberId user invitedMember GCUserMember membershipStatus IBUnknown customUserProfileId currentTs vr
|
||||
-- TODO [short links] review: setViaGroupLinkHash
|
||||
(groupId, groupLDN) <- createGroup_ db userId groupProfile (Just connLinkToConnect) Nothing currentTs
|
||||
hostMemberId <- insertHost_ currentTs groupId groupLDN
|
||||
let userMember = MemberIdRole (MemberId $ encodeUtf8 groupLDN <> "_user_unknown_id") GRMember
|
||||
void $ createContactMemberInv_ db user groupId (Just hostMemberId) user userMember GCUserMember GSMemUnknown IBUnknown Nothing currentTs vr
|
||||
getGroupInfo db vr user groupId
|
||||
where
|
||||
insertHost_ currentTs groupId groupLDN = do
|
||||
let memberId = MemberId $ encodeUtf8 groupLDN <> "_host_unknown_id"
|
||||
hostProfile = profileFromName $ nameFromMemberId memberId
|
||||
(localDisplayName, profileId) <- createNewMemberProfile_ db user hostProfile currentTs
|
||||
liftIO $ do
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
INSERT INTO group_members
|
||||
( group_id, member_id, member_role, member_category, member_status, invited_by,
|
||||
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
( (groupId, memberId, GRAdmin, GCHostMember, GSMemAccepted, fromInvitedBy userContactId IBUnknown)
|
||||
:. (userId, localDisplayName, Nothing :: (Maybe Int64), profileId, currentTs, currentTs)
|
||||
)
|
||||
insertedRowId db
|
||||
|
||||
setGroupConnLinkStartedConnection :: DB.Connection -> GroupInfo -> Bool -> IO GroupInfo
|
||||
setGroupConnLinkStartedConnection db groupInfo@GroupInfo {groupId} connLinkStartedConnection = do
|
||||
currentTs <- getCurrentTime
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET conn_link_started_connection = ?, updated_at = ? WHERE group_id = ?"
|
||||
(BI connLinkStartedConnection, currentTs, groupId)
|
||||
pure groupInfo {connLinkStartedConnection = connLinkStartedConnection}
|
||||
|
||||
updatePreparedUserAndHostMembersInvited :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> GroupMember -> GroupLinkInvitation -> ExceptT StoreError IO (GroupInfo, GroupMember)
|
||||
updatePreparedUserAndHostMembersInvited db vr user gInfo hostMember GroupLinkInvitation {fromMember, fromMemberName, invitedMember, groupProfile, accepted} = do
|
||||
let fromMemberProfile = profileFromName fromMemberName
|
||||
initialStatus = maybe GSMemAccepted (acceptanceToStatus $ memberAdmission groupProfile) accepted
|
||||
updatePreparedUserAndHostMembers' db vr user gInfo hostMember fromMember fromMemberProfile invitedMember groupProfile initialStatus
|
||||
|
||||
updatePreparedUserAndHostMembersRejected :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> GroupMember -> GroupLinkRejection -> ExceptT StoreError IO (GroupInfo, GroupMember)
|
||||
updatePreparedUserAndHostMembersRejected db vr user gInfo hostMember GroupLinkRejection {fromMember = fromMember@MemberIdRole {memberId}, invitedMember, groupProfile} = do
|
||||
let fromMemberProfile = profileFromName $ nameFromMemberId memberId
|
||||
updatePreparedUserAndHostMembers' db vr user gInfo hostMember fromMember fromMemberProfile invitedMember groupProfile GSMemRejected
|
||||
|
||||
updatePreparedUserAndHostMembers' :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> GroupMember -> MemberIdRole -> Profile -> MemberIdRole -> GroupProfile -> GroupMemberStatus -> ExceptT StoreError IO (GroupInfo, GroupMember)
|
||||
updatePreparedUserAndHostMembers'
|
||||
db
|
||||
vr
|
||||
user
|
||||
gInfo@GroupInfo {groupId, groupProfile = gp}
|
||||
hostMember
|
||||
fromMember
|
||||
fromMemberProfile
|
||||
invitedMember
|
||||
groupProfile
|
||||
membershipStatus = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
liftIO $ updateUserMember currentTs
|
||||
hostMember' <- updateHostMember currentTs
|
||||
when (gp /= groupProfile) $
|
||||
void $ updateGroupProfile db user gInfo groupProfile
|
||||
gInfo' <- getGroupInfo db vr user groupId
|
||||
pure (gInfo', hostMember')
|
||||
where
|
||||
updateUserMember currentTs = do
|
||||
let GroupInfo {membership} = gInfo
|
||||
MemberIdRole memberId memberRole = invitedMember
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET member_id = ?,
|
||||
member_role = ?,
|
||||
member_status = ?,
|
||||
updated_at = ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(memberId, memberRole, membershipStatus, currentTs, groupMemberId' membership)
|
||||
updateHostMember currentTs = do
|
||||
_ <- updateMemberProfile db user hostMember fromMemberProfile
|
||||
let MemberIdRole memberId memberRole = fromMember
|
||||
gmId = groupMemberId' hostMember
|
||||
liftIO $
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE group_members
|
||||
SET member_id = ?,
|
||||
member_role = ?,
|
||||
updated_at = ?
|
||||
WHERE group_member_id = ?
|
||||
|]
|
||||
(memberId, memberRole, currentTs, gmId)
|
||||
getGroupMemberById db vr user gmId
|
||||
|
||||
createGroupInvitedViaLink :: DB.Connection -> VersionRangeChat -> User -> Connection -> GroupLinkInvitation -> ExceptT StoreError IO (GroupInfo, GroupMember)
|
||||
createGroupInvitedViaLink db vr user conn GroupLinkInvitation {fromMember, fromMemberName, invitedMember, groupProfile, accepted, business} = do
|
||||
@@ -578,7 +666,7 @@ createGroupViaLink'
|
||||
business
|
||||
membershipStatus = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
groupId <- createGroup_ db userId groupProfile Nothing business currentTs
|
||||
(groupId, _groupLDN) <- createGroup_ db userId groupProfile Nothing business currentTs
|
||||
hostMemberId <- insertHost_ currentTs groupId
|
||||
liftIO $ DB.execute db "UPDATE connections SET conn_type = ?, group_member_id = ?, updated_at = ? WHERE connection_id = ?" (ConnMember, hostMemberId, currentTs, connId)
|
||||
-- using IBUnknown since host is created without contact
|
||||
@@ -603,7 +691,7 @@ createGroupViaLink'
|
||||
)
|
||||
insertedRowId db
|
||||
|
||||
createGroup_ :: DB.Connection -> UserId -> GroupProfile -> Maybe ACreatedConnLink -> Maybe BusinessChatInfo -> UTCTime -> ExceptT StoreError IO GroupId
|
||||
createGroup_ :: DB.Connection -> UserId -> GroupProfile -> Maybe ACreatedConnLink -> Maybe BusinessChatInfo -> UTCTime -> ExceptT StoreError IO (GroupId, Text)
|
||||
createGroup_ db userId groupProfile connLinkToConnect business currentTs = ExceptT $ do
|
||||
let GroupProfile {displayName, fullName, description, image, groupPreferences, memberAdmission} = groupProfile
|
||||
withLocalDisplayName db userId displayName $ \localDisplayName -> runExceptT $ do
|
||||
@@ -623,7 +711,8 @@ createGroup_ db userId groupProfile connLinkToConnect business currentTs = Excep
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
((profileId, localDisplayName, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. connLinkToConnectRow connLinkToConnect :. businessChatInfoRow business)
|
||||
insertedRowId db
|
||||
groupId <- insertedRowId db
|
||||
pure (groupId, localDisplayName)
|
||||
|
||||
setViaGroupLinkHash :: DB.Connection -> GroupId -> Int64 -> IO ()
|
||||
setViaGroupLinkHash db groupId connId =
|
||||
@@ -800,7 +889,8 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
@@ -893,6 +983,14 @@ getGroupMember db vr user@User {userId} groupId groupMemberId =
|
||||
(groupMemberQuery <> " WHERE m.group_id = ? AND m.group_member_id = ? AND m.user_id = ?")
|
||||
(userId, groupId, groupMemberId, userId)
|
||||
|
||||
getHostMember :: DB.Connection -> VersionRangeChat -> User -> GroupId -> ExceptT StoreError IO GroupMember
|
||||
getHostMember db vr user@User {userId} groupId =
|
||||
ExceptT . firstRow (toContactMember vr user) (SEGroupHostMemberNotFound groupId) $
|
||||
DB.query
|
||||
db
|
||||
(groupMemberQuery <> " WHERE m.group_id = ? AND m.member_category = ?")
|
||||
(userId, groupId, GCHostMember)
|
||||
|
||||
getMentionedGroupMember :: DB.Connection -> User -> GroupId -> GroupMemberId -> ExceptT StoreError IO CIMention
|
||||
getMentionedGroupMember db User {userId} groupId gmId =
|
||||
ExceptT $
|
||||
@@ -1660,7 +1758,8 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
|
||||
@@ -13,8 +13,10 @@ m20250526_short_links =
|
||||
[sql|
|
||||
ALTER TABLE contacts ADD COLUMN conn_full_link_to_connect BLOB;
|
||||
ALTER TABLE contacts ADD COLUMN conn_short_link_to_connect BLOB;
|
||||
|
||||
ALTER TABLE groups ADD COLUMN conn_full_link_to_connect BLOB;
|
||||
ALTER TABLE groups ADD COLUMN conn_short_link_to_connect BLOB;
|
||||
ALTER TABLE groups ADD COLUMN conn_link_started_connection INTEGER NOT NULL DEFAULT 0;
|
||||
|]
|
||||
|
||||
down_m20250526_short_links :: Query
|
||||
@@ -22,6 +24,8 @@ down_m20250526_short_links =
|
||||
[sql|
|
||||
ALTER TABLE contacts DROP COLUMN conn_full_link_to_connect;
|
||||
ALTER TABLE contacts DROP COLUMN conn_short_link_to_connect;
|
||||
|
||||
ALTER TABLE groups DROP COLUMN conn_full_link_to_connect;
|
||||
ALTER TABLE groups DROP COLUMN conn_short_link_to_connect;
|
||||
ALTER TABLE groups DROP COLUMN conn_link_started_connection;
|
||||
|]
|
||||
|
||||
@@ -46,7 +46,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
@@ -277,6 +278,16 @@ SEARCH contact_profiles USING INTEGER PRIMARY KEY (rowid=?)
|
||||
LIST SUBQUERY 1
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET member_id = ?,
|
||||
member_role = ?,
|
||||
updated_at = ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE xftp_file_descriptions
|
||||
SET file_descr_text = ?, file_descr_part_no = ?, file_descr_complete = ?
|
||||
@@ -294,6 +305,14 @@ Query:
|
||||
Plan:
|
||||
SEARCH users USING COVERING INDEX sqlite_autoindex_users_1 (contact_id=?)
|
||||
|
||||
Query:
|
||||
INSERT INTO group_members
|
||||
( group_id, member_id, member_role, member_category, member_status, invited_by,
|
||||
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|
||||
Plan:
|
||||
|
||||
Query:
|
||||
INSERT INTO group_members
|
||||
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
|
||||
@@ -656,6 +675,17 @@ Query:
|
||||
Plan:
|
||||
SEARCH chat_items USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET member_id = ?,
|
||||
member_role = ?,
|
||||
member_status = ?,
|
||||
updated_at = ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM chat_item_reactions
|
||||
WHERE contact_id = ? AND shared_msg_id = ? AND reaction_sent = ? AND reaction = ?
|
||||
@@ -853,7 +883,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupInfo {membership}
|
||||
@@ -902,7 +933,8 @@ Query:
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
@@ -4580,7 +4612,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
@@ -4605,7 +4638,8 @@ Query:
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
@@ -4683,6 +4717,31 @@ SEARCH c USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH cc USING COVERING INDEX idx_connections_group_member (user_id=? AND group_member_id=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction,
|
||||
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
|
||||
m.created_at, m.updated_at,
|
||||
m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts,
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id,
|
||||
c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter,
|
||||
c.conn_chat_version, c.peer_chat_min_version, c.peer_chat_max_version
|
||||
FROM group_members m
|
||||
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
|
||||
LEFT JOIN connections c ON c.connection_id = (
|
||||
SELECT max(cc.connection_id)
|
||||
FROM connections cc
|
||||
WHERE cc.user_id = ? AND cc.group_member_id = m.group_member_id
|
||||
)
|
||||
WHERE m.group_id = ? AND m.member_category = ?
|
||||
Plan:
|
||||
SEARCH m USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH cc USING COVERING INDEX idx_connections_group_member (user_id=? AND group_member_id=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction,
|
||||
@@ -6013,6 +6072,10 @@ Query: UPDATE groups SET chat_ts = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET conn_link_started_connection = ?, updated_at = ? WHERE group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET enable_ntfs = ?, send_rcpts = ?, favorite = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
@@ -139,7 +139,8 @@ CREATE TABLE groups(
|
||||
local_alias TEXT DEFAULT '',
|
||||
members_require_attention INTEGER NOT NULL DEFAULT 0,
|
||||
conn_full_link_to_connect BLOB,
|
||||
conn_short_link_to_connect BLOB, -- received
|
||||
conn_short_link_to_connect BLOB,
|
||||
conn_link_started_connection INTEGER NOT NULL DEFAULT 0, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
|
||||
@@ -89,6 +89,7 @@ data StoreError
|
||||
| SEGroupNotFoundByName {groupName :: GroupName}
|
||||
| SEGroupMemberNameNotFound {groupId :: GroupId, groupMemberName :: ContactName}
|
||||
| SEGroupMemberNotFound {groupMemberId :: GroupMemberId}
|
||||
| SEGroupHostMemberNotFound {groupId :: GroupId}
|
||||
| SEGroupMemberNotFoundByMemberId {memberId :: MemberId}
|
||||
| SEMemberContactGroupMemberNotFound {contactId :: ContactId}
|
||||
| SEGroupWithoutUser
|
||||
@@ -597,12 +598,12 @@ safeDeleteLDN db User {userId} localDisplayName = do
|
||||
|
||||
type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe MemberId)
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime, Maybe ConnReqContact, Maybe ShortLinkContact) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64, Int) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. (Maybe ConnReqContact, Maybe ShortLinkContact, BoolInt) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64, Int) :. GroupMemberRow
|
||||
|
||||
type GroupMemberRow = (Int64, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnLinkContact, LocalAlias, Maybe Preferences) :. (UTCTime, UTCTime) :. (Maybe UTCTime, Int64, Int64, Int64, Maybe UTCTime)
|
||||
|
||||
toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt, connFullLink, connShortLink) :. businessRow :. (uiThemes, customData, chatItemTTL, membersRequireAttention) :. userMemberRow) =
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. (connFullLink, connShortLink, BI connLinkStartedConnection) :. businessRow :. (uiThemes, customData, chatItemTTL, membersRequireAttention) :. userMemberRow) =
|
||||
let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
@@ -611,7 +612,7 @@ toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName,
|
||||
connLinkToConnect = case (connFullLink, connShortLink) of
|
||||
(Nothing, _) -> Nothing
|
||||
(Just fullLink, shortLink_) -> Just $ CCLink fullLink shortLink_
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, connLinkToConnect, chatTags, chatItemTTL, uiThemes, customData, membersRequireAttention}
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, connLinkToConnect, connLinkStartedConnection, chatTags, chatItemTTL, uiThemes, customData, membersRequireAttention}
|
||||
|
||||
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
|
||||
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, BI showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences) :. (createdAt, updatedAt) :. (supportChatTs_, supportChatUnread, supportChatMemberAttention, supportChatMentions, supportChatLastMsgFromMemberTs)) =
|
||||
@@ -644,7 +645,8 @@ groupInfoQuery =
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.conn_full_link_to_connect, g.conn_short_link_to_connect,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.ui_themes, g.custom_data, g.chat_item_ttl, g.members_require_attention,
|
||||
-- GroupMember - membership
|
||||
|
||||
@@ -420,6 +420,7 @@ data GroupInfo = GroupInfo
|
||||
chatTs :: Maybe UTCTime,
|
||||
userMemberProfileSentAt :: Maybe UTCTime,
|
||||
connLinkToConnect :: Maybe CreatedLinkContact,
|
||||
connLinkStartedConnection :: Bool,
|
||||
chatTags :: [ChatTagId],
|
||||
chatItemTTL :: Maybe Int64,
|
||||
uiThemes :: Maybe UIThemeEntityOverrides,
|
||||
|
||||
@@ -195,6 +195,7 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, testView} liveIte
|
||||
CRSentConfirmation u _ -> ttyUser u ["confirmation sent!"]
|
||||
CRSentInvitation u _ customUserProfile -> ttyUser u $ viewSentInvitation customUserProfile testView
|
||||
CRStartedConnectionToContact u c -> ttyUser u [ttyContact' c <> ": connection started"]
|
||||
CRStartedConnectionToGroup u g -> ttyUser u [ttyGroup' g <> ": connection started"]
|
||||
CRSentInvitationToContact u _c customUserProfile -> ttyUser u $ viewSentInvitation customUserProfile testView
|
||||
CRItemsReadForChat u _chatId -> ttyUser u ["items read for chat"]
|
||||
CRContactDeleted u c -> ttyUser u [ttyContact' c <> ": contact is deleted"]
|
||||
|
||||
Reference in New Issue
Block a user