mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-25 07:42:15 +00:00
core, ui: admission message (#5848)
This commit is contained in:
@@ -2569,7 +2569,7 @@ data class ChatItem (
|
||||
else -> CIMergeCategory.RcvGroupEvent
|
||||
}
|
||||
is CIContent.SndGroupEventContent -> when (content.sndGroupEvent) {
|
||||
is SndGroupEvent.UserRole, is SndGroupEvent.UserLeft -> null
|
||||
is SndGroupEvent.UserRole, is SndGroupEvent.UserLeft, is SndGroupEvent.UserPendingReview -> null
|
||||
else -> CIMergeCategory.SndGroupEvent
|
||||
}
|
||||
else -> {
|
||||
@@ -4349,6 +4349,7 @@ sealed class SndGroupEvent() {
|
||||
@Serializable @SerialName("memberDeleted") class MemberDeleted(val groupMemberId: Long, val profile: Profile): SndGroupEvent()
|
||||
@Serializable @SerialName("userLeft") class UserLeft(): SndGroupEvent()
|
||||
@Serializable @SerialName("groupUpdated") class GroupUpdated(val groupProfile: GroupProfile): SndGroupEvent()
|
||||
@Serializable @SerialName("userPendingReview") class UserPendingReview(): SndGroupEvent()
|
||||
|
||||
val text: String get() = when (this) {
|
||||
is MemberRole -> String.format(generalGetString(MR.strings.snd_group_event_changed_member_role), profile.profileViewName, role.text)
|
||||
@@ -4361,6 +4362,7 @@ sealed class SndGroupEvent() {
|
||||
is MemberDeleted -> String.format(generalGetString(MR.strings.snd_group_event_member_deleted), profile.profileViewName)
|
||||
is UserLeft -> generalGetString(MR.strings.snd_group_event_user_left)
|
||||
is GroupUpdated -> generalGetString(MR.strings.snd_group_event_group_profile_updated)
|
||||
is UserPendingReview -> generalGetString(MR.strings.snd_group_event_user_pending_review)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -636,6 +636,15 @@ fun ChatItemView(
|
||||
CIEventView(eventItemViewText(reversedChatItems))
|
||||
}
|
||||
|
||||
@Composable fun UserPendingReviewEventItemView() {
|
||||
Text(
|
||||
buildAnnotatedString {
|
||||
withStyle(chatEventStyle.copy(fontWeight = FontWeight.Bold)) { append(cItem.content.text) }
|
||||
},
|
||||
Modifier.padding(horizontal = 6.dp, vertical = 6.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DeletedItem() {
|
||||
MarkedDeletedItemView(chatsCtx, cItem, cInfo, cInfo.timedMessagesTTL, revealed, showViaProxy = showViaProxy, showTimestamp = showTimestamp)
|
||||
@@ -717,7 +726,10 @@ fun ChatItemView(
|
||||
MsgContentItemDropdownMenu()
|
||||
}
|
||||
is CIContent.SndGroupEventContent -> {
|
||||
EventItemView()
|
||||
when (c.sndGroupEvent) {
|
||||
is SndGroupEvent.UserPendingReview -> UserPendingReviewEventItemView()
|
||||
else -> EventItemView()
|
||||
}
|
||||
MsgContentItemDropdownMenu()
|
||||
}
|
||||
is CIContent.RcvConnEventContent -> {
|
||||
|
||||
@@ -1594,6 +1594,7 @@
|
||||
<string name="snd_group_event_member_deleted">you removed %1$s</string>
|
||||
<string name="snd_group_event_user_left">you left</string>
|
||||
<string name="snd_group_event_group_profile_updated">group profile updated</string>
|
||||
<string name="snd_group_event_user_pending_review">Please wait for group moderators to review your request to join the group.</string>
|
||||
|
||||
<string name="rcv_group_event_1_member_connected">%s connected</string>
|
||||
<string name="rcv_group_event_2_members_connected">%s and %s connected</string>
|
||||
|
||||
@@ -967,10 +967,17 @@ profileToSendOnAccept user ip = userProfileToSend user (getIncognitoProfile <$>
|
||||
ExistingIncognito lp -> fromLocalProfile lp
|
||||
|
||||
introduceToModerators :: VersionRangeChat -> User -> GroupInfo -> GroupMember -> CM ()
|
||||
introduceToModerators vr user gInfo m = do
|
||||
introduceToModerators vr user gInfo@GroupInfo {groupId} m = do
|
||||
when (maxVersion (memberChatVRange m) < groupKnockingVersion) $ sendPendingReviewMessage
|
||||
modMs <- withStore' $ \db -> getGroupModerators db vr user gInfo
|
||||
let rcpModMs = filter memberCurrent modMs
|
||||
introduceMember vr user gInfo m rcpModMs (Just $ MSMember $ memberId' m)
|
||||
where
|
||||
sendPendingReviewMessage = case memberConn m of
|
||||
Just conn -> do
|
||||
let event = XMsgNew $ MCSimple $ extMsgContent (MCText pendingReviewMessage) Nothing
|
||||
sendGroupMemberMessages user conn [event] groupId
|
||||
Nothing -> pure ()
|
||||
|
||||
introduceToAll :: VersionRangeChat -> User -> GroupInfo -> GroupMember -> CM ()
|
||||
introduceToAll vr user gInfo m = do
|
||||
|
||||
@@ -796,9 +796,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
when (connChatVersion < batchSend2Version) sendGroupAutoReply
|
||||
case mStatus of
|
||||
GSMemPendingApproval -> pure ()
|
||||
-- edge case: reviews were turned off mid connection;
|
||||
-- options: proceed to review as declared, or introduce to group and send XGrpLinkAcpt;
|
||||
-- choosing first option for simplicity, same edge case for approval is also not considered
|
||||
GSMemPendingReview -> introduceToModerators vr user gInfo' m'
|
||||
_ -> do
|
||||
introduceToAll vr user gInfo' m'
|
||||
@@ -2470,7 +2467,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
pure (announcedMember', Just scopeInfo)
|
||||
|
||||
xGrpMemIntro :: GroupInfo -> GroupMember -> MemberInfo -> Maybe MemberRestrictions -> CM ()
|
||||
xGrpMemIntro gInfo@GroupInfo {chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memChatVRange _) memRestrictions = do
|
||||
xGrpMemIntro gInfo@GroupInfo {membership, chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memChatVRange _) memRestrictions = do
|
||||
case memberCategory m of
|
||||
GCHostMember ->
|
||||
withStore' (\db -> runExceptT $ getGroupMemberByMemberId db vr user gInfo memId) >>= \case
|
||||
@@ -2481,6 +2478,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
Nothing -> messageError "x.grp.mem.intro: member chat version range incompatible"
|
||||
Just (ChatVersionRange mcvr)
|
||||
| maxVersion mcvr >= groupDirectInvVersion -> do
|
||||
memCount <- withStore' $ \db -> getGroupMembersCount db user gInfo
|
||||
-- only create SGEUserPendingReview item on the first introduction - when only 2 members are user and host
|
||||
when (memberPending membership && memCount == 2) $ do
|
||||
(gInfo', m', scopeInfo) <- mkGroupChatScope gInfo m
|
||||
createInternalChatItem user (CDGroupSnd gInfo' scopeInfo) (CISndGroupEvent SGEUserPendingReview) Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
-- [async agent commands] commands should be asynchronous, continuation is to send XGrpMemInv - have to remember one has completed and process on second
|
||||
groupConnIds <- createConn subMode
|
||||
|
||||
@@ -341,6 +341,12 @@ sndGroupEventToText = \case
|
||||
SGEMemberDeleted _ p -> "removed " <> profileToText p
|
||||
SGEUserLeft -> "left"
|
||||
SGEGroupUpdated _ -> "group profile updated"
|
||||
SGEUserPendingReview -> "please wait for group moderators to review your request to join the group"
|
||||
|
||||
-- used to send to members with old version
|
||||
pendingReviewMessage :: Text
|
||||
pendingReviewMessage =
|
||||
"Please wait for group moderators to review your request to join the group."
|
||||
|
||||
rcvConnEventToText :: RcvConnEvent -> Text
|
||||
rcvConnEventToText = \case
|
||||
|
||||
@@ -40,6 +40,7 @@ data SndGroupEvent
|
||||
| SGEMemberDeleted {groupMemberId :: GroupMemberId, profile :: Profile} -- CRUserDeletedMembers
|
||||
| SGEUserLeft -- CRLeftMemberUser
|
||||
| SGEGroupUpdated {groupProfile :: GroupProfile} -- CRGroupUpdated
|
||||
| SGEUserPendingReview
|
||||
deriving (Show)
|
||||
|
||||
data RcvConnEvent
|
||||
|
||||
@@ -56,6 +56,7 @@ module Simplex.Chat.Store.Groups
|
||||
getGroupMembers,
|
||||
getGroupModerators,
|
||||
getGroupMembersForExpiration,
|
||||
getGroupMembersCount,
|
||||
getGroupCurrentMembersCount,
|
||||
deleteGroupChatItems,
|
||||
deleteGroupMembers,
|
||||
@@ -944,6 +945,11 @@ toContactMember :: VersionRangeChat -> User -> (GroupMemberRow :. MaybeConnectio
|
||||
toContactMember vr User {userContactId} (memberRow :. connRow) =
|
||||
(toGroupMember userContactId memberRow) {activeConn = toMaybeConnection vr connRow}
|
||||
|
||||
getGroupMembersCount :: DB.Connection -> User -> GroupInfo -> IO Int
|
||||
getGroupMembersCount db User {userId} GroupInfo {groupId} =
|
||||
fromOnly . head
|
||||
<$> DB.query db "SELECT COUNT(1) FROM group_members WHERE group_id = ? AND user_id = ?" (groupId, userId)
|
||||
|
||||
getGroupCurrentMembersCount :: DB.Connection -> User -> GroupInfo -> IO Int
|
||||
getGroupCurrentMembersCount db User {userId} GroupInfo {groupId} = do
|
||||
statuses :: [GroupMemberStatus] <-
|
||||
|
||||
@@ -5650,6 +5650,10 @@ Query: SELECT COUNT(1) FROM contacts WHERE user_id = ? AND chat_item_ttl > 0
|
||||
Plan:
|
||||
SEARCH contacts USING INDEX idx_contacts_chat_ts (user_id=?)
|
||||
|
||||
Query: SELECT COUNT(1) FROM group_members WHERE group_id = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_group_id (user_id=? AND group_id=?)
|
||||
|
||||
Query: SELECT COUNT(1) FROM groups WHERE user_id = ? AND chat_item_ttl > 0
|
||||
Plan:
|
||||
SEARCH groups USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
|
||||
Reference in New Issue
Block a user