From e29a9371b6fb71905e7f36ba51ce55a54150d877 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 13 May 2025 16:29:47 +0000 Subject: [PATCH] core, kotlin: open support chat with any member (#5904) --- .../views/chat/group/GroupChatInfoView.kt | 5 +++- .../views/chat/group/GroupMemberInfoView.kt | 9 ++++--- src/Simplex/Chat/Store/Messages.hs | 26 ++++++++++++++----- tests/ChatTests/Groups.hs | 5 ++-- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index 006456004b..ee0d0e33cd 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -483,7 +483,10 @@ fun ModalData.GroupChatInfoLayout( } } } - if (groupInfo.membership.supportChat != null) { + if ( + groupInfo.membership.memberActive && + (groupInfo.membership.memberRole < GroupMemberRole.Moderator || groupInfo.membership.supportChat != null) + ) { anyTopSectionRowShow = true UserSupportChatButton(groupInfo, scrollToItemId) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt index 7a3bd60e14..3a0cb5a3bf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt @@ -439,10 +439,11 @@ fun GroupMemberInfoLayout( if (member.memberActive) { SectionView { - // TODO [knocking] allow creating support chat with members that don't have it (currently doesn't work) - // groupInfo.membership.memberRole >= GroupMemberRole.Moderator && - // (member.memberRole <= GroupMemberRole.Moderator || member.supportChat != null) - if (groupInfo.membership.memberRole >= GroupMemberRole.Moderator && member.supportChat != null) { + if ( + groupInfo.membership.memberRole >= GroupMemberRole.Moderator && + member.memberActive && + (member.memberRole < GroupMemberRole.Moderator || member.supportChat != null) + ) { SupportChatButton() } if (connectionCode != null) { diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 6331a3daf6..d6affc4f12 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -150,7 +150,7 @@ import Data.List.NonEmpty (NonEmpty) import qualified Data.List.NonEmpty as L import Data.Map.Strict (Map) import qualified Data.Map.Strict as M -import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe) +import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, mapMaybe) import Data.Ord (Down (..), comparing) import Data.Text (Text) import qualified Data.Text as T @@ -1352,7 +1352,7 @@ getGroupChat :: DB.Connection -> VersionRangeChat -> User -> Int64 -> Maybe Grou getGroupChat db vr user groupId scope_ contentFilter pagination search_ = do let search = fromMaybe "" search_ g <- getGroupInfo db vr user groupId - scopeInfo <- mapM (getGroupChatScopeInfo db vr user g) scope_ + scopeInfo <- mapM (getCreateGroupChatScopeInfo db vr user g) scope_ case pagination of CPLast count -> (,Nothing) <$> getGroupChatLast_ db user g scopeInfo contentFilter count search emptyChatStats CPAfter afterId count -> (,Nothing) <$> getGroupChatAfter_ db user g scopeInfo contentFilter afterId count search @@ -1362,6 +1362,24 @@ getGroupChat db vr user groupId scope_ contentFilter pagination search_ = do unless (null search) $ throwError $ SEInternalError "initial chat pagination doesn't support search" getGroupChatInitial_ db user g scopeInfo contentFilter count +getCreateGroupChatScopeInfo :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> GroupChatScope -> ExceptT StoreError IO GroupChatScopeInfo +getCreateGroupChatScopeInfo db vr user GroupInfo {membership} = \case + GCSMemberSupport Nothing -> do + when (isNothing $ supportChat membership) $ do + ts <- liftIO getCurrentTime + liftIO $ setSupportChatTs db (groupMemberId' membership) ts + pure $ GCSIMemberSupport {groupMember_ = Nothing} + GCSMemberSupport (Just gmId) -> do + m <- getGroupMemberById db vr user gmId + when (isNothing $ supportChat m) $ do + ts <- liftIO getCurrentTime + liftIO $ setSupportChatTs db gmId ts + pure GCSIMemberSupport {groupMember_ = Just m} + +getGroupChatScopeInfoForItem :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> ChatItemId -> ExceptT StoreError IO (Maybe GroupChatScopeInfo) +getGroupChatScopeInfoForItem db vr user g itemId = + getGroupChatScopeForItem_ db itemId >>= mapM (getGroupChatScopeInfo db vr user g) + getGroupChatScopeInfo :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> GroupChatScope -> ExceptT StoreError IO GroupChatScopeInfo getGroupChatScopeInfo db vr user GroupInfo {membership} = \case GCSMemberSupport Nothing -> case supportChat membership of @@ -1373,10 +1391,6 @@ getGroupChatScopeInfo db vr user GroupInfo {membership} = \case Nothing -> throwError $ SEInternalError "no support chat" Just _supportChat -> pure GCSIMemberSupport {groupMember_ = Just m} -getGroupChatScopeInfoForItem :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> ChatItemId -> ExceptT StoreError IO (Maybe GroupChatScopeInfo) -getGroupChatScopeInfoForItem db vr user g itemId = - getGroupChatScopeForItem_ db itemId >>= mapM (getGroupChatScopeInfo db vr user g) - getGroupChatScopeForItem_ :: DB.Connection -> ChatItemId -> ExceptT StoreError IO (Maybe GroupChatScope) getGroupChatScopeForItem_ db itemId = ExceptT . firstRow toScope (SEChatItemNotFound itemId) $ diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index 9b55b7cb37..ea83a10cba 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -6969,8 +6969,7 @@ testScopedSupportManyModerators = dan #$> ("/_get chat #1 count=3", chat, [(0, "connected"), (0, "1"), (0, "2")]) dan #$> ("/_get chat #1(_support:3) count=100", chat, [(0, "3"), (0, "4"), (1, "5")]) cath #$> ("/_get chat #1 count=3", chat, [(0, "connected"), (0, "1"), (0, "2")]) - cath ##> "/_get chat #1(_support:3) count=100" - cath <## "chat db error: SEInternalError {message = \"no support chat\"}" + cath #$> ("/_get chat #1(_support:3) count=100", chat, []) alice ##> "/member support chats #team" alice <## "bob (Bob) (id 2): unread: 0, require attention: 0, mentions: 0" @@ -6979,7 +6978,7 @@ testScopedSupportManyModerators = bob ##> "/member support chats #team" bob <## "support: unread: 0, require attention: 0, mentions: 0" cath ##> "/member support chats #team" - cath TestParams -> IO () testScopedSupportUnreadStats =