core, ui: create all links with short links, config parameter to use large link data, use short link as address in user profile (#5991)

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
This commit is contained in:
Evgeny
2025-06-17 12:34:51 +01:00
committed by spaced4ndy
parent c08a3e7c4a
commit e3e9ae2ffd
46 changed files with 413 additions and 323 deletions
+4 -4
View File
@@ -200,14 +200,14 @@ toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just member
Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences) :. (createdAt, updatedAt) :. (supportChatTs, supportChatUnread, supportChatUnanswered, supportChatMentions, supportChatLastMsgFromMemberTs))
toMaybeGroupMember _ _ = Nothing
createGroupLink :: DB.Connection -> User -> GroupInfo -> ConnId -> CreatedLinkContact -> GroupLinkId -> GroupMemberRole -> Bool -> SubscriptionMode -> ExceptT StoreError IO GroupLink
createGroupLink db user@User {userId} groupInfo@GroupInfo {groupId, localDisplayName} agentConnId (CCLink cReq shortLink) groupLinkId memberRole shortLinkDataSet subMode = do
createGroupLink :: DB.Connection -> User -> GroupInfo -> ConnId -> CreatedLinkContact -> GroupLinkId -> GroupMemberRole -> SubscriptionMode -> ExceptT StoreError IO GroupLink
createGroupLink db user@User {userId} groupInfo@GroupInfo {groupId, localDisplayName} agentConnId (CCLink cReq shortLink) groupLinkId memberRole subMode = do
checkConstraint (SEDuplicateGroupLink groupInfo) . liftIO $ do
currentTs <- getCurrentTime
DB.execute
db
"INSERT INTO user_contact_links (user_id, group_id, group_link_id, local_display_name, conn_req_contact, short_link_contact, short_link_data_set, group_link_member_role, auto_accept, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?)"
((userId, groupId, groupLinkId, "group_link_" <> localDisplayName, cReq, shortLink, BI shortLinkDataSet) :. (memberRole, BI True, currentTs, currentTs))
((userId, groupId, groupLinkId, "group_link_" <> localDisplayName, cReq, shortLink, BI (isJust shortLink)) :. (memberRole, BI True, currentTs, currentTs))
userContactLinkId <- insertedRowId db
void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId ConnNew initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode PQSupportOff
getGroupLink db user groupInfo
@@ -2032,7 +2032,7 @@ getGroupInfoViaUserShortLink db vr user@User {userId} shortLink = fmap eitherToM
(cReq, groupId) <- ExceptT getConnReqGroup
(cReq,) <$> getGroupInfo db vr user groupId
where
getConnReqGroup =
getConnReqGroup =
firstRow' toConnReqGroupId (SEInternalError "group link not found") $
DB.query
db
+26 -9
View File
@@ -53,6 +53,7 @@ module Simplex.Chat.Store.Profiles
getUserContactLinkViaShortLink,
setUserContactLinkShortLink,
getContactWithoutConnViaAddress,
getContactWithoutConnViaShortAddress,
updateUserAddressAutoAccept,
getProtocolServers,
insertProtocolServer,
@@ -75,6 +76,7 @@ module Simplex.Chat.Store.Profiles
updateCommandStatus,
getCommandDataByCorrId,
setUserUIThemes,
profileContactLink,
)
where
@@ -86,7 +88,7 @@ import Data.Functor (($>))
import Data.Int (Int64)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as L
import Data.Maybe (catMaybes, fromMaybe)
import Data.Maybe (catMaybes, fromMaybe, isJust)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (decodeLatin1, encodeUtf8)
@@ -332,11 +334,7 @@ setUserProfileContactLink db user@User {userId, profile = p@LocalProfile {profil
(contactLink, ts, userId, profileId)
pure (user :: User) {profile = p {contactLink}}
where
-- TODO [short links] this should be replaced with short links once they are supported by all clients.
-- Or, maybe, we want to allow both, when both are optional.
contactLink = case ucl_ of
Just UserContactLink {connLinkContact = CCLink cReq _} -> Just $ CLFull cReq
_ -> Nothing
contactLink = profileContactLink <$> ucl_
-- only used in tests
getUserContactProfiles :: DB.Connection -> User -> IO [Profile]
@@ -354,14 +352,14 @@ getUserContactProfiles db User {userId} =
toContactProfile :: (ContactName, Text, Maybe ImageData, Maybe ConnLinkContact, Maybe Preferences) -> Profile
toContactProfile (displayName, fullName, image, contactLink, preferences) = Profile {displayName, fullName, image, contactLink, preferences}
createUserContactLink :: DB.Connection -> User -> ConnId -> CreatedLinkContact -> Bool -> SubscriptionMode -> ExceptT StoreError IO ()
createUserContactLink db User {userId} agentConnId (CCLink cReq shortLink) shortLinkDataSet subMode =
createUserContactLink :: DB.Connection -> User -> ConnId -> CreatedLinkContact -> SubscriptionMode -> ExceptT StoreError IO ()
createUserContactLink db User {userId} agentConnId (CCLink cReq shortLink) subMode =
checkConstraint SEDuplicateContactLink . liftIO $ do
currentTs <- getCurrentTime
DB.execute
db
"INSERT INTO user_contact_links (user_id, conn_req_contact, short_link_contact, short_link_data_set, created_at, updated_at) VALUES (?,?,?,?,?,?)"
(userId, cReq, shortLink, BI shortLinkDataSet, currentTs, currentTs)
(userId, cReq, shortLink, BI (isJust shortLink), currentTs, currentTs)
userContactLinkId <- insertedRowId db
void $ createConnection_ db userId ConnUserContact (Just userContactLinkId) agentConnId ConnNew initialChatVersion chatInitialVRange Nothing Nothing Nothing 0 currentTs subMode CR.PQSupportOff
@@ -457,6 +455,9 @@ data UserContactLink = UserContactLink
}
deriving (Show)
profileContactLink :: UserContactLink -> ConnLinkContact
profileContactLink UserContactLink {connLinkContact = CCLink cReq sLink} = maybe (CLFull cReq) CLShort sLink
data GroupLinkInfo = GroupLinkInfo
{ groupId :: GroupId,
memberRole :: GroupMemberRole
@@ -559,6 +560,22 @@ getContactWithoutConnViaAddress db vr user@User {userId} (cReqSchema1, cReqSchem
(userId, cReqSchema1, cReqSchema2)
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getContact db vr user) ctId_
getContactWithoutConnViaShortAddress :: DB.Connection -> VersionRangeChat -> User -> ShortLinkContact -> IO (Maybe Contact)
getContactWithoutConnViaShortAddress db vr user@User {userId} shortLink = do
ctId_ <-
maybeFirstRow fromOnly $
DB.query
db
[sql|
SELECT ct.contact_id
FROM contacts ct
JOIN contact_profiles cp ON cp.contact_profile_id = ct.contact_profile_id
LEFT JOIN connections c ON c.contact_id = ct.contact_id
WHERE cp.user_id = ? AND cp.contact_link = ? AND c.connection_id IS NULL
|]
(userId, shortLink)
maybe (pure Nothing) (fmap eitherToMaybe . runExceptT . getContact db vr user) ctId_
updateUserAddressAutoAccept :: DB.Connection -> Int64 -> Maybe AutoAccept -> IO ()
updateUserAddressAutoAccept db userContactLinkId autoAccept =
DB.execute
@@ -1178,6 +1178,18 @@ Plan:
SEARCH g USING INTEGER PRIMARY KEY (rowid=?)
SEARCH m USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
Query:
SELECT ct.contact_id
FROM contacts ct
JOIN contact_profiles cp ON cp.contact_profile_id = ct.contact_profile_id
LEFT JOIN connections c ON c.contact_id = ct.contact_id
WHERE cp.user_id = ? AND cp.contact_link = ? AND c.connection_id IS NULL
Plan:
SEARCH cp USING COVERING INDEX idx_contact_profiles_contact_link (user_id=? AND contact_link=?)
SEARCH ct USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
SEARCH c USING COVERING INDEX idx_connections_contact_id (contact_id=?) LEFT-JOIN
Query:
SELECT ct.contact_id
FROM contacts ct