mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-03-30 14:15:55 +00:00
core: fix retrying connection via contact card (preset contacts) (#6104)
* core: fix retrying connection via contact card (preset contacts) * ios * kotlin * banner
This commit is contained in:
@@ -208,8 +208,14 @@ struct ContactListNavLink: View {
|
||||
.tint(.red)
|
||||
}
|
||||
.confirmationDialog("Connect with \(contact.chatViewName)", isPresented: $showConnectContactViaAddressDialog, titleVisibility: .visible) {
|
||||
Button("Use current profile") { connectContactViaAddress_(contact, false) }
|
||||
Button("Use new incognito profile") { connectContactViaAddress_(contact, true) }
|
||||
if !contact.profileChangeProhibited {
|
||||
Button("Use current profile") { connectContactViaAddress_(contact, false) }
|
||||
Button("Use new incognito profile") { connectContactViaAddress_(contact, true) }
|
||||
} else if !contact.contactConnIncognito {
|
||||
Button("Use current profile") { connectContactViaAddress_(contact, false) }
|
||||
} else {
|
||||
Button("Use incognito profile") { connectContactViaAddress_(contact, true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,8 +178,8 @@
|
||||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a */; };
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
|
||||
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
|
||||
@@ -543,8 +543,8 @@
|
||||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a"; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a"; sourceTree = "<group>"; };
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
|
||||
@@ -704,8 +704,8 @@
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a in Frameworks */,
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -790,8 +790,8 @@
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */,
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */,
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.0.7-HtMnGcLT3joL6B8buibOdF.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.4.1.0-CLkstteZ5zsL7AgM2nJh38.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
|
||||
@@ -1793,7 +1793,7 @@ public struct Contact: Identifiable, Decodable, NamedChat, Hashable {
|
||||
}
|
||||
|
||||
public var isContactCard: Bool {
|
||||
activeConn == nil && profile.contactLink != nil && active && preparedContact == nil && contactRequestId == nil
|
||||
(activeConn == nil || activeConn?.connStatus == .prepared) && profile.contactLink != nil && active && preparedContact == nil && contactRequestId == nil
|
||||
}
|
||||
|
||||
public var contactConnIncognito: Bool {
|
||||
|
||||
@@ -1778,7 +1778,7 @@ data class Contact(
|
||||
}
|
||||
|
||||
val isContactCard: Boolean =
|
||||
activeConn == null && profile.contactLink != null && active && preparedContact == null && contactRequestId == null
|
||||
(activeConn == null || activeConn.connStatus == ConnStatus.Prepared) && profile.contactLink != null && active && preparedContact == null && contactRequestId == null
|
||||
|
||||
val contactConnIncognito =
|
||||
activeConn?.customUserProfileId != null
|
||||
|
||||
@@ -794,33 +794,49 @@ fun askCurrentOrIncognitoProfileConnectContactViaAddress(
|
||||
close: (() -> Unit)?,
|
||||
openChat: Boolean
|
||||
) {
|
||||
@Composable
|
||||
fun UseCurrentProfileButton() {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi {
|
||||
val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = false)
|
||||
if (ok && openChat) {
|
||||
close?.invoke()
|
||||
openDirectChat(rhId, contact.contactId)
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text(generalGetString(MR.strings.connect_use_current_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun UseIncognitoProfileButton(text: String) {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi {
|
||||
val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = true)
|
||||
if (ok && openChat) {
|
||||
close?.invoke()
|
||||
openDirectChat(rhId, contact.contactId)
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text(text, Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
AlertManager.privacySensitive.showAlertDialogButtonsColumn(
|
||||
title = String.format(generalGetString(MR.strings.connect_with_contact_name_question), contact.chatViewName),
|
||||
buttons = {
|
||||
Column {
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi {
|
||||
close?.invoke()
|
||||
val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = false)
|
||||
if (ok && openChat) {
|
||||
openDirectChat(rhId, contact.contactId)
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text(generalGetString(MR.strings.connect_use_current_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
withBGApi {
|
||||
close?.invoke()
|
||||
val ok = connectContactViaAddress(chatModel, rhId, contact.contactId, incognito = true)
|
||||
if (ok && openChat) {
|
||||
openDirectChat(rhId, contact.contactId)
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Text(generalGetString(MR.strings.connect_use_new_incognito_profile), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
|
||||
if (!contact.profileChangeProhibited) {
|
||||
UseCurrentProfileButton()
|
||||
UseIncognitoProfileButton(generalGetString(MR.strings.connect_use_new_incognito_profile))
|
||||
} else if (!contact.contactConnIncognito) {
|
||||
UseCurrentProfileButton()
|
||||
} else {
|
||||
UseIncognitoProfileButton(generalGetString(MR.strings.connect_use_incognito_profile))
|
||||
}
|
||||
SectionItemView({
|
||||
AlertManager.privacySensitive.hideAlert()
|
||||
|
||||
@@ -104,6 +104,9 @@ fun ContactPreviewView(
|
||||
modifier = Modifier
|
||||
.size(21.dp)
|
||||
)
|
||||
if (chat.chatInfo.incognito) {
|
||||
Spacer(Modifier.width(DEFAULT_SPACE_AFTER_ICON))
|
||||
}
|
||||
}
|
||||
|
||||
if (showDeletedChatIcon && chat.chatInfo.chatDeleted) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<string name="connect_via_group_link">Join group?</string>
|
||||
<string name="connect_use_current_profile">Use current profile</string>
|
||||
<string name="connect_use_new_incognito_profile">Use new incognito profile</string>
|
||||
<string name="connect_use_incognito_profile">Use incognito profile</string>
|
||||
<string name="profile_will_be_sent_to_contact_sending_link">Your profile will be sent to the contact that you received this link from.</string>
|
||||
<string name="you_will_join_group">You will connect to all group members.</string>
|
||||
<string name="connect_via_link_verb">Connect</string>
|
||||
|
||||
@@ -1909,14 +1909,18 @@ processChatCommand vr nm = \case
|
||||
Connect _ Nothing -> throwChatError CEInvalidConnReq
|
||||
APIConnectContactViaAddress userId incognito contactId -> withUserId userId $ \user -> do
|
||||
ct@Contact {activeConn, profile = LocalProfile {contactLink}} <- withFastStore $ \db -> getContact db vr user contactId
|
||||
when (isJust activeConn) $ throwCmdError "contact already has connection"
|
||||
ccLink <- case contactLink of
|
||||
Just (CLFull cReq) -> pure $ CCLink cReq Nothing
|
||||
Just (CLShort sLnk) -> do
|
||||
(cReq, _cData) <- getShortLinkConnReq user sLnk
|
||||
pure $ CCLink cReq $ Just sLnk
|
||||
Nothing -> throwCmdError "no address in contact profile"
|
||||
connectContactViaAddress user incognito ct ccLink
|
||||
connectContactViaAddress user incognito ct ccLink `catchChatError` \e -> do
|
||||
-- get updated contact, in case connection was started - in UI it would lock ability to change incognito choice
|
||||
-- on next connection attempt, in case server received request while client got network error
|
||||
ct' <- withFastStore $ \db -> getContact db vr user contactId
|
||||
toView $ CEvtChatInfoUpdated user (AChatInfo SCTDirect $ DirectChat ct')
|
||||
throwError e
|
||||
ConnectSimplex incognito -> withUser $ \user -> do
|
||||
plan <- contactRequestPlan user adminContactReq Nothing `catchChatError` const (pure $ CPContactAddress (CAPOk Nothing))
|
||||
connectWithPlan user incognito (ACCL SCMContact (CCLink adminContactReq Nothing)) plan
|
||||
@@ -3021,7 +3025,6 @@ processChatCommand vr nm = \case
|
||||
let incognitoProfile = fromLocalProfile <$> localIncognitoProfile
|
||||
conn' <- joinContact user conn cReq incognitoProfile xContactId welcomeSharedMsgId msg_ inGroup PQSupportOn
|
||||
pure $ CVRSentInvitation conn' incognitoProfile
|
||||
mkXContactId = maybe (XContactId <$> drgRandomBytes 16) pure
|
||||
connect' groupLinkId cReqHash xContactId_ = do
|
||||
let inGroup = isJust groupLinkId
|
||||
pqSup = if inGroup then PQSupportOff else PQSupportOn
|
||||
@@ -3035,19 +3038,31 @@ processChatCommand vr nm = \case
|
||||
conn' <- joinContact user conn cReq incognitoProfile xContactId welcomeSharedMsgId msg_ inGroup pqSup
|
||||
pure $ CVRSentInvitation conn' incognitoProfile
|
||||
connectContactViaAddress :: User -> IncognitoEnabled -> Contact -> CreatedLinkContact -> CM ChatResponse
|
||||
connectContactViaAddress user@User {userId} incognito ct@Contact {contactId} (CCLink cReq shortLink) =
|
||||
withInvitationLock "connectContactViaAddress" (strEncode cReq) $ do
|
||||
newXContactId <- XContactId <$> drgRandomBytes 16
|
||||
let pqSup = PQSupportOn
|
||||
(connId, chatV) <- prepareContact user cReq pqSup
|
||||
let cReqHash = ConnReqUriHash . C.sha256Hash $ strEncode cReq
|
||||
-- [incognito] generate profile to send
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId (Just $ PCEContact ct) cReqHash shortLink newXContactId incognitoProfile Nothing subMode chatV pqSup
|
||||
void $ joinContact user conn cReq incognitoProfile newXContactId Nothing Nothing False pqSup
|
||||
ct' <- withStore $ \db -> getContact db vr user contactId
|
||||
pure $ CRSentInvitationToContact user ct' incognitoProfile
|
||||
connectContactViaAddress user@User {userId} incognito ct@Contact {contactId, activeConn} (CCLink cReq shortLink) =
|
||||
withInvitationLock "connectContactViaAddress" (strEncode cReq) $
|
||||
case activeConn of
|
||||
Nothing -> do
|
||||
let pqSup = PQSupportOn
|
||||
(connId, chatV) <- prepareContact user cReq pqSup
|
||||
newXContactId <- XContactId <$> drgRandomBytes 16
|
||||
-- [incognito] generate profile to send
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let cReqHash = ConnReqUriHash . C.sha256Hash $ strEncode cReq
|
||||
conn <- withFastStore' $ \db -> createConnReqConnection db userId connId (Just $ PCEContact ct) cReqHash shortLink newXContactId incognitoProfile Nothing subMode chatV pqSup
|
||||
void $ joinContact user conn cReq incognitoProfile newXContactId Nothing Nothing False pqSup
|
||||
ct' <- withStore $ \db -> getContact db vr user contactId
|
||||
pure $ CRSentInvitationToContact user ct' incognitoProfile
|
||||
Just conn@Connection {connStatus, xContactId = xContactId_, customUserProfileId} -> case connStatus of
|
||||
ConnPrepared -> do
|
||||
when (incognito /= isJust customUserProfileId) $ throwCmdError "incognito mode is different from prepared connection"
|
||||
xContactId <- mkXContactId xContactId_
|
||||
localIncognitoProfile <- forM customUserProfileId $ \pId -> withFastStore $ \db -> getProfileById db userId pId
|
||||
let incognitoProfile = fromLocalProfile <$> localIncognitoProfile
|
||||
void $ joinContact user conn cReq incognitoProfile xContactId Nothing Nothing False PQSupportOn
|
||||
ct' <- withStore $ \db -> getContact db vr user contactId
|
||||
pure $ CRSentInvitationToContact user ct' incognitoProfile
|
||||
_ -> throwCmdError "contact already has connection"
|
||||
prepareContact :: User -> ConnReqContact -> PQSupport -> CM (ConnId, VersionChat)
|
||||
prepareContact user cReq pqSup = do
|
||||
-- 0) toggle disabled - PQSupportOff
|
||||
@@ -3059,6 +3074,8 @@ processChatCommand vr nm = \case
|
||||
let chatV = agentToChatVersion agentV
|
||||
connId <- withAgent $ \a -> prepareConnectionToJoin a (aUserId user) True cReq pqSup
|
||||
pure (connId, chatV)
|
||||
mkXContactId :: Maybe XContactId -> CM XContactId
|
||||
mkXContactId = maybe (XContactId <$> drgRandomBytes 16) pure
|
||||
joinContact :: User -> Connection -> ConnReqContact -> Maybe Profile -> XContactId -> Maybe SharedMsgId -> Maybe (SharedMsgId, MsgContent) -> Bool -> PQSupport -> CM Connection
|
||||
joinContact user conn@Connection {connChatVersion = chatV} cReq incognitoProfile xContactId welcomeSharedMsgId msg_ inGroup pqSup = do
|
||||
let profileToSend =
|
||||
|
||||
@@ -546,6 +546,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
(gInfo, host) <- withStore $ \db -> do
|
||||
liftIO $ deleteContactCardKeepConn db connId ct
|
||||
createGroupInvitedViaLink db vr user conn'' glInv
|
||||
void $ createChatItem user (CDGroupSnd gInfo Nothing) False CIChatBanner Nothing (Just epochStart)
|
||||
-- [incognito] send saved profile
|
||||
incognitoProfile <- forM customUserProfileId $ \pId -> withStore (\db -> getProfileById db userId pId)
|
||||
let profileToSend = userProfileInGroup user (fromLocalProfile <$> incognitoProfile)
|
||||
|
||||
Reference in New Issue
Block a user