feat(@desktop/chat): Displaying new type of chat message - bridge message

Show discord user as a message sender.
Show discord avatar next to user name.
Show "Bridged from Discord" label.
Open adjusted profile context menu.

Issue #13098
This commit is contained in:
Michal Iskierko 2024-01-05 16:34:20 +01:00 committed by Michał Iskierko
parent eee8ec8e32
commit 0a18dda176
19 changed files with 137 additions and 22 deletions

View File

@ -147,6 +147,7 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, communityId: st
imagesAlbum,
albumMessageIds,
message.albumImagesCount,
message.bridgeMessage,
))
method convertToItems*(

View File

@ -206,6 +206,7 @@ proc createMessageItemsFromMessageDtos(self: Module, messages: seq[MessageDto],
if (len(message.albumId) == 0): @[] else: @[message.image],
if (len(message.albumId) == 0): @[] else: @[message.id],
message.albumImagesCount,
message.bridgeMessage,
)
self.updateLinkPreviewsContacts(item, requestFromMailserver = item.seen)
@ -284,6 +285,7 @@ proc createFetchMoreMessagesItem(self: Module): Item =
albumMessageImages = @[],
albumMessageIds = @[],
albumImagesCount = 0,
BridgeMessage(),
)
proc createChatIdentifierItem(self: Module): Item =
@ -349,6 +351,7 @@ proc createChatIdentifierItem(self: Module): Item =
albumMessageImages = @[],
albumMessageIds = @[],
albumImagesCount = 0,
bridgeMessage = BridgeMessage(),
)
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module) =

View File

@ -228,6 +228,7 @@ proc buildPinnedMessageItem(self: Module, message: MessageDto, actionInitiatedBy
if (len(message.albumId) == 0): @[] else: @[message.image],
if (len(message.albumId) == 0): @[] else: @[message.id],
message.albumImagesCount,
message.bridgeMessage,
)
item.pinned = true
item.pinnedBy = actionInitiatedBy

View File

@ -70,6 +70,7 @@ type
albumMessageImages: seq[string]
albumMessageIds: seq[string]
albumImagesCount: int
bridgeName: string
proc initItem*(
id,
@ -121,6 +122,7 @@ proc initItem*(
albumMessageImages: seq[string],
albumMessageIds: seq[string],
albumImagesCount: int,
bridgeMessage: BridgeMessage,
): Item =
result = Item()
result.id = id
@ -208,6 +210,13 @@ proc initItem*(
if attachment.contentType.contains("image"):
result.messageAttachments.add(attachment.localUrl)
if contentType == ContentType.BridgeMessage:
result.messageText = bridgeMessage.content
result.unparsedText = bridgeMessage.content
result.senderDisplayName = bridgeMessage.userName
result.senderIcon = bridgeMessage.userAvatar
result.bridgeName = bridgeMessage.bridgeName
proc initNewMessagesMarkerItem*(clock, timestamp: int64): Item =
return initItem(
id = "",
@ -259,6 +268,7 @@ proc initNewMessagesMarkerItem*(clock, timestamp: int64): Item =
albumMessageImages = @[],
albumMessageIds = @[],
albumImagesCount = 0,
bridgeMessage = BridgeMessage(),
)
proc `$`*(self: Item): string =
@ -404,6 +414,9 @@ proc `albumMessageIds=`*(self: Item, value: seq[string]) {.inline.} =
proc albumImagesCount*(self: Item): int {.inline.} =
self.albumImagesCount
proc bridgeName*(self: Item): string {.inline.} =
self.bridgeName
proc messageContainsMentions*(self: Item): bool {.inline.} =
self.messageContainsMentions
@ -542,6 +555,7 @@ proc toJsonNode*(self: Item): JsonNode =
"albumMessageImages": self.albumMessageImages,
"albumMessageIds": self.albumMessageIds,
"albumImagesCount": self.albumImagesCount,
"bridgeName": self.bridgeName
}
proc editMode*(self: Item): bool {.inline.} =

View File

@ -73,6 +73,7 @@ type
QuotedMessageAlbumImagesCount
AlbumMessageImages
AlbumImagesCount
BridgeName
QtObject:
type
@ -178,6 +179,7 @@ QtObject:
ModelRole.QuotedMessageAlbumImagesCount.int: "quotedMessageAlbumImagesCount",
ModelRole.AlbumMessageImages.int: "albumMessageImages",
ModelRole.AlbumImagesCount.int: "albumImagesCount",
ModelRole.BridgeName.int: "bridgeName",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -350,6 +352,8 @@ QtObject:
result = newQVariant(item.albumMessageImages.join(" "))
of ModelRole.AlbumImagesCount:
result = newQVariant(item.albumImagesCount)
of ModelRole.BridgeName:
result = newQVariant(item.bridgeName)
proc updateItemAtIndex(self: Model, index: int) =
let ind = self.createIndex(index, 0, nil)

View File

@ -22,6 +22,7 @@ type
SystemMessageMutualEventSent = 15
SystemMessageMutualEventAccepted = 16
SystemMessageMutualEventRemoved = 17
BridgeMessage = 18
proc toContentType*(value: int): ContentType =
try:

View File

@ -56,6 +56,14 @@ type DiscordMessage* = object
author*: DiscordMessageAuthor
attachments*: seq[DiscordMessageAttachment]
type BridgeMessage* = object
bridgeName*: string
userName*: string
userAvatar*: string
userId*: string
content*: string
messageId*: string
parentMessageId*: string
type QuotedMessage* = object
`from`*: string
@ -95,6 +103,7 @@ type MessageDto* = object
outgoingStatus*: string
quotedMessage*: QuotedMessage
discordMessage*: DiscordMessage
bridgeMessage*: BridgeMessage
rtl*: bool
parsedText*: seq[ParsedText]
lineCount*: int
@ -170,6 +179,16 @@ proc toDiscordMessage*(jsonObj: JsonNode): DiscordMessage =
for attachment in attachmentsArr:
result.attachments.add(toDiscordMessageAttachment(attachment))
proc toBridgeMessage*(jsonObj: JsonNode): BridgeMessage =
result = BridgeMessage()
discard jsonObj.getProp("userName", result.userName)
discard jsonObj.getProp("bridgeName", result.bridgeName)
discard jsonObj.getProp("userAvatar", result.userAvatar)
discard jsonObj.getProp("userID", result.userId)
discard jsonObj.getProp("content", result.content)
discard jsonObj.getProp("messageID", result.messageId)
discard jsonObj.getProp("parentMessageID", result.parentMessageId)
proc toQuotedMessage*(jsonObj: JsonNode): QuotedMessage =
result = QuotedMessage()
var contentType: int
@ -263,6 +282,10 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto =
if(jsonObj.getProp("discordMessage", discordMessageObj)):
result.discordMessage = toDiscordMessage(discordMessageObj)
var bridgeMessageObj: JsonNode
if(jsonObj.getProp("bridgeMessage", bridgeMessageObj)):
result.bridgeMessage = toBridgeMessage(bridgeMessageObj)
var stickerObj: JsonNode
if(jsonObj.getProp("sticker", stickerObj)):
result.sticker = toSticker(stickerObj)

View File

@ -59,6 +59,7 @@ proc createTestMessageItem(id: string, clock: int64): Item =
albumMessageImages = @[],
albumMessageIds = @[],
albumImagesCount = 0,
bridgeMessage = BridgeMessage(),
)
let message0_chatIdentifier = createTestMessageItem("chat-identifier", -2)

View File

@ -25,7 +25,8 @@ Control {
SystemMessagePinnedMessage = 14,
SystemMessageMutualEventSent = 15,
SystemMessageMutualEventAccepted = 16,
SystemMessageMutualEventRemoved = 17
SystemMessageMutualEventRemoved = 17,
BridgeMessage = 18
}
property list<Item> quickActions
@ -221,6 +222,8 @@ Control {
name: root.messageDetails.sender.displayName
asset: root.messageDetails.sender.profileImage.assetSettings
ringSettings: root.messageDetails.sender.profileImage.ringSettings
bridgeBadge.visible: root.messageDetails.contentType === StatusMessage.ContentType.BridgeMessage
bridgeBadge.image.source: root.messageDetails.sender.badgeImage
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
@ -267,7 +270,8 @@ Control {
&& ((root.messageDetails.contentType === StatusMessage.ContentType.Text) ||
(root.messageDetails.contentType === StatusMessage.ContentType.Emoji) ||
(root.messageDetails.contentType === StatusMessage.ContentType.DiscordMessage) ||
(root.messageDetails.contentType === StatusMessage.ContentType.Invitation)))
(root.messageDetails.contentType === StatusMessage.ContentType.Invitation) ||
(root.messageDetails.contentType === StatusMessage.ContentType.BridgeMessage)))
visible: active
sourceComponent: StatusTextMessage {
objectName: "StatusMessage_textMessage"

View File

@ -12,6 +12,8 @@ QtObject {
property bool isContact: false
property int trustIndicator: StatusContactVerificationIcons.TrustedType.None
property string badgeImage: ""
property StatusProfileImageSettings profileImage: StatusProfileImageSettings {
pubkey: root.id
showRing: !root.isEnsVerified

View File

@ -12,6 +12,8 @@ Loader {
// Badge color properties must be set if badgeItem.visible = true
property alias badge: statusBadge
property alias bridgeBadge: bridgeBadge
property StatusAssetSettings asset: StatusAssetSettings {
width: 40
height: 40
@ -33,7 +35,7 @@ Loader {
property bool loading: false
property bool hoverEnabled: false
readonly property bool hovered: (sourceComponent == roundedIcon && item) ?
readonly property bool hovered: (sourceComponent === roundedIcon && item) ?
item.hovered : false
signal clicked(var mouse)
@ -140,6 +142,20 @@ Loader {
z: root.dZ
}
StatusRoundedImage {
id: bridgeBadge
visible: false
anchors.bottom: root.bottom
anchors.right: root.right
anchors.rightMargin: -border.width
anchors.bottomMargin: -border.width
implicitHeight: 20
implicitWidth: 20
border.width: 3
border.color: Theme.palette.statusBadge.foregroundColor
z: root.dZ
}
Component {
id: loadingComp
LoadingComponent {

View File

@ -111,6 +111,7 @@ StatusDialog {
quotedMessageAuthorDetailsEnsVerified: model.quotedMessageAuthorEnsVerified
quotedMessageAuthorDetailsIsContact: model.quotedMessageAuthorIsContact
quotedMessageAuthorDetailsColorHash: model.quotedMessageAuthorColorHash
bridgeName: model.bridgeName
// This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once.

View File

@ -325,6 +325,7 @@ Item {
quotedMessageAuthorDetailsColorHash: model.quotedMessageAuthorColorHash
quotedMessageAlbumMessageImages: model.quotedMessageAlbumMessageImages.split(" ")
quotedMessageAlbumImagesCount: model.quotedMessageAlbumImagesCount
bridgeName: model.bridgeName
gapFrom: model.gapFrom
gapTo: model.gapTo

View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" rx="8" fill="#5865F2"/>
<g clip-path="url(#clip0_50821_248568)">
<path d="M11.471 4.66999C10.814 4.35248 10.1204 4.12724 9.40789 4C9.31039 4.18397 9.22218 4.37324 9.14361 4.56704C8.3847 4.44633 7.61293 4.44633 6.85401 4.56704C6.7754 4.37326 6.68719 4.18399 6.58974 4C5.87681 4.12831 5.18275 4.35409 4.52508 4.67165C3.21944 6.71067 2.8655 8.69904 3.04247 10.6592C3.80708 11.2555 4.66291 11.709 5.57275 12C5.77761 11.7092 5.9589 11.4006 6.11467 11.0776C5.8188 10.961 5.53324 10.8171 5.26128 10.6476C5.33285 10.5928 5.40285 10.5363 5.4705 10.4815C6.26183 10.8743 7.12552 11.078 7.99999 11.078C8.87446 11.078 9.73816 10.8743 10.5295 10.4815C10.5979 10.5405 10.6679 10.5969 10.7387 10.6476C10.4662 10.8174 10.1801 10.9615 9.88374 11.0785C10.0393 11.4013 10.2206 11.7096 10.4257 12C11.3363 11.7102 12.1928 11.2569 12.9575 10.66C13.1652 8.38688 12.6028 6.41677 11.471 4.66999ZM6.33883 9.45372C5.84567 9.45372 5.43825 8.98132 5.43825 8.40017C5.43825 7.81901 5.83152 7.34247 6.33726 7.34247C6.843 7.34247 7.24728 7.81901 7.23863 8.40017C7.22997 8.98132 6.84143 9.45372 6.33883 9.45372ZM9.66115 9.45372C9.16721 9.45372 8.76136 8.98132 8.76136 8.40017C8.76136 7.81901 9.15462 7.34247 9.66115 7.34247C10.1677 7.34247 10.5688 7.81901 10.5602 8.40017C10.5515 8.98132 10.1637 9.45372 9.66115 9.45372Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_50821_248568">
<rect width="10" height="8" fill="white" transform="translate(3 4)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -40,6 +40,7 @@ Item {
property bool editButtonVisible: displayNamePlusIconsVisible
property bool loading: false
readonly property bool compact: root.imageSize === ProfileHeader.ImageSize.Compact
property bool isBridgedAccount: false
signal clicked()
signal editClicked()
@ -119,6 +120,7 @@ Item {
imageHeight: imageWidth
ensVerified: root.userIsEnsVerified
loading: root.loading
isBridgedAccount: root.isBridgedAccount
}
StatusRoundButton {
@ -206,7 +208,7 @@ Item {
StatusContactVerificationIcons {
Layout.alignment: Qt.AlignVCenter
visible: !root.isCurrentUser
visible: !root.isCurrentUser && !root.isBridgedAccount
isContact: root.isContact
trustIndicator: root.trustStatus
}
@ -235,7 +237,7 @@ Item {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
visible: root.pubkeyVisible
text: Utils.getElidedCompressedPk(pubkey)
text: root.isBridgedAccount ? qsTr("Bridged from Discord") : Utils.getElidedCompressedPk(pubkey)
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 13
color: Style.current.secondaryText
@ -243,7 +245,7 @@ Item {
RowLayout {
Layout.alignment: Qt.AlignHCenter
visible: root.pubkeyVisibleWithCopy
visible: root.pubkeyVisibleWithCopy && !root.isBridgedAccount
StyledText {
id: txtChatKey
text: qsTr("Chatkey:%1...").arg(pubkey.substring(0, 32))
@ -265,7 +267,7 @@ Item {
EmojiHash {
id: emojiHash
Layout.alignment: Qt.AlignHCenter
visible: root.emojiHashVisible
visible: root.emojiHashVisible && !root.isBridgedAccount
compact: root.compact
publicKey: root.pubkey
}

View File

@ -16,11 +16,12 @@ Loader {
property string name
property string pubkey
property string image
property bool showRing: !ensVerified
property bool showRing: !ensVerified && !root.isBridgedAccount
property bool interactive: true
property bool disabled: false
property bool ensVerified: false
property bool loading: false
property bool isBridgedAccount: false
property int colorId: Utils.colorIdForPubkey(pubkey)
property var colorHash: Utils.getColorHashAsJson(pubkey, ensVerified)
@ -41,6 +42,8 @@ Loader {
ringSpecModel: root.showRing ? root.colorHash : undefined
}
loading: root.loading
bridgeBadge.visible: root.isBridgedAccount
bridgeBadge.image.source: Style.svg("discord-bridge")
Loader {
anchors.fill: parent

View File

@ -128,13 +128,15 @@ Loader {
property bool stickersLoaded: false
property string sticker
property int stickerPack: -1
property string bridgeName: ""
property bool isEmoji: messageContentType === Constants.messageContentType.emojiType
property bool isImage: messageContentType === Constants.messageContentType.imageType || (isDiscordMessage && messageImage != "")
property bool isAudio: messageContentType === Constants.messageContentType.audioType
property bool isSticker: messageContentType === Constants.messageContentType.stickerType
property bool isDiscordMessage: messageContentType === Constants.messageContentType.discordMessageType
property bool isText: messageContentType === Constants.messageContentType.messageType || messageContentType === Constants.messageContentType.contactRequestType || isDiscordMessage
property bool isBridgeMessage: messageContentType === Constants.messageContentType.bridgeMessageType
property bool isText: messageContentType === Constants.messageContentType.messageType || messageContentType === Constants.messageContentType.contactRequestType || isDiscordMessage || isBridgeMessage
property bool isMessage: isEmoji || isImage || isSticker || isText || isAudio
|| messageContentType === Constants.messageContentType.communityInviteType || messageContentType === Constants.messageContentType.transactionType
@ -152,6 +154,7 @@ Loader {
selectedUserPublicKey: isReply ? quotedMessageFrom : root.senderId,
selectedUserDisplayName: isReply ? quotedMessageAuthorDetailsDisplayName : root.senderDisplayName,
selectedUserIcon: isReply ? quotedMessageAuthorDetailsThumbnailImage : root.senderIcon,
isBridgedAccount: root.isBridgeMessage
}
Global.openMenu(profileContextMenuComponent, sender, params)
@ -239,6 +242,7 @@ Loader {
case Constants.messageContentType.communityInviteType:
case Constants.messageContentType.discordMessageType:
case Constants.messageContentType.contactRequestType:
case Constants.messageContentType.bridgeMessageType:
return messageComponent
case Constants.messageContentType.unknownContentType:
// NOTE: We could display smth like "unknown message type, please upgrade Status to see it".
@ -296,6 +300,8 @@ Loader {
return StatusMessage.ContentType.Invitation;
case Constants.messageContentType.discordMessageType:
return StatusMessage.ContentType.DiscordMessage;
case Constants.messageContentType.bridgeMessageType:
return StatusMessage.ContentType.BridgeMessage;
case Constants.messageContentType.systemMessagePinnedMessage:
return StatusMessage.ContentType.SystemMessagePinnedMessage;
case Constants.messageContentType.systemMessageMutualEventSent:
@ -333,6 +339,11 @@ Loader {
break;
}
}
function correctBridgeNameCapitalization(bridgeName) {
return (bridgeName === "discord") ? "Discord" : bridgeName
}
}
Component {
@ -724,7 +735,14 @@ Loader {
messageDetails: StatusMessageDetails {
contentType: delegate.contentType
messageOriginInfo: isDiscordMessage ? qsTr("Imported from discord") : ""
messageOriginInfo: {
if (isDiscordMessage) {
return qsTr("Imported from discord")
} else if (isBridgeMessage) {
return qsTr("Bridged from %1").arg(d.correctBridgeNameCapitalization(root.bridgeName))
}
return ""
}
messageText: root.messageText
messageContent: {
switch (delegate.contentType)
@ -747,9 +765,9 @@ Loader {
sender.id: root.senderIsEnsVerified ? "" : Utils.getCompressedPk(root.senderId)
sender.displayName: root.senderDisplayName
sender.secondaryName: root.senderOptionalName
sender.isEnsVerified: root.senderIsEnsVerified
sender.isContact: root.senderIsAdded
sender.trustIndicator: root.senderTrustStatus
sender.isEnsVerified: root.isBridgeMessage ? false : root.senderIsEnsVerified
sender.isContact: root.isBridgeMessage ? false : root.senderIsAdded
sender.trustIndicator: root.isBridgeMessage ? StatusContactVerificationIcons.TrustedType.None: root.senderTrustStatus
sender.profileImage {
width: 40
height: 40
@ -757,8 +775,9 @@ Loader {
pubkey: root.senderId
colorId: Utils.colorIdForPubkey(root.senderId)
colorHash: root.senderColorHash
showRing: !root.isDiscordMessage && !root.senderIsEnsVerified
showRing: !root.isDiscordMessage && !root.senderIsEnsVerified && !root.isBridgeMessage
}
sender.badgeImage: Style.svg("discord-bridge")
}
replyDetails: StatusMessageDetails {

View File

@ -25,6 +25,8 @@ StatusMenu {
property string selectedUserDisplayName: ""
property string selectedUserIcon: ""
property bool isBridgedAccount: false
readonly property bool isMe: {
return root.selectedUserPublicKey === root.store.contactsStore.myPublicKey;
}
@ -104,15 +106,18 @@ StatusMenu {
isContact: root.isContact
isCurrentUser: root.isMe
userIsEnsVerified: (!!contactDetails && contactDetails.ensVerified) || false
isBridgedAccount: root.isBridgedAccount
}
StatusMenuSeparator {
topPadding: root.topPadding
visible: !root.isBridgedAccount
}
ViewProfileMenuItem {
id: viewProfileAction
objectName: "viewProfile_StatusItem"
enabled: !root.isBridgedAccount
onTriggered: {
root.openProfileClicked(root.selectedUserPublicKey)
root.close()
@ -122,7 +127,7 @@ StatusMenu {
SendMessageMenuItem {
id: sendMessageMenuItem
objectName: "sendMessage_StatusItem"
enabled: root.isContact && !root.isBlockedContact
enabled: root.isContact && !root.isBlockedContact && !root.isBridgedAccount
onTriggered: {
root.createOneToOneChat("", root.selectedUserPublicKey, "")
root.close()
@ -133,7 +138,7 @@ StatusMenu {
id: sendContactRequestMenuItem
objectName: "sendContactRequest_StatusItem"
enabled: !root.isMe && !root.isContact
&& !root.isBlockedContact && !root.hasPendingContactRequest
&& !root.isBlockedContact && !root.hasPendingContactRequest && !root.isBridgedAccount
onTriggered: {
Global.openContactRequestPopup(root.selectedUserPublicKey, null)
root.close()
@ -149,6 +154,7 @@ StatusMenu {
&& !root.isBlockedContact
&& root.outgoingVerificationStatus === Constants.verificationStatus.unverified
&& !root.hasActiveReceivedVerificationRequestFrom
&& !root.isBridgedAccount
onTriggered: {
Global.openSendIDRequestPopup(root.selectedUserPublicKey, null)
root.close()
@ -167,6 +173,7 @@ StatusMenu {
&& !root.isBlockedContact && !root.isTrusted
&& (root.hasActiveReceivedVerificationRequestFrom
|| root.isVerificationRequestSent)
&& !root.isBridgedAccount
onTriggered: {
if (hasActiveReceivedVerificationRequestFrom) {
Global.openIncomingIDRequestPopup(root.selectedUserPublicKey, null)
@ -183,7 +190,7 @@ StatusMenu {
objectName: "rename_StatusItem"
text: qsTr("Rename")
icon.name: "edit_pencil"
enabled: !root.isMe
enabled: !root.isMe && !root.isBridgedAccount
onTriggered: {
Global.openNicknamePopupRequested(root.selectedUserPublicKey, contactDetails.localNickname,
"%1 (%2)".arg(root.selectedUserDisplayName).arg(Utils.getElidedCompressedPk(root.selectedUserPublicKey)))
@ -196,7 +203,7 @@ StatusMenu {
objectName: "unblock_StatusItem"
text: qsTr("Unblock User")
icon.name: "remove-circle"
enabled: !root.isMe && root.isBlockedContact
enabled: !root.isMe && root.isBlockedContact && !root.isBridgedAccount
onTriggered: Global.unblockContactRequested(root.selectedUserPublicKey, root.selectedUserDisplayName)
}
@ -212,7 +219,7 @@ StatusMenu {
text: qsTr("Mark as Untrustworthy")
icon.name: "warning"
type: StatusAction.Type.Danger
enabled: !root.isMe && root.userTrustIsUnknown
enabled: !root.isMe && root.userTrustIsUnknown && !root.isBridgedAccount
onTriggered: root.store.contactsStore.markUntrustworthy(root.selectedUserPublicKey)
}
@ -221,7 +228,7 @@ StatusMenu {
objectName: "removeUntrustworthy_StatusItem"
text: qsTr("Remove Untrustworthy Mark")
icon.name: "warning"
enabled: !root.isMe && root.userIsUntrustworthy
enabled: !root.isMe && root.userIsUntrustworthy && !root.isBridgedAccount
onTriggered: root.store.contactsStore.removeTrustStatus(root.selectedUserPublicKey)
}
@ -230,7 +237,7 @@ StatusMenu {
objectName: "removeContact_StatusItem"
icon.name: "remove-contact"
type: StatusAction.Type.Danger
enabled: root.isContact && !root.isBlockedContact && !root.hasPendingContactRequest
enabled: root.isContact && !root.isBlockedContact && !root.hasPendingContactRequest && !root.isBridgedAccount
onTriggered: {
Global.removeContactRequested(root.selectedUserDisplayName, root.selectedUserPublicKey)
root.close()
@ -243,7 +250,7 @@ StatusMenu {
text: qsTr("Block User")
icon.name: "cancel"
type: StatusAction.Type.Danger
enabled: !root.isMe && !root.isBlockedContact
enabled: !root.isMe && !root.isBlockedContact && !root.isBridgedAccount
onTriggered: Global.blockContactRequested(root.selectedUserPublicKey, root.selectedUserDisplayName)
}

View File

@ -457,6 +457,7 @@ QtObject {
readonly property int systemMessageMutualEventSent: 15
readonly property int systemMessageMutualEventAccepted: 16
readonly property int systemMessageMutualEventRemoved: 17
readonly property int bridgeMessageType: 18
}
readonly property QtObject messageModelRoles: QtObject {