mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 12:19:54 +00:00
Merge 3a04d5640b
into e31e8a6def
This commit is contained in:
commit
136856f477
21 changed files with 367 additions and 224 deletions
|
@ -1420,7 +1420,6 @@ struct UserContactLink: Decodable, Hashable {
|
|||
|
||||
struct AddressSettings: Codable, Hashable {
|
||||
var businessAddress: Bool
|
||||
var welcomeMessage: String?
|
||||
var autoAccept: AutoAccept?
|
||||
var autoReply: MsgContent?
|
||||
}
|
||||
|
|
|
@ -701,6 +701,7 @@ struct ComposeView: View {
|
|||
private func sendMemberContactInvitation() {
|
||||
Task {
|
||||
do {
|
||||
await MainActor.run { hideKeyboard() }
|
||||
if let mc = connectCheckLinkPreview() {
|
||||
await sending()
|
||||
let contact = try await apiSendMemberContactInvitation(chat.chatInfo.apiId, mc)
|
||||
|
@ -733,13 +734,14 @@ struct ComposeView: View {
|
|||
),
|
||||
secondaryButton:
|
||||
empty
|
||||
? .cancel(Text("Add message")) { keyboardVisible = true }
|
||||
? .cancel(Text("Add message"), action: hideKeyboard)
|
||||
: .cancel()
|
||||
))
|
||||
}
|
||||
|
||||
private func sendConnectPreparedContact() {
|
||||
Task {
|
||||
await MainActor.run { hideKeyboard() }
|
||||
await sending()
|
||||
let mc = connectCheckLinkPreview()
|
||||
if let contact = await apiConnectPreparedContact(contactId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc) {
|
||||
|
@ -756,6 +758,7 @@ struct ComposeView: View {
|
|||
|
||||
private func connectPreparedGroup() {
|
||||
Task {
|
||||
await MainActor.run { hideKeyboard() }
|
||||
await sending()
|
||||
let mc = connectCheckLinkPreview()
|
||||
if let groupInfo = await apiConnectPreparedGroup(groupId: chat.chatInfo.apiId, incognito: incognitoGroupDefault.get(), msg: mc) {
|
||||
|
|
|
@ -371,7 +371,6 @@ struct ToggleShortLinkHeader: View {
|
|||
|
||||
struct AddressSettingsState: Equatable {
|
||||
var businessAddress = false
|
||||
var welcomeMessage = ""
|
||||
var autoAccept = false
|
||||
var autoAcceptIncognito = false
|
||||
var autoReply = ""
|
||||
|
@ -380,7 +379,6 @@ struct AddressSettingsState: Equatable {
|
|||
|
||||
init(settings: AddressSettings) {
|
||||
self.businessAddress = settings.businessAddress
|
||||
self.welcomeMessage = settings.welcomeMessage ?? ""
|
||||
self.autoAccept = settings.autoAccept != nil
|
||||
self.autoAcceptIncognito = settings.autoAccept?.acceptIncognito == true
|
||||
self.autoReply = settings.autoReply?.text ?? ""
|
||||
|
@ -389,7 +387,6 @@ struct AddressSettingsState: Equatable {
|
|||
var addressSettings: AddressSettings {
|
||||
AddressSettings(
|
||||
businessAddress: self.businessAddress,
|
||||
welcomeMessage: self.welcomeMessage.isEmpty ? nil : self.welcomeMessage,
|
||||
autoAccept: self.autoAccept ? AutoAccept(acceptIncognito: self.autoAcceptIncognito) : nil,
|
||||
autoReply: self.autoReply.isEmpty ? nil : MsgContent.text(self.autoReply)
|
||||
)
|
||||
|
@ -463,14 +460,8 @@ struct UserAddressSettingsView: View {
|
|||
autoAcceptToggle().disabled(settings.businessAddress)
|
||||
}
|
||||
|
||||
Section {
|
||||
messageEditor(placeholder: NSLocalizedString("Enter welcome message… (optional)", comment: "placeholder"), text: $settings.welcomeMessage)
|
||||
} header: {
|
||||
Text("Welcome message")
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
} footer: {
|
||||
Text("Shown to your contact before connection.")
|
||||
}
|
||||
// TODO v6.4.1 move auto-reply editor here
|
||||
messageEditor(placeholder: NSLocalizedString("Enter welcome message… (optional)", comment: "placeholder"), text: $settings.autoReply)
|
||||
|
||||
if settings.autoAccept {
|
||||
autoAcceptSection()
|
||||
|
@ -554,7 +545,8 @@ struct UserAddressSettingsView: View {
|
|||
if !ChatModel.shared.addressShortLinkDataSet && !settings.businessAddress {
|
||||
acceptIncognitoToggle()
|
||||
}
|
||||
messageEditor(placeholder: NSLocalizedString("Enter auto-reply message… (optional)", comment: "placeholder"), text: $settings.autoReply)
|
||||
// TODO v6.4.1 show this message editor even with auto-accept disabled
|
||||
messageEditor(placeholder: NSLocalizedString("Enter welcome message… (optional)", comment: "placeholder"), text: $settings.autoReply)
|
||||
} header: {
|
||||
Text("Auto-accept")
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
|
|
|
@ -2217,7 +2217,7 @@ public enum MemberCriteria: String, Codable, Identifiable, Hashable {
|
|||
|
||||
public struct ContactShortLinkData: Codable, Hashable {
|
||||
public var profile: Profile
|
||||
public var message: String?
|
||||
public var message: MsgContent?
|
||||
public var business: Bool
|
||||
}
|
||||
|
||||
|
|
|
@ -521,7 +521,7 @@ object ChatModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun chatItemBelongsToScope(cInfo: ChatInfo, cItem: ChatItem): Boolean =
|
||||
when (secondaryContextFilter) {
|
||||
null ->
|
||||
|
@ -2063,7 +2063,7 @@ enum class MemberCriteria {
|
|||
@Serializable
|
||||
data class ContactShortLinkData (
|
||||
val profile: Profile,
|
||||
val message: String?,
|
||||
val message: MsgContent?,
|
||||
val business: Boolean
|
||||
)
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ initializeBotAddress' logAddress cc = do
|
|||
when logAddress $ do
|
||||
putStrLn $ "Bot's contact address is: " <> B.unpack (maybe (strEncode uri) strEncode shortUri)
|
||||
when (isJust shortUri) $ putStrLn $ "Full contact address for old clients: " <> B.unpack (strEncode uri)
|
||||
let settings = AddressSettings {businessAddress = False, welcomeMessage = Nothing, autoAccept = Just AutoAccept {acceptIncognito = False}, autoReply = Nothing}
|
||||
let settings = AddressSettings {businessAddress = False, autoAccept = Just AutoAccept {acceptIncognito = False}, autoReply = Nothing}
|
||||
void $ sendChatCmd cc $ SetAddressSettings settings
|
||||
|
||||
sendMessage :: ChatController -> Contact -> Text -> IO ()
|
||||
|
|
|
@ -72,6 +72,7 @@ import Simplex.Chat.Library.Internal
|
|||
import Simplex.Chat.Stats
|
||||
import Simplex.Chat.Store
|
||||
import Simplex.Chat.Store.AppSettings
|
||||
import Simplex.Chat.Store.ContactRequest
|
||||
import Simplex.Chat.Store.Connections
|
||||
import Simplex.Chat.Store.Direct
|
||||
import Simplex.Chat.Store.Files
|
||||
|
@ -1153,10 +1154,10 @@ processChatCommand' vr = \case
|
|||
uclId <- getUserContactLinkIdByCReq db connReqId
|
||||
uclGLinkInfo <- getUserContactLinkById db userId uclId
|
||||
pure (uclId, uclGLinkInfo)
|
||||
let UserContactLink {shortLinkDataSet} = ucl
|
||||
let UserContactLink {shortLinkDataSet, addressSettings} = ucl
|
||||
when (shortLinkDataSet && incognito) $ throwCmdError "incognito not allowed for address with short link data"
|
||||
withUserContactLock "acceptContact" uclId $ do
|
||||
cReq <- withFastStore $ \db -> getContactRequest db user connReqId
|
||||
cReq@UserContactRequest {welcomeSharedMsgId} <- withFastStore $ \db -> getContactRequest db user connReqId
|
||||
(ct, conn@Connection {connId}, sqSecured) <- acceptContactRequest user cReq incognito
|
||||
let contactUsed = isNothing gLinkInfo_
|
||||
ct' <- withStore' $ \db -> do
|
||||
|
@ -1166,6 +1167,13 @@ processChatCommand' vr = \case
|
|||
then conn {connStatus = ConnSndReady} <$ updateConnectionStatusFromTo db connId ConnNew ConnSndReady
|
||||
else pure conn
|
||||
pure ct {contactUsed, activeConn = Just conn'}
|
||||
when sqSecured $ forM_ (autoReply addressSettings) $ \mc -> case welcomeSharedMsgId of
|
||||
Just smId ->
|
||||
void $ sendDirectContactMessage user ct' $ XMsgUpdate smId mc M.empty Nothing Nothing Nothing
|
||||
Nothing -> do
|
||||
(msg, _) <- sendDirectContactMessage user ct' $ XMsgNew $ MCSimple $ extMsgContent mc Nothing
|
||||
ci <- saveSndChatItem user (CDDirectSnd ct') msg (CISndMsgContent mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDSnd (DirectChat ct') ci]
|
||||
pure $ CRAcceptingContactRequest user ct'
|
||||
APIRejectContact connReqId -> withUser $ \user -> do
|
||||
userContactLinkId <- withFastStore $ \db -> getUserContactLinkIdByCReq db connReqId
|
||||
|
@ -1748,7 +1756,7 @@ processChatCommand' vr = \case
|
|||
createItem sharedMsgId content = createChatItem user cd True content sharedMsgId Nothing
|
||||
cInfo = GroupChat gInfo Nothing
|
||||
void $ createGroupFeatureItems_ user cd True CIRcvGroupFeature gInfo
|
||||
aci <- mapM (createItem welcomeSharedMsgId . CIRcvMsgContent . MCText) message
|
||||
aci <- mapM (createItem welcomeSharedMsgId . CIRcvMsgContent) message
|
||||
let chat = case aci of
|
||||
Just (AChatItem SCTGroup dir _ ci) -> Chat cInfo [CChatItem dir ci] emptyChatStats {unreadCount = 1, minUnreadItemId = chatItemId' ci}
|
||||
_ -> Chat cInfo [] emptyChatStats
|
||||
|
@ -1759,7 +1767,7 @@ processChatCommand' vr = \case
|
|||
cInfo = DirectChat ct
|
||||
void $ createItem Nothing $ CIRcvDirectE2EEInfo $ E2EInfo $ connRequestPQEncryption cReq
|
||||
void $ createFeatureEnabledItems_ user ct
|
||||
aci <- mapM (createItem welcomeSharedMsgId . CIRcvMsgContent . MCText) message
|
||||
aci <- mapM (createItem welcomeSharedMsgId . CIRcvMsgContent) message
|
||||
let chat = case aci of
|
||||
Just (AChatItem SCTDirect dir _ ci) -> Chat cInfo [CChatItem dir ci] emptyChatStats {unreadCount = 1, minUnreadItemId = chatItemId' ci}
|
||||
_ -> Chat cInfo [] emptyChatStats
|
||||
|
@ -1804,9 +1812,13 @@ processChatCommand' vr = \case
|
|||
ci <- saveSndChatItem user (CDDirectSnd ct') msg (CISndMsgContent mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDSnd (DirectChat ct') ci]
|
||||
pure $ CRStartedConnectionToContact user ct' customUserProfile
|
||||
Just PreparedContact {connLinkToConnect = ACCL SCMContact ccLink, welcomeSharedMsgId} -> do
|
||||
-- TODO [short links] reuse welcomeSharedMsgId
|
||||
msg_ <- forM msgContent_ $ \mc -> (,mc) <$> getSharedMsgId
|
||||
Just PreparedContact {connLinkToConnect = ACCL SCMContact ccLink, welcomeSharedMsgId, requestSharedMsgId} -> do
|
||||
msg_ <- forM msgContent_ $ \mc -> case requestSharedMsgId of
|
||||
Just smId -> pure (smId, mc)
|
||||
Nothing -> do
|
||||
smId <- getSharedMsgId
|
||||
withFastStore' $ \db -> setRequestSharedMsgIdForContact db contactId smId
|
||||
pure (smId, mc)
|
||||
connectViaContact user incognito ccLink welcomeSharedMsgId msg_ (Just $ ACCGContact contactId) >>= \case
|
||||
CRSentInvitation {customUserProfile} -> do
|
||||
-- get updated contact with connection
|
||||
|
@ -1820,12 +1832,20 @@ processChatCommand' vr = \case
|
|||
(gInfo, hostMember) <- withFastStore $ \db -> (,) <$> getGroupInfo db vr user groupId <*> getHostMember db vr user groupId
|
||||
case preparedGroup gInfo of
|
||||
Nothing -> throwCmdError "group doesn't have link to connect"
|
||||
Just PreparedGroup {connLinkToConnect} ->
|
||||
-- TODO [short links] store request message with shared message ID (for business chat)
|
||||
connectViaContact user incognito connLinkToConnect Nothing Nothing (Just $ ACCGGroup gInfo (groupMemberId' hostMember)) >>= \case
|
||||
Just PreparedGroup {connLinkToConnect, welcomeSharedMsgId, requestSharedMsgId} -> do
|
||||
msg_ <- forM msgContent_ $ \mc -> case requestSharedMsgId of
|
||||
Just smId -> pure (smId, mc)
|
||||
Nothing -> do
|
||||
smId <- getSharedMsgId
|
||||
withFastStore' $ \db -> setRequestSharedMsgIdForGroup db groupId smId
|
||||
pure (smId, mc)
|
||||
connectViaContact user incognito connLinkToConnect welcomeSharedMsgId msg_ (Just $ ACCGGroup gInfo $ groupMemberId' hostMember) >>= \case
|
||||
CRSentInvitation {customUserProfile} -> do
|
||||
-- get updated group info (connLinkStartedConnection and incognito membership)
|
||||
gInfo' <- withFastStore $ \db -> getGroupInfo db vr user groupId
|
||||
forM_ msg_ $ \(sharedMsgId, mc) -> do
|
||||
ci <- createChatItem user (CDGroupSnd gInfo' Nothing) False (CISndMsgContent mc) (Just sharedMsgId) Nothing
|
||||
toView $ CEvtNewChatItems user [ci]
|
||||
pure $ CRStartedConnectionToGroup user gInfo' customUserProfile
|
||||
cr -> pure cr
|
||||
APIConnect userId incognito acl -> withUserId userId $ \user -> case acl of
|
||||
|
@ -3461,7 +3481,7 @@ processChatCommand' vr = \case
|
|||
contactShortLinkData :: Profile -> Maybe AddressSettings -> CM UserLinkData
|
||||
contactShortLinkData p settings = do
|
||||
large <- chatReadVar useLargeLinkData
|
||||
let msg = welcomeMessage =<< settings
|
||||
let msg = autoReply =<< settings
|
||||
business = maybe False businessAddress settings
|
||||
contactData
|
||||
| large = ContactShortLinkData p msg business
|
||||
|
@ -4769,10 +4789,10 @@ chatCommandP =
|
|||
dbEncryptionConfig currentKey newKey = DBEncryptionConfig {currentKey, newKey, keepKey = Just False}
|
||||
#endif
|
||||
-- TODO [short links] parser for address settings
|
||||
autoAcceptP = ifM onOffP (businessAA <|> addressAA) (pure $ AddressSettings False Nothing Nothing Nothing)
|
||||
autoAcceptP = ifM onOffP (businessAA <|> addressAA) (pure $ AddressSettings False Nothing Nothing)
|
||||
where
|
||||
addressAA = AddressSettings False Nothing <$> (Just . AutoAccept <$> (" incognito=" *> onOffP <|> pure False)) <*> autoReply
|
||||
businessAA = " business" *> (AddressSettings True Nothing (Just $ AutoAccept False) <$> autoReply)
|
||||
addressAA = AddressSettings False <$> (Just . AutoAccept <$> (" incognito=" *> onOffP <|> pure False)) <*> autoReply
|
||||
businessAA = " business" *> (AddressSettings True (Just $ AutoAccept False) <$> autoReply)
|
||||
autoReply = optional (A.space *> msgContentP)
|
||||
rcCtrlAddressP = RCCtrlAddress <$> ("addr=" *> strP) <*> (" iface=" *> (jsonP <|> text1P))
|
||||
text1P = safeDecodeUtf8 <$> A.takeTill (== ' ')
|
||||
|
|
|
@ -36,7 +36,7 @@ import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing, mapMaybe)
|
|||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text.Encoding (decodeLatin1)
|
||||
import Data.Time.Clock (UTCTime, diffUTCTime)
|
||||
import Data.Time.Clock (UTCTime, diffUTCTime, getCurrentTime)
|
||||
import qualified Data.UUID as UUID
|
||||
import qualified Data.UUID.V4 as V4
|
||||
import Data.Word (Word32)
|
||||
|
@ -580,9 +580,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
createFeatureEnabledItems user ct'
|
||||
(Just PreparedContact {connLinkToConnect = ACCL _ (CCLink cReq _)}, _) ->
|
||||
unless (Just pqEnc == connRequestPQEncryption cReq) createE2EItem
|
||||
(_, Just connReqId) -> do
|
||||
UserContactRequest {pqSupport} <- withStore $ \db -> getContactRequest db user connReqId
|
||||
unless (CR.pqSupportToEnc pqSupport == pqEnc) createE2EItem
|
||||
(_, Just connReqId) ->
|
||||
withStore' (\db -> getContactRequest' db user connReqId) >>= \case
|
||||
Just UserContactRequest {pqSupport} | CR.pqSupportToEnc pqSupport == pqEnc -> pure ()
|
||||
_ -> createE2EItem
|
||||
when (contactConnInitiated conn') $ do
|
||||
let Connection {groupLinkId} = conn'
|
||||
doProbeContacts = isJust groupLinkId
|
||||
|
@ -590,7 +591,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
withStore' $ \db -> resetContactConnInitiated db user conn'
|
||||
forM_ viaUserContactLink $ \userContactLinkId -> do
|
||||
(ucl, gli_) <- withStore $ \db -> getUserContactLinkById db userId userContactLinkId
|
||||
when (connChatVersion < batchSend2Version) $ sendAutoReply ucl ct'
|
||||
-- let UserContactLink {addressSettings = AddressSettings {autoReply}} = ucl
|
||||
when (connChatVersion < batchSend2Version) $ forM_ (autoReply $ addressSettings ucl) $ \mc -> sendAutoReply ct' mc Nothing -- old versions only
|
||||
-- TODO REMOVE LEGACY vvv
|
||||
forM_ gli_ $ \GroupLinkInfo {groupId, memberRole = gLinkMemRole} -> do
|
||||
groupInfo <- withStore $ \db -> getGroupInfo db vr user groupId
|
||||
|
@ -656,9 +658,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
when (directOrUsed ct && sqSecured) $ do
|
||||
lift $ setContactNetworkStatus ct NSConnected
|
||||
toView $ CEvtContactSndReady user ct
|
||||
forM_ viaUserContactLink $ \userContactLinkId -> do
|
||||
when (connChatVersion >= batchSend2Version) $ forM_ viaUserContactLink $ \userContactLinkId -> do
|
||||
(ucl, _) <- withStore $ \db -> getUserContactLinkById db userId userContactLinkId
|
||||
when (connChatVersion >= batchSend2Version) $ sendAutoReply ucl ct
|
||||
forM_ (autoReply $ addressSettings ucl) $ \mc -> do
|
||||
connReq_ <- pure (contactRequestId' ct) $>>= \connReqId -> withStore' (\db -> getContactRequest' db user connReqId)
|
||||
sendAutoReply ct mc connReq_
|
||||
QCONT ->
|
||||
void $ continueSending connEntity conn
|
||||
MWARN msgId err -> do
|
||||
|
@ -678,9 +682,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
-- TODO add debugging output
|
||||
_ -> pure ()
|
||||
where
|
||||
sendAutoReply UserContactLink {addressSettings = AddressSettings {autoReply}} ct =
|
||||
forM_ autoReply $ \mc -> do
|
||||
(msg, _) <- sendDirectContactMessage user ct (XMsgNew $ MCSimple (extMsgContent mc Nothing))
|
||||
sendAutoReply ct mc = \case
|
||||
Just UserContactRequest {welcomeSharedMsgId = Just smId} ->
|
||||
void $ sendDirectContactMessage user ct $ XMsgUpdate smId mc M.empty Nothing Nothing Nothing
|
||||
_ -> do
|
||||
(msg, _) <- sendDirectContactMessage user ct $ XMsgNew $ MCSimple $ extMsgContent mc Nothing
|
||||
ci <- saveSndChatItem user (CDDirectSnd ct) msg (CISndMsgContent mc)
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTDirect SMDSnd (DirectChat ct) ci]
|
||||
|
||||
|
@ -808,9 +814,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
(gInfo'', m'', scopeInfo) <- mkGroupChatScope gInfo' m'
|
||||
let cd = CDGroupRcv gInfo'' scopeInfo m''
|
||||
createInternalChatItem user cd (CIRcvGroupE2EEInfo E2EInfo {pqEnabled = Just PQEncOff}) Nothing
|
||||
createGroupFeatureItems user cd CIRcvGroupFeature gInfo''
|
||||
let business = isJust $ businessChat gInfo''
|
||||
unless business $ createGroupFeatureItems user cd CIRcvGroupFeature gInfo''
|
||||
memberConnectedChatItem gInfo'' scopeInfo m''
|
||||
unless (memberPending membership) $ maybeCreateGroupDescrLocal gInfo'' m''
|
||||
unless (memberPending membership || business) $ maybeCreateGroupDescrLocal gInfo'' m''
|
||||
GCInviteeMember -> do
|
||||
(gInfo', mStatus) <-
|
||||
if not (memberPending m)
|
||||
|
@ -829,7 +836,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
toView $ CEvtJoinedGroupMember user gInfo'' m' {memberStatus = mStatus}
|
||||
let Connection {viaUserContactLink} = conn
|
||||
when (isJust viaUserContactLink && isNothing (memberContactId m')) $ sendXGrpLinkMem gInfo''
|
||||
when (connChatVersion < batchSend2Version) sendGroupAutoReply
|
||||
when (connChatVersion < batchSend2Version) $ getAutoReplyMsg >>= mapM_ (\mc -> sendGroupAutoReply mc Nothing)
|
||||
case mStatus of
|
||||
GSMemPendingApproval -> pure ()
|
||||
GSMemPendingReview -> introduceToModerators vr user gInfo'' m'
|
||||
|
@ -1011,7 +1018,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
JOINED sqSecured _serviceId ->
|
||||
-- [async agent commands] continuation on receiving JOINED
|
||||
when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData ->
|
||||
when (sqSecured && connChatVersion >= batchSend2Version) sendGroupAutoReply
|
||||
when (sqSecured && connChatVersion >= batchSend2Version) $ do
|
||||
mc_ <- getAutoReplyMsg
|
||||
forM_ mc_ $ \mc -> do
|
||||
connReq_ <- withStore' $ \db -> getBusinessContactRequest db user groupId
|
||||
sendGroupAutoReply mc connReq_
|
||||
QCONT -> do
|
||||
continued <- continueSending connEntity conn
|
||||
when continued $ sendPendingGroupMessages user m conn
|
||||
|
@ -1039,22 +1050,23 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
updateGroupItemsErrorStatus db msgId groupMemberId newStatus = do
|
||||
itemIds <- getChatItemIdsByAgentMsgId db connId msgId
|
||||
forM_ itemIds $ \itemId -> updateGroupMemSndStatus' db itemId groupMemberId newStatus
|
||||
sendGroupAutoReply = autoReplyMC >>= mapM_ send
|
||||
where
|
||||
autoReplyMC = do
|
||||
let GroupInfo {businessChat} = gInfo
|
||||
GroupMember {memberId = joiningMemberId} = m
|
||||
case businessChat of
|
||||
Just BusinessChatInfo {customerId, chatType = BCCustomer}
|
||||
| joiningMemberId == customerId -> useReply <$> withStore (`getUserAddress` user)
|
||||
where
|
||||
useReply UserContactLink {addressSettings = AddressSettings {autoReply}} = autoReply
|
||||
_ -> pure Nothing
|
||||
send mc = do
|
||||
msg <- sendGroupMessage' user gInfo [m] (XMsgNew $ MCSimple (extMsgContent mc Nothing))
|
||||
ci <- saveSndChatItem user (CDGroupSnd gInfo Nothing) msg (CISndMsgContent mc)
|
||||
withStore' $ \db -> createGroupSndStatus db (chatItemId' ci) (groupMemberId' m) GSSNew
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTGroup SMDSnd (GroupChat gInfo Nothing) ci]
|
||||
getAutoReplyMsg = do
|
||||
let GroupInfo {businessChat} = gInfo
|
||||
GroupMember {memberId = joiningMemberId} = m
|
||||
case businessChat of
|
||||
Just BusinessChatInfo {customerId, chatType = BCCustomer}
|
||||
| joiningMemberId == customerId -> useReply <$> withStore (`getUserAddress` user)
|
||||
where
|
||||
useReply UserContactLink {addressSettings = AddressSettings {autoReply}} = autoReply
|
||||
_ -> pure Nothing
|
||||
sendGroupAutoReply mc = \case
|
||||
Just UserContactRequest {welcomeSharedMsgId = Just smId} ->
|
||||
void $ sendGroupMessage' user gInfo [m] $ XMsgUpdate smId mc M.empty Nothing Nothing Nothing
|
||||
_ -> do
|
||||
msg <- sendGroupMessage' user gInfo [m] $ XMsgNew $ MCSimple $ extMsgContent mc Nothing
|
||||
ci <- saveSndChatItem user (CDGroupSnd gInfo Nothing) msg (CISndMsgContent mc)
|
||||
withStore' $ \db -> createGroupSndStatus db (chatItemId' ci) (groupMemberId' m) GSSNew
|
||||
toView $ CEvtNewChatItems user [AChatItem SCTGroup SMDSnd (GroupChat gInfo Nothing) ci]
|
||||
|
||||
agentMsgDecryptError :: AgentCryptoError -> (MsgDecryptError, Word32)
|
||||
agentMsgDecryptError = \case
|
||||
|
@ -1255,56 +1267,121 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
|||
REBusinessChat gInfo _clientMember ->
|
||||
-- TODO [short links] update request msg
|
||||
toView $ CEvtBusinessRequestAlreadyAccepted user gInfo
|
||||
RSCurrentRequest ucr re_ repeatRequest -> case re_ of
|
||||
RSCurrentRequest prevUcr_ ucr@UserContactRequest {welcomeSharedMsgId} re_ -> case re_ of
|
||||
Nothing -> toView $ CEvtReceivedContactRequest user ucr Nothing
|
||||
Just (REContact ct) -> do
|
||||
-- TODO [short links] prevent duplicate items
|
||||
-- update welcome message if changed (send update event to UI) and add updated feature items.
|
||||
-- Do not created e2e item on repeat request
|
||||
if repeatRequest
|
||||
then do
|
||||
-- TODO [short links] update request msg
|
||||
-- ....
|
||||
acceptOrShow Nothing -- pass item?
|
||||
else do
|
||||
-- TODO [short links] save sharedMsgId instead of the last Nothing
|
||||
let createItem content = createChatItem user (CDDirectRcv ct) False content Nothing Nothing
|
||||
void $ createItem $ CIRcvDirectE2EEInfo $ E2EInfo $ Just $ CR.pqSupportToEnc $ reqPQSup
|
||||
let cd = CDDirectRcv ct
|
||||
aci_ <- case prevUcr_ of
|
||||
Just UserContactRequest {requestSharedMsgId = prevSharedMsgId_} ->
|
||||
-- TODO [short links] this branch does not update feature items and e2e items, as they are highly unlikely to change
|
||||
-- they will be updated after connection is accepted.
|
||||
upsertDirectRequestItem cd (requestMsg_, prevSharedMsgId_)
|
||||
Nothing -> do
|
||||
let e2eContent = CIRcvDirectE2EEInfo $ E2EInfo $ Just $ CR.pqSupportToEnc $ reqPQSup
|
||||
void $ createChatItem user cd False e2eContent Nothing Nothing
|
||||
void $ createFeatureEnabledItems_ user ct
|
||||
-- TODO [short links] save sharedMsgId
|
||||
aci <- forM requestMsg_ $ \(sharedMsgId, mc) -> do
|
||||
aci <- createItem $ CIRcvMsgContent mc
|
||||
unlessM (asks $ coreApi . config) $ toView $ CEvtNewChatItems user [aci]
|
||||
pure aci
|
||||
acceptOrShow aci
|
||||
where
|
||||
acceptOrShow aci_ =
|
||||
case autoAccept of
|
||||
Nothing -> do
|
||||
let cInfo = DirectChat ct
|
||||
chat = AChat SCTDirect $ case aci_ of
|
||||
Just (AChatItem SCTDirect dir _ ci) -> Chat cInfo [CChatItem dir ci] emptyChatStats {unreadCount = 1, minUnreadItemId = chatItemId' ci}
|
||||
_ -> Chat cInfo [] emptyChatStats
|
||||
toView $ CEvtReceivedContactRequest user ucr (Just chat)
|
||||
Just AutoAccept {acceptIncognito} -> do
|
||||
incognitoProfile <-
|
||||
if not shortLinkDataSet && acceptIncognito
|
||||
then Just . NewIncognito <$> liftIO generateRandomProfile
|
||||
else pure Nothing
|
||||
ct' <- acceptContactRequestAsync user uclId ct ucr incognitoProfile
|
||||
-- chat in event?
|
||||
toView $ CEvtAcceptingContactRequest user ct'
|
||||
forM_ (autoReply addressSettings) $ \mc -> forM_ welcomeSharedMsgId $ \sharedMsgId ->
|
||||
createChatItem user (CDDirectSnd ct) False (CISndMsgContent mc) (Just sharedMsgId) Nothing
|
||||
mapM (createRequestItem cd) requestMsg_
|
||||
case autoAccept of
|
||||
Nothing -> do
|
||||
let cInfo = DirectChat ct
|
||||
chat = AChat SCTDirect $ case aci_ of
|
||||
Just (AChatItem SCTDirect dir _ ci) -> Chat cInfo [CChatItem dir ci] emptyChatStats {unreadCount = 1, minUnreadItemId = chatItemId' ci}
|
||||
_ -> Chat cInfo [] emptyChatStats
|
||||
toView $ CEvtReceivedContactRequest user ucr $ Just chat
|
||||
Just AutoAccept {acceptIncognito} -> do
|
||||
incognitoProfile <-
|
||||
if not shortLinkDataSet && acceptIncognito
|
||||
then Just . NewIncognito <$> liftIO generateRandomProfile
|
||||
else pure Nothing
|
||||
ct' <- acceptContactRequestAsync user uclId ct ucr incognitoProfile
|
||||
toView $ CEvtAcceptingContactRequest user ct'
|
||||
Just (REBusinessChat gInfo clientMember) -> do
|
||||
-- TODO [short links] prevent duplicate items (use repeatRequest like for REContact)
|
||||
(_gInfo', _clientMember') <- acceptBusinessJoinRequestAsync user uclId gInfo clientMember ucr
|
||||
-- TODO [short links] add welcome message if welcomeMsgId is present
|
||||
-- forM_ autoReply $ \arMC ->
|
||||
-- when (shortLinkDataSet && v >= shortLinkDataVersion) $
|
||||
-- createInternalChatItem user (CDGroupSnd gInfo Nothing) (CISndMsgContent arMC) Nothing
|
||||
-- TODO [short links] save sharedMsgId
|
||||
forM_ requestMsg_ $ \(sharedMsgId, mc) ->
|
||||
createInternalChatItem user (CDGroupRcv gInfo Nothing clientMember) (CIRcvMsgContent mc) Nothing
|
||||
let cd = CDGroupRcv gInfo Nothing clientMember
|
||||
void $ case prevUcr_ of
|
||||
Just UserContactRequest {requestSharedMsgId = prevSharedMsgId_} ->
|
||||
-- TODO [short links] this branch does not update feature items and e2e items, as they are highly unlikely to change
|
||||
-- they will be updated after connection is accepted.
|
||||
upsertBusinessRequestItem cd (requestMsg_, prevSharedMsgId_)
|
||||
Nothing -> do
|
||||
-- TODO [short links] possibly, we can just keep them created where they are created on the business side due to auto-accept
|
||||
-- let e2eContent = CIRcvGroupE2EEInfo $ E2EInfo $ Just False -- no PQ encryption in groups
|
||||
-- void $ createChatItem user cd False e2eContent Nothing Nothing
|
||||
-- void $ createFeatureEnabledItems_ user ct
|
||||
forM_ (autoReply addressSettings) $ \arMC -> forM_ welcomeSharedMsgId $ \sharedMsgId ->
|
||||
createChatItem user (CDGroupSnd gInfo Nothing) False (CISndMsgContent arMC) (Just sharedMsgId) Nothing
|
||||
mapM (createRequestItem cd) requestMsg_
|
||||
toView $ CEvtAcceptingBusinessRequest user gInfo
|
||||
where
|
||||
upsertDirectRequestItem :: ChatDirection 'CTDirect 'MDRcv -> (Maybe (SharedMsgId, MsgContent), Maybe SharedMsgId) -> CM (Maybe AChatItem)
|
||||
upsertDirectRequestItem cd@(CDDirectRcv ct@Contact {contactId}) = upsertRequestItem cd updateRequestItem markRequestItemDeleted
|
||||
where
|
||||
updateRequestItem (sharedMsgId, mc) =
|
||||
withStore (\db -> getDirectChatItemBySharedMsgId db user contactId sharedMsgId) >>= \case
|
||||
CChatItem SMDRcv ci@ChatItem {content = CIRcvMsgContent oldMC}
|
||||
| mc /= oldMC -> do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
aci <- withStore' $ \db -> do
|
||||
addInitialAndNewCIVersions db (chatItemId' ci) (chatItemTs' ci, oldMC) (currentTs, mc)
|
||||
aChatItem <$> updateDirectChatItem' db user contactId ci (CIRcvMsgContent mc) True False Nothing Nothing
|
||||
toView $ CEvtChatItemUpdated user aci
|
||||
pure $ Just aci
|
||||
| otherwise -> pure $ Just $ aChatItem ci
|
||||
_ -> pure Nothing
|
||||
where
|
||||
aChatItem = AChatItem SCTDirect SMDRcv (DirectChat ct)
|
||||
markRequestItemDeleted sharedMsgId =
|
||||
withStore' (\db -> runExceptT $ getDirectChatItemBySharedMsgId db user contactId sharedMsgId) >>= \case
|
||||
Right (cci@(CChatItem SMDRcv _)) -> do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
deletions <- if featureAllowed SCFFullDelete forContact ct
|
||||
then deleteDirectCIs user ct [cci]
|
||||
else markDirectCIsDeleted user ct [cci] currentTs
|
||||
toView $ CEvtChatItemsDeleted user deletions False False
|
||||
_ -> pure ()
|
||||
upsertBusinessRequestItem :: ChatDirection 'CTGroup 'MDRcv -> (Maybe (SharedMsgId, MsgContent), Maybe SharedMsgId) -> CM (Maybe AChatItem)
|
||||
upsertBusinessRequestItem cd@(CDGroupRcv gInfo@GroupInfo {groupId} _ clientMember) = upsertRequestItem cd updateRequestItem markRequestItemDeleted
|
||||
where
|
||||
updateRequestItem (sharedMsgId, mc) =
|
||||
withStore (\db -> getGroupChatItemBySharedMsgId db user gInfo (groupMemberId' clientMember) sharedMsgId) >>= \case
|
||||
CChatItem SMDRcv ci@ChatItem {chatDir = CIGroupRcv m', content = CIRcvMsgContent oldMC}
|
||||
| sameMemberId (memberId' clientMember) m' ->
|
||||
if mc /= oldMC
|
||||
then do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
aci <- withStore' $ \db -> do
|
||||
addInitialAndNewCIVersions db (chatItemId' ci) (chatItemTs' ci, oldMC) (currentTs, mc)
|
||||
aChatItem <$> updateGroupChatItem db user groupId ci (CIRcvMsgContent mc) True False Nothing
|
||||
toView $ CEvtChatItemUpdated user aci
|
||||
pure $ Just aci
|
||||
else pure $ Just $ aChatItem ci
|
||||
_ -> pure Nothing
|
||||
where
|
||||
aChatItem = AChatItem SCTGroup SMDRcv (GroupChat gInfo Nothing)
|
||||
markRequestItemDeleted sharedMsgId =
|
||||
withStore' (\db -> runExceptT $ getGroupMemberCIBySharedMsgId db user gInfo (memberId' clientMember) sharedMsgId) >>= \case
|
||||
Right cci@(CChatItem SMDRcv ChatItem {chatDir = CIGroupRcv m'})
|
||||
| sameMemberId (memberId' clientMember) m' -> do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
deletions <- if groupFeatureMemberAllowed SGFFullDelete clientMember gInfo
|
||||
then deleteGroupCIs user gInfo Nothing [cci] Nothing currentTs
|
||||
else markGroupCIsDeleted user gInfo Nothing [cci] Nothing currentTs
|
||||
toView $ CEvtChatItemsDeleted user deletions False False
|
||||
_ -> pure ()
|
||||
createRequestItem :: ChatTypeI c => ChatDirection c 'MDRcv -> (SharedMsgId, MsgContent) -> CM AChatItem
|
||||
createRequestItem cd (sharedMsgId, mc) = do
|
||||
aci <- createChatItem user cd False (CIRcvMsgContent mc) (Just sharedMsgId) Nothing
|
||||
toView $ CEvtNewChatItems user [aci]
|
||||
pure aci
|
||||
upsertRequestItem :: ChatTypeI c => ChatDirection c 'MDRcv -> ((SharedMsgId, MsgContent) -> CM (Maybe AChatItem)) -> (SharedMsgId -> CM ()) -> (Maybe (SharedMsgId, MsgContent), Maybe SharedMsgId) -> CM (Maybe AChatItem)
|
||||
upsertRequestItem cd update delete = \case
|
||||
(Just msg, Nothing) -> Just <$> createRequestItem cd msg
|
||||
(Just msg@(sharedMsgId, _), Just prevSharedMsgId) | sharedMsgId == prevSharedMsgId ->
|
||||
update msg `catchCINotFound` \_ -> Just <$> createRequestItem cd msg
|
||||
(Nothing, Just prevSharedMsgId) -> Nothing <$ delete prevSharedMsgId
|
||||
_ -> pure Nothing
|
||||
-- ##### Group link join requests (don't create contact requests) #####
|
||||
Just gli@GroupLinkInfo {groupId, memberRole = gLinkMemRole} -> do
|
||||
-- TODO [short links] deduplicate request by xContactId?
|
||||
|
|
|
@ -1224,3 +1224,19 @@ instance ToJSON (ChatMessage 'Json) where
|
|||
|
||||
instance FromJSON (ChatMessage 'Json) where
|
||||
parseJSON v = appJsonToCM <$?> parseJSON v
|
||||
|
||||
data ContactShortLinkData = ContactShortLinkData
|
||||
{ profile :: Profile,
|
||||
message :: Maybe MsgContent,
|
||||
business :: Bool
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data GroupShortLinkData = GroupShortLinkData
|
||||
{ groupProfile :: GroupProfile
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''ContactShortLinkData)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''GroupShortLinkData)
|
||||
|
|
|
@ -112,7 +112,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
|||
[sql|
|
||||
SELECT
|
||||
c.contact_profile_id, c.local_display_name, c.via_group, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, c.contact_used, c.contact_status, c.enable_ntfs, c.send_rcpts, c.favorite,
|
||||
p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.conn_full_link_to_connect, c.conn_short_link_to_connect, c.welcome_shared_msg_id, c.contact_request_id,
|
||||
p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.conn_full_link_to_connect, c.conn_short_link_to_connect, c.welcome_shared_msg_id, c.request_shared_msg_id, c.contact_request_id,
|
||||
c.contact_group_member_id, c.contact_grp_inv_sent, c.ui_themes, c.chat_deleted, c.custom_data, c.chat_item_ttl
|
||||
FROM contacts c
|
||||
JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id
|
||||
|
@ -140,7 +140,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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}
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
module Simplex.Chat.Store.ContactRequest
|
||||
( createOrUpdateContactRequest,
|
||||
setContactAcceptedXContactId,
|
||||
setBusinessChatAcceptedXContactId
|
||||
setBusinessChatAcceptedXContactId,
|
||||
setRequestSharedMsgIdForContact,
|
||||
setRequestSharedMsgIdForGroup
|
||||
)
|
||||
where
|
||||
|
||||
|
@ -81,11 +83,14 @@ createOrUpdateContactRequest
|
|||
Just xContactId ->
|
||||
-- 1) first we try to find accepted contact or business chat by xContactId
|
||||
liftIO (getAcceptedContact xContactId) >>= \case
|
||||
Just ct -> pure $ RSAcceptedRequest Nothing (REContact ct)
|
||||
Just ct -> do
|
||||
cr <- liftIO $ getContactRequestByXContactId xContactId
|
||||
pure $ RSAcceptedRequest cr (REContact ct)
|
||||
Nothing -> liftIO (getAcceptedBusinessChat xContactId) >>= \case
|
||||
Just gInfo@GroupInfo {businessChat = Just BusinessChatInfo {customerId}} -> do
|
||||
clientMember <- getGroupMemberByMemberId db vr user gInfo customerId
|
||||
pure $ RSAcceptedRequest Nothing (REBusinessChat gInfo clientMember)
|
||||
cr <- liftIO $ getContactRequestByXContactId xContactId
|
||||
pure $ RSAcceptedRequest cr (REBusinessChat gInfo clientMember)
|
||||
Just GroupInfo {businessChat = Nothing} -> throwError SEInvalidBusinessChatContactRequest
|
||||
-- 2) if no legacy accepted contact or business chat was found, next we try to find an existing request
|
||||
Nothing ->
|
||||
|
@ -105,7 +110,7 @@ createOrUpdateContactRequest
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
@ -196,7 +201,7 @@ createOrUpdateContactRequest
|
|||
(contactId, contactRequestId)
|
||||
ucr <- getContactRequest db user contactRequestId
|
||||
ct <- getContact db vr user contactId
|
||||
pure $ RSCurrentRequest ucr (Just $ REContact ct) False
|
||||
pure $ RSCurrentRequest Nothing ucr (Just $ REContact ct)
|
||||
createBusinessChat = do
|
||||
let Profile {preferences = userPreferences} = profileToSendOnAccept user Nothing True
|
||||
groupPreferences = maybe defaultBusinessGroupPrefs businessGroupPrefs userPreferences
|
||||
|
@ -208,15 +213,15 @@ createOrUpdateContactRequest
|
|||
"UPDATE contact_requests SET business_group_id = ? WHERE contact_request_id = ?"
|
||||
(groupId, contactRequestId)
|
||||
ucr <- getContactRequest db user contactRequestId
|
||||
pure $ RSCurrentRequest ucr (Just $ REBusinessChat gInfo clientMember) False
|
||||
pure $ RSCurrentRequest Nothing ucr (Just $ REBusinessChat gInfo clientMember)
|
||||
updateContactRequest :: UserContactRequest -> ExceptT StoreError IO RequestStage
|
||||
updateContactRequest UserContactRequest {contactRequestId, contactId_, localDisplayName = oldLdn, profile = Profile {displayName = oldDisplayName}} = do
|
||||
updateContactRequest ucr@UserContactRequest {contactRequestId, contactId_, localDisplayName = oldLdn, profile = Profile {displayName = oldDisplayName}} = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
liftIO $ updateProfile currentTs
|
||||
updateRequest currentTs
|
||||
ucr' <- getContactRequest db user contactRequestId
|
||||
re_ <- getRequestEntity ucr'
|
||||
pure $ RSCurrentRequest ucr' re_ True
|
||||
pure $ RSCurrentRequest (Just ucr) ucr' re_
|
||||
where
|
||||
updateProfile currentTs =
|
||||
DB.execute
|
||||
|
@ -288,12 +293,16 @@ createOrUpdateContactRequest
|
|||
|
||||
setContactAcceptedXContactId :: DB.Connection -> Contact -> XContactId -> IO ()
|
||||
setContactAcceptedXContactId db Contact {contactId} xContactId =
|
||||
DB.execute
|
||||
db "UPDATE contacts SET xcontact_id = ? WHERE contact_id = ?"
|
||||
(xContactId, contactId)
|
||||
DB.execute db "UPDATE contacts SET xcontact_id = ? WHERE contact_id = ?" (xContactId, contactId)
|
||||
|
||||
setBusinessChatAcceptedXContactId :: DB.Connection -> GroupInfo -> XContactId -> IO ()
|
||||
setBusinessChatAcceptedXContactId db GroupInfo {groupId} xContactId =
|
||||
DB.execute
|
||||
db "UPDATE groups SET business_xcontact_id = ? WHERE group_id = ?"
|
||||
(xContactId, groupId)
|
||||
DB.execute db "UPDATE groups SET business_xcontact_id = ? WHERE group_id = ?" (xContactId, groupId)
|
||||
|
||||
setRequestSharedMsgIdForContact :: DB.Connection -> ContactId -> SharedMsgId -> IO ()
|
||||
setRequestSharedMsgIdForContact db contactId sharedMsgId = do
|
||||
DB.execute db "UPDATE contacts SET request_shared_msg_id = ? WHERE contact_id = ?" (sharedMsgId, contactId)
|
||||
|
||||
setRequestSharedMsgIdForGroup :: DB.Connection -> GroupId -> SharedMsgId -> IO ()
|
||||
setRequestSharedMsgIdForGroup db groupId sharedMsgId = do
|
||||
DB.execute db "UPDATE groups SET request_shared_msg_id = ? WHERE group_id = ?" (sharedMsgId, groupId)
|
||||
|
|
|
@ -60,6 +60,8 @@ module Simplex.Chat.Store.Direct
|
|||
getUserContacts,
|
||||
getUserContactLinkIdByCReq,
|
||||
getContactRequest,
|
||||
getContactRequest',
|
||||
getBusinessContactRequest,
|
||||
getContactRequestIdByName,
|
||||
deleteContactRequest,
|
||||
createContactFromRequest,
|
||||
|
@ -108,10 +110,10 @@ import qualified Simplex.Messaging.Agent.Store.DB as DB
|
|||
import Simplex.Messaging.Crypto.Ratchet (PQSupport)
|
||||
import Simplex.Messaging.Protocol (SubscriptionMode (..))
|
||||
#if defined(dbPostgres)
|
||||
import Database.PostgreSQL.Simple (Only (..), (:.) (..))
|
||||
import Database.PostgreSQL.Simple (Only (..), Query, (:.) (..))
|
||||
import Database.PostgreSQL.Simple.SqlQQ (sql)
|
||||
#else
|
||||
import Database.SQLite.Simple (Only (..), (:.) (..))
|
||||
import Database.SQLite.Simple (Only (..), Query, (:.) (..))
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
#endif
|
||||
|
||||
|
@ -218,7 +220,7 @@ getContactByConnReqHash db vr user@User {userId} cReqHash = do
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
@ -286,7 +288,7 @@ createPreparedContact db user@User {userId} p@Profile {preferences} connLinkToCo
|
|||
createdAt = currentTs,
|
||||
updatedAt = currentTs,
|
||||
chatTs = Just currentTs,
|
||||
preparedContact = Just $ PreparedContact connLinkToConnect (connMode m) welcomeSharedMsgId,
|
||||
preparedContact = Just PreparedContact {connLinkToConnect, uiConnLinkType = connMode m, welcomeSharedMsgId, requestSharedMsgId = Nothing},
|
||||
contactRequestId = Nothing,
|
||||
contactGroupMemberId = Nothing,
|
||||
contactGrpInvSent = False,
|
||||
|
@ -687,23 +689,32 @@ getUserContactLinkIdByCReq db contactRequestId =
|
|||
getContactRequest :: DB.Connection -> User -> Int64 -> ExceptT StoreError IO UserContactRequest
|
||||
getContactRequest db User {userId} contactRequestId =
|
||||
ExceptT . firstRow toContactRequest (SEContactRequestNotFound contactRequestId) $
|
||||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT
|
||||
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id,
|
||||
cr.contact_id, cr.business_group_id, cr.user_contact_link_id,
|
||||
c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id,
|
||||
cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences,
|
||||
cr.created_at, cr.updated_at,
|
||||
cr.peer_chat_min_version, cr.peer_chat_max_version
|
||||
FROM contact_requests cr
|
||||
JOIN connections c USING (user_contact_link_id)
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ?
|
||||
AND cr.contact_request_id = ?
|
||||
|]
|
||||
(userId, contactRequestId)
|
||||
DB.query db (contactRequestQuery <> " WHERE cr.user_id = ? AND cr.contact_request_id = ?") (userId, contactRequestId)
|
||||
|
||||
getContactRequest' :: DB.Connection -> User -> Int64 -> IO (Maybe UserContactRequest)
|
||||
getContactRequest' db User {userId} contactRequestId =
|
||||
maybeFirstRow toContactRequest $
|
||||
DB.query db (contactRequestQuery <> " WHERE cr.user_id = ? AND cr.contact_request_id = ?") (userId, contactRequestId)
|
||||
|
||||
getBusinessContactRequest :: DB.Connection -> User -> GroupId -> IO (Maybe UserContactRequest)
|
||||
getBusinessContactRequest db User {userId} groupId =
|
||||
maybeFirstRow toContactRequest $
|
||||
DB.query db (contactRequestQuery <> " WHERE cr.user_id = ? AND cr.business_group_id = ?") (userId, groupId)
|
||||
|
||||
contactRequestQuery :: Query
|
||||
contactRequestQuery =
|
||||
[sql|
|
||||
SELECT
|
||||
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id,
|
||||
cr.contact_id, cr.business_group_id, cr.user_contact_link_id,
|
||||
c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id,
|
||||
cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences,
|
||||
cr.created_at, cr.updated_at,
|
||||
cr.peer_chat_min_version, cr.peer_chat_max_version
|
||||
FROM contact_requests cr
|
||||
JOIN connections c USING (user_contact_link_id)
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
|]
|
||||
|
||||
getContactRequestIdByName :: DB.Connection -> UserId -> ContactName -> ExceptT StoreError IO Int64
|
||||
getContactRequestIdByName db userId cName =
|
||||
|
@ -807,7 +818,7 @@ getContact_ db vr user@User {userId} contactId deleted = do
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
|
|
@ -937,7 +937,7 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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,
|
||||
|
@ -1291,7 +1291,7 @@ createBusinessRequestGroup
|
|||
gVar
|
||||
user@User {userId, userContactId}
|
||||
cReqChatVRange
|
||||
Profile {displayName, fullName, image, contactLink, preferences}
|
||||
Profile {displayName, fullName, image}
|
||||
profileId -- contact request profile id, to be used for member profile
|
||||
ldn -- contact request local display name, to be used for group local display name
|
||||
groupPreferences = do
|
||||
|
@ -1813,7 +1813,7 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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}
|
||||
|
|
|
@ -441,9 +441,8 @@ data GroupLinkInfo = GroupLinkInfo
|
|||
|
||||
data AddressSettings = AddressSettings
|
||||
{ businessAddress :: Bool, -- possibly, it can be wrapped together with acceptIncognito, or AutoAccept made sum type
|
||||
welcomeMessage :: Maybe Text, -- included in short link information
|
||||
autoAccept :: Maybe AutoAccept, -- accept automatically
|
||||
autoReply :: Maybe MsgContent -- sent on acceptance, can be supported with manual acceptance as well
|
||||
autoReply :: Maybe MsgContent -- included in short link information, sent on acceptance in case wasn't shown during connection
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
@ -458,11 +457,11 @@ $(J.deriveJSON defaultJSON ''AddressSettings)
|
|||
|
||||
$(J.deriveJSON defaultJSON ''UserContactLink)
|
||||
|
||||
toUserContactLink :: (Int64, ConnReqContact, Maybe ShortLinkContact, BoolInt, BoolInt, Maybe Text, BoolInt, BoolInt, Maybe MsgContent) -> UserContactLink
|
||||
toUserContactLink (userContactLinkId, connReq, shortLink, BI shortLinkDataSet, BI businessAddress, welcomeMessage, BI autoAccept', BI acceptIncognito, autoReply) =
|
||||
toUserContactLink :: (Int64, ConnReqContact, Maybe ShortLinkContact, BoolInt, BoolInt, BoolInt, BoolInt, Maybe MsgContent) -> UserContactLink
|
||||
toUserContactLink (userContactLinkId, connReq, shortLink, BI shortLinkDataSet, BI businessAddress, BI autoAccept', BI acceptIncognito, autoReply) =
|
||||
UserContactLink userContactLinkId (CCLink connReq shortLink) shortLinkDataSet $
|
||||
let autoAccept = if autoAccept' then Just AutoAccept {acceptIncognito} else Nothing
|
||||
in AddressSettings {businessAddress, welcomeMessage, autoAccept, autoReply}
|
||||
in AddressSettings {businessAddress, autoAccept, autoReply}
|
||||
|
||||
getUserAddress :: DB.Connection -> User -> ExceptT StoreError IO UserContactLink
|
||||
getUserAddress db User {userId} =
|
||||
|
@ -475,7 +474,7 @@ getUserContactLinkById db userId userContactLinkId =
|
|||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content, group_id, group_link_member_role
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content, group_id, group_link_member_role
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND user_contact_link_id = ?
|
||||
|]
|
||||
|
@ -511,7 +510,7 @@ getUserContactLinkViaShortLink db User {userId} shortLink =
|
|||
userContactLinkQuery :: Query
|
||||
userContactLinkQuery =
|
||||
[sql|
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
FROM user_contact_links
|
||||
|]
|
||||
|
||||
|
@ -561,15 +560,15 @@ getContactWithoutConnViaShortAddress db vr user@User {userId} shortLink = do
|
|||
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getContact db vr user) ctId_
|
||||
|
||||
updateUserAddressSettings :: DB.Connection -> Int64 -> AddressSettings -> IO ()
|
||||
updateUserAddressSettings db userContactLinkId AddressSettings {businessAddress, welcomeMessage, autoAccept, autoReply} =
|
||||
updateUserAddressSettings db userContactLinkId AddressSettings {businessAddress, autoAccept, autoReply} =
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE user_contact_links
|
||||
SET auto_accept = ?, auto_accept_incognito = ?, business_address = ?, address_welcome_message = ?, auto_reply_msg_content = ?
|
||||
SET auto_accept = ?, auto_accept_incognito = ?, business_address = ?, auto_reply_msg_content = ?
|
||||
WHERE user_contact_link_id = ?
|
||||
|]
|
||||
(autoAcceptValues :. (businessAddress, welcomeMessage, autoReply, userContactLinkId))
|
||||
(autoAcceptValues :. (businessAddress, autoReply, userContactLinkId))
|
||||
where
|
||||
autoAcceptValues = case autoAccept of
|
||||
Just AutoAccept {acceptIncognito} -> (BI True, BI acceptIncognito)
|
||||
|
|
|
@ -11,6 +11,7 @@ m20250526_short_links =
|
|||
ALTER TABLE contacts ADD COLUMN conn_full_link_to_connect BLOB;
|
||||
ALTER TABLE contacts ADD COLUMN conn_short_link_to_connect BLOB;
|
||||
ALTER TABLE contacts ADD COLUMN welcome_shared_msg_id BLOB;
|
||||
ALTER TABLE contacts ADD COLUMN request_shared_msg_id BLOB;
|
||||
|
||||
ALTER TABLE contacts ADD COLUMN contact_request_id INTEGER REFERENCES contact_requests ON DELETE SET NULL;
|
||||
CREATE INDEX idx_contacts_contact_request_id ON contacts(contact_request_id);
|
||||
|
@ -23,12 +24,12 @@ ALTER TABLE contact_requests ADD COLUMN request_shared_msg_id BLOB;
|
|||
ALTER TABLE group_members ADD COLUMN member_xcontact_id BLOB;
|
||||
|
||||
ALTER TABLE user_contact_links ADD COLUMN short_link_data_set INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE user_contact_links ADD COLUMN address_welcome_message TEXT;
|
||||
|
||||
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;
|
||||
ALTER TABLE groups ADD COLUMN welcome_shared_msg_id BLOB;
|
||||
ALTER TABLE groups ADD COLUMN request_shared_msg_id BLOB;
|
||||
|
||||
ALTER TABLE chat_items ADD COLUMN show_group_as_sender INTEGER NOT NULL DEFAULT 0;
|
||||
|]
|
||||
|
@ -39,6 +40,7 @@ down_m20250526_short_links =
|
|||
ALTER TABLE contacts DROP COLUMN conn_full_link_to_connect;
|
||||
ALTER TABLE contacts DROP COLUMN conn_short_link_to_connect;
|
||||
ALTER TABLE contacts DROP COLUMN welcome_shared_msg_id;
|
||||
ALTER TABLE contacts DROP COLUMN request_shared_msg_id;
|
||||
|
||||
DROP INDEX idx_contacts_contact_request_id;
|
||||
ALTER TABLE contacts DROP COLUMN contact_request_id;
|
||||
|
@ -51,12 +53,12 @@ ALTER TABLE contact_requests DROP COLUMN request_shared_msg_id;
|
|||
ALTER TABLE group_members DROP COLUMN member_xcontact_id;
|
||||
|
||||
ALTER TABLE user_contact_links DROP COLUMN short_link_data_set;
|
||||
ALTER TABLE user_contact_links DROP COLUMN address_welcome_message;
|
||||
|
||||
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;
|
||||
ALTER TABLE groups DROP COLUMN welcome_shared_msg_id;
|
||||
ALTER TABLE groups DROP COLUMN request_shared_msg_id;
|
||||
|
||||
ALTER TABLE chat_items DROP COLUMN show_group_as_sender;
|
||||
|]
|
||||
|
|
|
@ -63,7 +63,7 @@ Query:
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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}
|
||||
|
@ -197,7 +197,7 @@ Query:
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
@ -384,7 +384,7 @@ Plan:
|
|||
Query:
|
||||
SELECT
|
||||
c.contact_profile_id, c.local_display_name, c.via_group, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, c.contact_used, c.contact_status, c.enable_ntfs, c.send_rcpts, c.favorite,
|
||||
p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.conn_full_link_to_connect, c.conn_short_link_to_connect, c.welcome_shared_msg_id, c.contact_request_id,
|
||||
p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.conn_full_link_to_connect, c.conn_short_link_to_connect, c.welcome_shared_msg_id, c.request_shared_msg_id, c.contact_request_id,
|
||||
c.contact_group_member_id, c.contact_grp_inv_sent, c.ui_themes, c.chat_deleted, c.custom_data, c.chat_item_ttl
|
||||
FROM contacts c
|
||||
JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id
|
||||
|
@ -920,7 +920,7 @@ Query:
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
@ -945,7 +945,7 @@ Query:
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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}
|
||||
|
@ -995,7 +995,7 @@ Query:
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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,
|
||||
|
@ -1504,7 +1504,7 @@ Query:
|
|||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, cp.contact_link, cp.local_alias, ct.contact_used, ct.contact_status, ct.enable_ntfs, ct.send_rcpts, ct.favorite,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.contact_request_id,
|
||||
cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id,
|
||||
ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl,
|
||||
-- Connection
|
||||
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,
|
||||
|
@ -1692,25 +1692,6 @@ SEARCH cr USING INDEX idx_contact_requests_updated_at (user_id=?)
|
|||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id,
|
||||
cr.contact_id, cr.business_group_id, cr.user_contact_link_id,
|
||||
c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id,
|
||||
cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences,
|
||||
cr.created_at, cr.updated_at,
|
||||
cr.peer_chat_min_version, cr.peer_chat_max_version
|
||||
FROM contact_requests cr
|
||||
JOIN connections c USING (user_contact_link_id)
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ?
|
||||
AND cr.contact_request_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH cr USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
created_at, updated_at, chat_ts, favorite, unread_chat
|
||||
|
@ -3511,7 +3492,7 @@ Plan:
|
|||
SEARCH usage_conditions USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content, group_id, group_link_member_role
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content, group_id, group_link_member_role
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND user_contact_link_id = ?
|
||||
|
||||
|
@ -4620,7 +4601,7 @@ SEARCH server_operators USING INTEGER PRIMARY KEY (rowid=?)
|
|||
|
||||
Query:
|
||||
UPDATE user_contact_links
|
||||
SET auto_accept = ?, auto_accept_incognito = ?, business_address = ?, address_welcome_message = ?, auto_reply_msg_content = ?
|
||||
SET auto_accept = ?, auto_accept_incognito = ?, business_address = ?, auto_reply_msg_content = ?
|
||||
WHERE user_contact_link_id = ?
|
||||
|
||||
Plan:
|
||||
|
@ -4686,7 +4667,7 @@ Query:
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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
|
||||
|
@ -4712,7 +4693,7 @@ Query:
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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
|
||||
|
@ -4732,6 +4713,40 @@ SEARCH gp USING INTEGER PRIMARY KEY (rowid=?)
|
|||
SEARCH mu USING INDEX idx_group_members_contact_id (contact_id=?)
|
||||
SEARCH pu USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id,
|
||||
cr.contact_id, cr.business_group_id, cr.user_contact_link_id,
|
||||
c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id,
|
||||
cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences,
|
||||
cr.created_at, cr.updated_at,
|
||||
cr.peer_chat_min_version, cr.peer_chat_max_version
|
||||
FROM contact_requests cr
|
||||
JOIN connections c USING (user_contact_link_id)
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ? AND cr.business_group_id = ?
|
||||
Plan:
|
||||
SEARCH cr USING INDEX idx_contact_requests_business_group_id (business_group_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_id=?)
|
||||
|
||||
Query:
|
||||
SELECT
|
||||
cr.contact_request_id, cr.local_display_name, cr.agent_invitation_id,
|
||||
cr.contact_id, cr.business_group_id, cr.user_contact_link_id,
|
||||
c.agent_conn_id, cr.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, cr.xcontact_id,
|
||||
cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences,
|
||||
cr.created_at, cr.updated_at,
|
||||
cr.peer_chat_min_version, cr.peer_chat_max_version
|
||||
FROM contact_requests cr
|
||||
JOIN connections c USING (user_contact_link_id)
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ? AND cr.contact_request_id = ?
|
||||
Plan:
|
||||
SEARCH cr USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INDEX idx_connections_user_contact_link_id (user_contact_link_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,
|
||||
|
@ -5171,21 +5186,21 @@ Plan:
|
|||
SCAN usage_conditions
|
||||
|
||||
Query:
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND conn_req_contact IN (?,?)
|
||||
Plan:
|
||||
SEARCH user_contact_links USING INDEX sqlite_autoindex_user_contact_links_1 (user_id=?)
|
||||
|
||||
Query:
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND local_display_name = '' AND group_id IS NULL
|
||||
Plan:
|
||||
SEARCH user_contact_links USING INDEX sqlite_autoindex_user_contact_links_1 (user_id=? AND local_display_name=?)
|
||||
|
||||
Query:
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, address_welcome_message, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
SELECT user_contact_link_id, conn_req_contact, short_link_contact, short_link_data_set, business_address, auto_accept, auto_accept_incognito, auto_reply_msg_content
|
||||
FROM user_contact_links
|
||||
WHERE user_id = ? AND short_link_contact = ?
|
||||
Plan:
|
||||
|
@ -6038,6 +6053,10 @@ Query: UPDATE contacts SET local_display_name = ?, updated_at = ? WHERE user_id
|
|||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET request_shared_msg_id = ? WHERE contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET send_rcpts = NULL
|
||||
Plan:
|
||||
SCAN contacts
|
||||
|
|
|
@ -82,6 +82,7 @@ CREATE TABLE contacts(
|
|||
conn_full_link_to_connect BLOB,
|
||||
conn_short_link_to_connect BLOB,
|
||||
welcome_shared_msg_id BLOB,
|
||||
request_shared_msg_id BLOB,
|
||||
contact_request_id INTEGER REFERENCES contact_requests ON DELETE SET NULL,
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
|
@ -143,7 +144,8 @@ CREATE TABLE groups(
|
|||
conn_full_link_to_connect BLOB,
|
||||
conn_short_link_to_connect BLOB,
|
||||
conn_link_started_connection INTEGER NOT NULL DEFAULT 0,
|
||||
welcome_shared_msg_id BLOB, -- received
|
||||
welcome_shared_msg_id BLOB,
|
||||
request_shared_msg_id BLOB, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
|
@ -336,7 +338,6 @@ CREATE TABLE user_contact_links(
|
|||
business_address INTEGER DEFAULT 0,
|
||||
short_link_contact BLOB,
|
||||
short_link_data_set INTEGER NOT NULL DEFAULT 0,
|
||||
address_welcome_message TEXT,
|
||||
UNIQUE(user_id, local_display_name)
|
||||
);
|
||||
CREATE TABLE contact_requests(
|
||||
|
|
|
@ -431,7 +431,7 @@ deleteUnusedIncognitoProfileById_ db User {userId} profileId =
|
|||
|]
|
||||
(userId, profileId, userId, profileId, userId, profileId)
|
||||
|
||||
type PreparedContactRow = (Maybe AConnectionRequestUri, Maybe AConnShortLink, Maybe SharedMsgId)
|
||||
type PreparedContactRow = (Maybe AConnectionRequestUri, Maybe AConnShortLink, Maybe SharedMsgId, Maybe SharedMsgId)
|
||||
|
||||
type ContactRow' = (ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, Maybe ConnLinkContact, LocalAlias, BoolInt, ContactStatus) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime) :. PreparedContactRow :. (Maybe Int64, Maybe GroupMemberId, BoolInt, Maybe UIThemeEntityOverrides, BoolInt, Maybe CustomData, Maybe Int64)
|
||||
|
||||
|
@ -448,8 +448,9 @@ toContact vr user chatTags ((Only contactId :. (profileId, localDisplayName, via
|
|||
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, preparedContact, contactRequestId, contactGroupMemberId, contactGrpInvSent, chatTags, chatItemTTL, uiThemes, chatDeleted, customData}
|
||||
|
||||
toPreparedContact :: PreparedContactRow -> Maybe PreparedContact
|
||||
toPreparedContact (connFullLink, connShortLink, welcomeSharedMsgId) =
|
||||
(\cl@(ACCL m _) -> PreparedContact cl (connMode m) welcomeSharedMsgId) <$> toACreatedConnLink_ connFullLink connShortLink
|
||||
toPreparedContact (connFullLink, connShortLink, welcomeSharedMsgId, requestSharedMsgId) =
|
||||
(\cl@(ACCL m _) -> PreparedContact {connLinkToConnect = cl, uiConnLinkType = connMode m, welcomeSharedMsgId, requestSharedMsgId})
|
||||
<$> toACreatedConnLink_ connFullLink connShortLink
|
||||
|
||||
toACreatedConnLink_ :: Maybe AConnectionRequestUri -> Maybe AConnShortLink -> Maybe ACreatedConnLink
|
||||
toACreatedConnLink_ Nothing _ = Nothing
|
||||
|
@ -604,7 +605,7 @@ safeDeleteLDN db User {userId} localDisplayName = do
|
|||
|]
|
||||
(userId, localDisplayName, userId)
|
||||
|
||||
type PreparedGroupRow = (Maybe ConnReqContact, Maybe ShortLinkContact, BoolInt, Maybe SharedMsgId)
|
||||
type PreparedGroupRow = (Maybe ConnReqContact, Maybe ShortLinkContact, BoolInt, Maybe SharedMsgId, Maybe SharedMsgId)
|
||||
|
||||
type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe MemberId)
|
||||
|
||||
|
@ -624,8 +625,8 @@ toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName,
|
|||
|
||||
toPreparedGroup :: PreparedGroupRow -> Maybe PreparedGroup
|
||||
toPreparedGroup = \case
|
||||
(Just fullLink, shortLink_, BI connLinkStartedConnection, welcomeSharedMsgId) ->
|
||||
Just PreparedGroup {connLinkToConnect = CCLink fullLink shortLink_, connLinkStartedConnection, welcomeSharedMsgId}
|
||||
(Just fullLink, shortLink_, BI connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId) ->
|
||||
Just PreparedGroup {connLinkToConnect = CCLink fullLink shortLink_, connLinkStartedConnection, welcomeSharedMsgId, requestSharedMsgId}
|
||||
_ -> Nothing
|
||||
|
||||
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
|
||||
|
@ -660,7 +661,7 @@ groupInfoQuery =
|
|||
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.conn_link_started_connection, g.welcome_shared_msg_id,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
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
|
||||
|
|
|
@ -207,7 +207,8 @@ contactRequestId' Contact {contactRequestId} = contactRequestId
|
|||
data PreparedContact = PreparedContact
|
||||
{ connLinkToConnect :: ACreatedConnLink,
|
||||
uiConnLinkType :: ConnectionMode,
|
||||
welcomeSharedMsgId :: Maybe SharedMsgId
|
||||
welcomeSharedMsgId :: Maybe SharedMsgId,
|
||||
requestSharedMsgId :: Maybe SharedMsgId
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
@ -404,8 +405,15 @@ data RequestEntity
|
|||
type RepeatRequest = Bool
|
||||
|
||||
data RequestStage
|
||||
= RSAcceptedRequest (Maybe UserContactRequest) RequestEntity -- Optional request is for legacy deleted requests
|
||||
| RSCurrentRequest UserContactRequest (Maybe RequestEntity) RepeatRequest -- Optional entity is for legacy requests without entity
|
||||
= RSAcceptedRequest
|
||||
{ acceptedRequest :: Maybe UserContactRequest, -- Request is optional to support deleted legacy requests
|
||||
requestEntity :: RequestEntity
|
||||
}
|
||||
| RSCurrentRequest
|
||||
{ previousRequest :: Maybe UserContactRequest,
|
||||
currentRequest :: UserContactRequest,
|
||||
requestEntity_ :: Maybe RequestEntity -- Entity is optional to support legacy requests without entity
|
||||
}
|
||||
|
||||
type UserName = Text
|
||||
|
||||
|
@ -488,7 +496,8 @@ instance ToField BusinessChatType where toField = toField . textEncode
|
|||
data PreparedGroup = PreparedGroup
|
||||
{ connLinkToConnect :: CreatedLinkContact,
|
||||
connLinkStartedConnection :: Bool,
|
||||
welcomeSharedMsgId :: Maybe SharedMsgId -- it is stored only for business chats, and only if welcome message is specified
|
||||
welcomeSharedMsgId :: Maybe SharedMsgId, -- it is stored only for business chats, and only if welcome message is specified
|
||||
requestSharedMsgId :: Maybe SharedMsgId
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
|
@ -715,18 +724,6 @@ instance ToField ImageData where toField (ImageData t) = toField t
|
|||
|
||||
deriving newtype instance FromField ImageData
|
||||
|
||||
data ContactShortLinkData = ContactShortLinkData
|
||||
{ profile :: Profile,
|
||||
message :: Maybe Text,
|
||||
business :: Bool
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data GroupShortLinkData = GroupShortLinkData
|
||||
{ groupProfile :: GroupProfile
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data CReqClientData = CRDataGroup {groupLinkId :: GroupLinkId}
|
||||
|
||||
newtype GroupLinkId = GroupLinkId {unGroupLinkId :: ByteString} -- used to identify invitation via group link
|
||||
|
@ -1998,10 +1995,6 @@ instance FromField MsgFilter where fromField = fromIntField_ msgFilterIntP
|
|||
|
||||
instance ToField MsgFilter where toField = toField . msgFilterInt
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''ContactShortLinkData)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''GroupShortLinkData)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''CReqClientData)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''MemberIdRole)
|
||||
|
|
|
@ -1084,7 +1084,7 @@ simplexChatContact' = \case
|
|||
|
||||
-- TODO [short links] show all settings
|
||||
viewAddressSettings :: AddressSettings -> [StyledString]
|
||||
viewAddressSettings AddressSettings {businessAddress, welcomeMessage = _, autoAccept, autoReply} = case autoAccept of
|
||||
viewAddressSettings AddressSettings {businessAddress, autoAccept, autoReply} = case autoAccept of
|
||||
Just AutoAccept {acceptIncognito} ->
|
||||
("auto_accept on" <> aaInfo)
|
||||
: maybe [] ((["auto reply:"] <>) . ttyMsgContent) autoReply
|
||||
|
|
|
@ -3662,8 +3662,9 @@ testShortLinkAddressChangeAutoReply =
|
|||
alice <# "bob> hello"
|
||||
alice <## "bob (Bob): accepting contact request..."
|
||||
alice <## "bob (Bob): you can send messages to contact"
|
||||
alice <# "@bob welcome!" -- auto reply
|
||||
bob <# "alice> welcome!"
|
||||
-- welcome messages, not sent as events
|
||||
-- alice <# "@bob welcome!"
|
||||
-- bob <# "alice> welcome!"
|
||||
concurrently_
|
||||
(bob <## "alice (Alice): contact is connected")
|
||||
(alice <## "bob (Bob): contact is connected")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue