[#2386] Fixed inline emoji reaction menu not showing on top of message
* Also replaced usage of synamic scoping with properties, signals and functions where possible Closes #2386
This commit is contained in:
parent
3c6571ac52
commit
0f0b239f2a
|
@ -18,40 +18,38 @@ import "./ChatColumn/ChatComponents"
|
|||
import "./data"
|
||||
import "../Wallet"
|
||||
|
||||
StackLayout {
|
||||
|
||||
Item {
|
||||
id: chatColumnLayout
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.minimumWidth: 300
|
||||
|
||||
property alias pinnedMessagesPopupComponent: pinnedMessagesPopupComponent
|
||||
|
||||
property int chatGroupsListViewCount: 0
|
||||
|
||||
property bool isReply: false
|
||||
property bool isImage: false
|
||||
|
||||
property bool isExtendedInput: isReply || isImage
|
||||
|
||||
property bool isConnected: false
|
||||
property string contactToRemove: ""
|
||||
|
||||
property bool showUsers: false
|
||||
|
||||
property var doNotShowAddToContactBannerToThose: ([])
|
||||
|
||||
property var onActivated: function () {
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
property string activeChatId: chatsModel.channelView.activeChannel.id
|
||||
property bool isBlocked: profileModel.contacts.isContactBlocked(activeChatId)
|
||||
property bool isContact: profileModel.contacts.isAdded(activeChatId)
|
||||
property bool contactRequestReceived: profileModel.contacts.contactRequestReceived(activeChatId)
|
||||
|
||||
property string currentNotificationChatId
|
||||
property string currentNotificationCommunityId
|
||||
property alias input: chatInput
|
||||
|
||||
property string hoveredMessage
|
||||
property string activeMessage
|
||||
property var currentTime: 0
|
||||
property var idMap: ({})
|
||||
property var suggestionsObj: ([])
|
||||
property Timer timer: Timer { }
|
||||
property var onActivated: function () {
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
function setHovered(messageId, hovered) {
|
||||
if (hovered) {
|
||||
|
@ -69,47 +67,6 @@ StackLayout {
|
|||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
property var currentTime: 0
|
||||
|
||||
Timer {
|
||||
interval: 60000; // 1 min
|
||||
running: true;
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
chatColumnLayout.currentTime = Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 300
|
||||
|
||||
currentIndex: chatsModel.channelView.activeChannelIndex > -1 && chatGroupsListViewCount > 0 ? 0 : 1
|
||||
|
||||
Component {
|
||||
id: pinnedMessagesPopupComponent
|
||||
PinnedMessagesPopup {
|
||||
id: pinnedMessagesPopup
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
MessageContextMenu {
|
||||
id: messageContextMenu
|
||||
}
|
||||
|
||||
StatusImageModal {
|
||||
id: imagePopup
|
||||
}
|
||||
|
||||
property var idMap: ({})
|
||||
property var suggestionsObj: ([])
|
||||
|
||||
function addSuggestionFromMessageList(i){
|
||||
const contactAddr = chatsModel.messageView.messageList.getMessageData(i, "publicKey");
|
||||
if(idMap[contactAddr]) return;
|
||||
|
@ -155,7 +112,6 @@ StackLayout {
|
|||
isImage = false;
|
||||
let replyMessageIndex = chatsModel.messageView.messageList.getMessageIndex(SelectedMessage.messageId);
|
||||
if (replyMessageIndex === -1) return;
|
||||
|
||||
let userName = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName")
|
||||
let message = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message")
|
||||
let identicon = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon")
|
||||
|
@ -180,25 +136,6 @@ StackLayout {
|
|||
txModalLoader.close()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: profileModel.contacts
|
||||
onContactListChanged: {
|
||||
isBlocked = profileModel.contacts.isContactBlocked(activeChatId);
|
||||
}
|
||||
onContactBlocked: {
|
||||
chatsModel.messageView.removeMessagesByUserId(publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.channelView
|
||||
onActiveChannelChanged: {
|
||||
chatsModel.messageView.hideLoadingIndicator()
|
||||
SelectedMessage.reset();
|
||||
chatColumn.isReply = false;
|
||||
}
|
||||
}
|
||||
|
||||
function clickOnNotification() {
|
||||
// So far we're just showing this app as the top most window. Once we decide about the way
|
||||
// how to notify the app what channle should be displayed within the app when user clicks
|
||||
|
@ -210,34 +147,41 @@ StackLayout {
|
|||
applicationWindow.requestActivate()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: systemTray
|
||||
onMessageClicked: function () {
|
||||
clickOnNotification()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
}
|
||||
|
||||
function positionAtMessage(messageId) {
|
||||
stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].item.scrollToMessage(messageId)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
StatusChatToolBar {
|
||||
id: topBar
|
||||
Layout.fillWidth: true
|
||||
Timer {
|
||||
interval: 60000; // 1 min
|
||||
running: true
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
chatColumnLayout.currentTime = Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
property string chatId: chatsModel.channelView.activeChannel.id
|
||||
property string profileImage: appMain.getProfileImage(chatId) || ""
|
||||
StackLayout {
|
||||
anchors.fill: parent
|
||||
currentIndex: chatsModel.channelView.activeChannelIndex > -1 && chatGroupsListViewCount > 0 ? 0 : 1
|
||||
|
||||
chatInfoButton.title: Utils.removeStatusEns(chatsModel.channelView.activeChannel.name)
|
||||
chatInfoButton.subTitle: {
|
||||
switch (chatsModel.channelView.activeChannel.chatType) {
|
||||
StatusImageModal {
|
||||
id: imagePopup
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
StatusChatToolBar {
|
||||
id: topBar
|
||||
Layout.fillWidth: true
|
||||
|
||||
property string chatId: chatsModel.channelView.activeChannel.id
|
||||
property string profileImage: appMain.getProfileImage(chatId) || ""
|
||||
|
||||
chatInfoButton.title: Utils.removeStatusEns(chatsModel.channelView.activeChannel.name)
|
||||
chatInfoButton.subTitle: {
|
||||
switch (chatsModel.channelView.activeChannel.chatType) {
|
||||
case Constants.chatTypeOneToOne:
|
||||
return (profileModel.contacts.isAdded(topBar.chatId) ?
|
||||
profileModel.contacts.contactRequestReceived(topBar.chatId) ?
|
||||
|
@ -259,113 +203,125 @@ StackLayout {
|
|||
case Constants.chatTypeCommunity:
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
chatInfoButton.image.source: profileImage || chatsModel.channelView.activeChannel.identicon
|
||||
chatInfoButton.image.isIdenticon: !!!profileImage && chatsModel.channelView.activeChannel.identicon
|
||||
chatInfoButton.icon.color: chatsModel.channelView.activeChannel.color
|
||||
chatInfoButton.type: chatsModel.channelView.activeChannel.chatType
|
||||
chatInfoButton.pinnedMessagesCount: chatsModel.messageView.pinnedMessagesList.count
|
||||
chatInfoButton.muted: chatsModel.channelView.activeChannel.muted
|
||||
chatInfoButton.image.source: profileImage || chatsModel.channelView.activeChannel.identicon
|
||||
chatInfoButton.image.isIdenticon: !!!profileImage && chatsModel.channelView.activeChannel.identicon
|
||||
chatInfoButton.icon.color: chatsModel.channelView.activeChannel.color
|
||||
chatInfoButton.type: chatsModel.channelView.activeChannel.chatType
|
||||
chatInfoButton.pinnedMessagesCount: chatsModel.messageView.pinnedMessagesList.count
|
||||
chatInfoButton.muted: chatsModel.channelView.activeChannel.muted
|
||||
|
||||
chatInfoButton.onPinnedMessagesCountClicked: openPopup(pinnedMessagesPopupComponent)
|
||||
chatInfoButton.onUnmute: chatsModel.channelView.unmuteChatItem(chatsModel.channelView.activeChannel.id)
|
||||
chatInfoButton.onPinnedMessagesCountClicked: openPopup(pinnedMessagesPopupComponent)
|
||||
chatInfoButton.onUnmute: chatsModel.channelView.unmuteChatItem(chatsModel.channelView.activeChannel.id)
|
||||
|
||||
chatInfoButton.sensor.enabled: chatsModel.channelView.activeChannel.chatType !== Constants.chatTypePublic &&
|
||||
chatsModel.channelView.activeChannel.chatType !== Constants.chatTypeCommunity
|
||||
chatInfoButton.onClicked: {
|
||||
switch (chatsModel.channelView.activeChannel.chatType) {
|
||||
chatInfoButton.sensor.enabled: chatsModel.channelView.activeChannel.chatType !== Constants.chatTypePublic &&
|
||||
chatsModel.channelView.activeChannel.chatType !== Constants.chatTypeCommunity
|
||||
chatInfoButton.onClicked: {
|
||||
switch (chatsModel.channelView.activeChannel.chatType) {
|
||||
case Constants.chatTypePrivateGroupChat:
|
||||
openPopup(groupInfoPopupComponent, {channelType: GroupInfoPopup.ChannelType.ActiveChannel})
|
||||
break;
|
||||
case Constants.chatTypeOneToOne:
|
||||
openProfilePopup(chatsModel.userNameOrAlias(chatsModel.channelView.activeChannel.id),
|
||||
chatsModel.channelView.activeChannel.id, profileImage || chatsModel.channelView.activeChannel.identicon,
|
||||
"", chatsModel.channelView.activeChannel.nickname)
|
||||
chatsModel.channelView.activeChannel.id, profileImage || chatsModel.channelView.activeChannel.identicon,
|
||||
"", chatsModel.channelView.activeChannel.nickname)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
membersButton.visible: appSettings.showOnlineUsers && chatsModel.channelView.activeChannel.chatType !== Constants.chatTypeOneToOne
|
||||
notificationButton.visible: appSettings.isActivityCenterEnabled
|
||||
notificationCount: chatsModel.activityNotificationList.unreadCount
|
||||
membersButton.visible: appSettings.showOnlineUsers && chatsModel.channelView.activeChannel.chatType !== Constants.chatTypeOneToOne
|
||||
notificationButton.visible: appSettings.isActivityCenterEnabled
|
||||
notificationCount: chatsModel.activityNotificationList.unreadCount
|
||||
|
||||
onSearchButtonClicked: searchPopup.open()
|
||||
SearchPopup {
|
||||
id: searchPopup
|
||||
}
|
||||
|
||||
onMembersButtonClicked: showUsers = !showUsers
|
||||
onNotificationButtonClicked: activityCenter.open()
|
||||
|
||||
popupMenu: ChatContextMenu {
|
||||
openHandler: {
|
||||
chatItem = chatsModel.channelView.activeChannel
|
||||
onSearchButtonClicked: searchPopup.open()
|
||||
SearchPopup {
|
||||
id: searchPopup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Component.onCompleted: {
|
||||
isConnected = chatsModel.isOnline
|
||||
if(!isConnected){
|
||||
connectedStatusRect.visible = true
|
||||
}
|
||||
}
|
||||
onMembersButtonClicked: showUsers = !showUsers
|
||||
onNotificationButtonClicked: activityCenter.open()
|
||||
|
||||
id: connectedStatusRect
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
z: 60
|
||||
height: 40
|
||||
color: isConnected ? Style.current.green : Style.current.darkGrey
|
||||
visible: false
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Style.current.white
|
||||
id: connectedStatusLbl
|
||||
text: isConnected ?
|
||||
//% "Connected"
|
||||
qsTrId("connected") :
|
||||
//% "Disconnected"
|
||||
qsTrId("disconnected")
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel
|
||||
onOnlineStatusChanged: {
|
||||
if (connected == isConnected) return;
|
||||
isConnected = connected;
|
||||
if(isConnected){
|
||||
timer.setTimeout(function(){
|
||||
connectedStatusRect.visible = false;
|
||||
}, 5000);
|
||||
} else {
|
||||
connectedStatusRect.visible = true;
|
||||
popupMenu: ChatContextMenu {
|
||||
openHandler: {
|
||||
chatItem = chatsModel.channelView.activeChannel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddToContactBanner {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Rectangle {
|
||||
id: connectedStatusRect
|
||||
Layout.fillWidth: true
|
||||
height: 40
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
z: 60
|
||||
visible: false
|
||||
color: isConnected ? Style.current.green : Style.current.darkGrey
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Style.current.white
|
||||
id: connectedStatusLbl
|
||||
text: isConnected ?
|
||||
//% "Connected"
|
||||
qsTrId("connected") :
|
||||
//% "Disconnected"
|
||||
qsTrId("disconnected")
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackLayoutChatMessages
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
Repeater {
|
||||
model: chatsModel.messageView
|
||||
Loader {
|
||||
active: false
|
||||
sourceComponent: ChatMessages {
|
||||
id: chatMessages
|
||||
messageList: model.messages
|
||||
currentTime: chatColumnLayout.currentTime
|
||||
Connections {
|
||||
target: chatsModel
|
||||
onOnlineStatusChanged: {
|
||||
if (connected == isConnected) return;
|
||||
isConnected = connected;
|
||||
if(isConnected){
|
||||
timer.setTimeout(function(){
|
||||
connectedStatusRect.visible = false;
|
||||
}, 5000);
|
||||
} else {
|
||||
connectedStatusRect.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
isConnected = chatsModel.isOnline
|
||||
if(!isConnected){
|
||||
connectedStatusRect.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddToContactBanner {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stackLayoutChatMessages
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
Repeater {
|
||||
model: chatsModel.messageView
|
||||
Loader {
|
||||
active: false
|
||||
sourceComponent: ChatMessages {
|
||||
messageList: model.messages
|
||||
currentTime: chatColumnLayout.currentTime
|
||||
messageContextMenuInst: MessageContextMenu {
|
||||
reactionModel: EmojiReactions { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.channelView
|
||||
onActiveChannelChanged: {
|
||||
stackLayoutChatMessages.currentIndex = chatsModel.messageView.getMessageListIndex(chatsModel.channelView.activeChannelIndex)
|
||||
if(stackLayoutChatMessages.currentIndex > -1 && !stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active){
|
||||
stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,293 +329,320 @@ StackLayout {
|
|||
Connections {
|
||||
target: chatsModel.channelView
|
||||
onActiveChannelChanged: {
|
||||
stackLayoutChatMessages.currentIndex = chatsModel.messageView.getMessageListIndex(chatsModel.channelView.activeChannelIndex)
|
||||
if(stackLayoutChatMessages.currentIndex > -1 && !stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active){
|
||||
stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active = true;
|
||||
chatInput.suggestions.hide();
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
populateSuggestions();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onMessagePushed: {
|
||||
addSuggestionFromMessageList(messageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: profileModel
|
||||
onContactsChanged: {
|
||||
populateSuggestions();
|
||||
}
|
||||
}
|
||||
|
||||
ChatRequestMessage {
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: Style.current.bigPadding
|
||||
}
|
||||
|
||||
Item {
|
||||
id: inputArea
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: parent.width
|
||||
height: chatInput.height
|
||||
Layout.preferredHeight: height
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onLoadingMessagesChanged:
|
||||
if(value){
|
||||
loadingMessagesIndicator.active = true
|
||||
} else {
|
||||
timer.setTimeout(function(){
|
||||
loadingMessagesIndicator.active = false;
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loadingMessagesIndicator
|
||||
active: chatsModel.messageView.loadingMessages
|
||||
sourceComponent: loadingIndicator
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: chatInput.top
|
||||
anchors.rightMargin: Style.current.padding
|
||||
anchors.bottomMargin: Style.current.padding
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loadingIndicator
|
||||
LoadingAnimation { }
|
||||
}
|
||||
|
||||
StatusChatInput {
|
||||
id: chatInput
|
||||
visible: {
|
||||
if (chatsModel.channelView.activeChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||
return chatsModel.channelView.activeChannel.isMember
|
||||
}
|
||||
if (chatsModel.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) {
|
||||
return isContact && contactRequestReceived
|
||||
}
|
||||
const community = chatsModel.communities.activeCommunity
|
||||
return !community.active ||
|
||||
community.access === Constants.communityChatPublicAccess ||
|
||||
community.admin ||
|
||||
chatsModel.channelView.activeChannel.canPost
|
||||
}
|
||||
enabled: !isBlocked
|
||||
chatInputPlaceholder: isBlocked ?
|
||||
//% "This user has been blocked."
|
||||
qsTrId("this-user-has-been-blocked-") :
|
||||
//% "Type a message."
|
||||
qsTrId("type-a-message-")
|
||||
anchors.bottom: parent.bottom
|
||||
recentStickers: chatsModel.stickers.recent
|
||||
stickerPackList: chatsModel.stickers.stickerPacks
|
||||
chatType: chatsModel.channelView.activeChannel.chatType
|
||||
onSendTransactionCommandButtonClicked: {
|
||||
if (chatsModel.channelView.activeChannel.ensVerified) {
|
||||
txModalLoader.sourceComponent = cmpSendTransactionWithEns
|
||||
} else {
|
||||
txModalLoader.sourceComponent = cmpSendTransactionNoEns
|
||||
}
|
||||
txModalLoader.item.open()
|
||||
}
|
||||
onReceiveTransactionCommandButtonClicked: {
|
||||
txModalLoader.sourceComponent = cmpReceiveTransaction
|
||||
txModalLoader.item.open()
|
||||
}
|
||||
onStickerSelected: {
|
||||
chatsModel.stickers.send(hashId, packId)
|
||||
}
|
||||
onSendMessage: {
|
||||
if (chatInput.fileUrls.length > 0){
|
||||
chatsModel.sendImages(JSON.stringify(fileUrls));
|
||||
}
|
||||
let msg = chatsModel.plainText(Emoji.deparse(chatInput.textInput.text))
|
||||
if (msg.length > 0){
|
||||
msg = chatInput.interpretMessage(msg)
|
||||
chatsModel.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
|
||||
if(event) event.accepted = true
|
||||
sendMessageSound.stop();
|
||||
Qt.callLater(sendMessageSound.play);
|
||||
|
||||
chatInput.textInput.clear();
|
||||
chatInput.textInput.textFormat = TextEdit.PlainText;
|
||||
chatInput.textInput.textFormat = TextEdit.RichText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EmojiReactions {
|
||||
id: reactionModel
|
||||
EmptyChat { }
|
||||
|
||||
Loader {
|
||||
id: txModalLoader
|
||||
function close() {
|
||||
if (!this.item) {
|
||||
return
|
||||
}
|
||||
this.item.close()
|
||||
this.closed()
|
||||
}
|
||||
function closed() {
|
||||
this.sourceComponent = undefined
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cmpSendTransactionNoEns
|
||||
ChatCommandModal {
|
||||
id: sendTransactionNoEns
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
sendChatCommand: chatColumnLayout.requestAddressForTransaction
|
||||
isRequested: false
|
||||
//% "Send"
|
||||
commandTitle: qsTrId("command-button-send")
|
||||
title: commandTitle
|
||||
//% "Request Address"
|
||||
finalButtonLabel: qsTrId("request-address")
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: Constants.zeroAddress, // Setting as zero address since we don't have the address yet
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
selectRecipient.readOnly: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cmpReceiveTransaction
|
||||
ChatCommandModal {
|
||||
id: receiveTransaction
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
sendChatCommand: chatColumnLayout.requestTransaction
|
||||
isRequested: true
|
||||
//% "Request"
|
||||
commandTitle: qsTrId("wallet-request")
|
||||
title: commandTitle
|
||||
//% "Request"
|
||||
finalButtonLabel: qsTrId("wallet-request")
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: Constants.zeroAddress, // Setting as zero address since we don't have the address yet
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
selectRecipient.readOnly: true
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cmpSendTransactionWithEns
|
||||
SendModal {
|
||||
id: sendTransactionWithEns
|
||||
onOpened: {
|
||||
walletModel.gasView.getGasPricePredictions()
|
||||
}
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
selectRecipient.readOnly: true
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: "",
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact,
|
||||
ensVerified: true
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
|
||||
ActivityCenter {
|
||||
id: activityCenter
|
||||
height: chatColumnLayout.height - (topBar.height * 2) // TODO get screen size
|
||||
y: topBar.height
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: profileModel.contacts
|
||||
onContactListChanged: {
|
||||
isBlocked = profileModel.contacts.isContactBlocked(activeChatId);
|
||||
}
|
||||
onContactBlocked: {
|
||||
chatsModel.messageView.removeMessagesByUserId(publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.channelView
|
||||
onActiveChannelChanged: {
|
||||
chatInput.suggestions.hide();
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
populateSuggestions();
|
||||
chatsModel.messageView.hideLoadingIndicator()
|
||||
SelectedMessage.reset();
|
||||
chatColumn.isReply = false;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: systemTray
|
||||
onMessageClicked: function () {
|
||||
clickOnNotification()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: pinnedMessagesPopupComponent
|
||||
PinnedMessagesPopup {
|
||||
id: pinnedMessagesPopup
|
||||
onClosed: destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onMessagePushed: {
|
||||
addSuggestionFromMessageList(messageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: profileModel
|
||||
onContactsChanged: {
|
||||
populateSuggestions();
|
||||
}
|
||||
}
|
||||
onMessageNotificationPushed: function(chatId, msg, contentType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) {
|
||||
if (contentType == Constants.editType)
|
||||
return;
|
||||
|
||||
ChatRequestMessage {
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: Style.current.bigPadding
|
||||
}
|
||||
if (appSettings.notificationSetting == Constants.notifyAllMessages ||
|
||||
(appSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) {
|
||||
if (chatId === chatsModel.channelView.activeChannel.id && applicationWindow.active === true) {
|
||||
// Do not show the notif if we are in the channel already and the window is active and focused
|
||||
return
|
||||
}
|
||||
|
||||
Item {
|
||||
id: inputArea
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: parent.width
|
||||
height: chatInput.height
|
||||
Layout.preferredHeight: height
|
||||
chatColumnLayout.currentNotificationChatId = chatId
|
||||
chatColumnLayout.currentNotificationCommunityId = null
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
onLoadingMessagesChanged:
|
||||
if(value){
|
||||
loadingMessagesIndicator.active = true
|
||||
let name;
|
||||
if (appSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) {
|
||||
name = "Status"
|
||||
} else if (chatType === Constants.chatTypePublic) {
|
||||
name = chatId
|
||||
} else {
|
||||
timer.setTimeout(function(){
|
||||
loadingMessagesIndicator.active = false;
|
||||
}, 5000);
|
||||
name = chatType === Constants.chatTypePrivateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username)
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loadingMessagesIndicator
|
||||
active: chatsModel.messageView.loadingMessages
|
||||
sourceComponent: loadingIndicator
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: chatInput.top
|
||||
anchors.rightMargin: Style.current.padding
|
||||
anchors.bottomMargin: Style.current.padding
|
||||
}
|
||||
|
||||
Component {
|
||||
id: loadingIndicator
|
||||
LoadingAnimation {}
|
||||
}
|
||||
|
||||
StatusChatInput {
|
||||
id: chatInput
|
||||
visible: {
|
||||
if (chatsModel.channelView.activeChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||
return chatsModel.channelView.activeChannel.isMember
|
||||
}
|
||||
if (chatsModel.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) {
|
||||
return isContact && contactRequestReceived
|
||||
}
|
||||
const community = chatsModel.communities.activeCommunity
|
||||
return !community.active ||
|
||||
community.access === Constants.communityChatPublicAccess ||
|
||||
community.admin ||
|
||||
chatsModel.channelView.activeChannel.canPost
|
||||
}
|
||||
enabled: !isBlocked
|
||||
chatInputPlaceholder: isBlocked ?
|
||||
//% "This user has been blocked."
|
||||
qsTrId("this-user-has-been-blocked-") :
|
||||
//% "Type a message."
|
||||
qsTrId("type-a-message-")
|
||||
anchors.bottom: parent.bottom
|
||||
recentStickers: chatsModel.stickers.recent
|
||||
stickerPackList: chatsModel.stickers.stickerPacks
|
||||
chatType: chatsModel.channelView.activeChannel.chatType
|
||||
onSendTransactionCommandButtonClicked: {
|
||||
if (chatsModel.channelView.activeChannel.ensVerified) {
|
||||
txModalLoader.sourceComponent = cmpSendTransactionWithEns
|
||||
let message;
|
||||
if (appSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) {
|
||||
switch(contentType){
|
||||
//% "Image"
|
||||
case Constants.imageType: message = qsTrId("image"); break
|
||||
//% "Sticker"
|
||||
case Constants.stickerType: message = qsTrId("sticker"); break
|
||||
default: message = msg // don't parse emojis here as it emits HTML
|
||||
}
|
||||
} else {
|
||||
txModalLoader.sourceComponent = cmpSendTransactionNoEns
|
||||
//% "You have a new message"
|
||||
message = qsTrId("you-have-a-new-message")
|
||||
}
|
||||
txModalLoader.item.open()
|
||||
}
|
||||
onReceiveTransactionCommandButtonClicked: {
|
||||
txModalLoader.sourceComponent = cmpReceiveTransaction
|
||||
txModalLoader.item.open()
|
||||
}
|
||||
onStickerSelected: {
|
||||
chatsModel.stickers.send(hashId, packId)
|
||||
}
|
||||
onSendMessage: {
|
||||
if (chatInput.fileUrls.length > 0){
|
||||
chatsModel.sendImages(JSON.stringify(fileUrls));
|
||||
}
|
||||
let msg = chatsModel.plainText(Emoji.deparse(chatInput.textInput.text))
|
||||
if (msg.length > 0){
|
||||
msg = chatInput.interpretMessage(msg)
|
||||
chatsModel.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
|
||||
if(event) event.accepted = true
|
||||
sendMessageSound.stop();
|
||||
Qt.callLater(sendMessageSound.play);
|
||||
|
||||
chatInput.textInput.clear();
|
||||
chatInput.textInput.textFormat = TextEdit.PlainText;
|
||||
chatInput.textInput.textFormat = TextEdit.RichText;
|
||||
currentlyHasANotification = true
|
||||
if (appSettings.useOSNotifications && systemTray.supportsMessages) {
|
||||
systemTray.showMessage(name,
|
||||
message,
|
||||
SystemTrayIcon.NoIcon,
|
||||
Constants.notificationPopupTTL)
|
||||
} else {
|
||||
notificationWindow.notifyUser(chatId, name, message, chatType, identicon, chatColumnLayout.clickOnNotification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EmptyChat {}
|
||||
|
||||
Loader {
|
||||
id: txModalLoader
|
||||
function close() {
|
||||
if (!this.item) {
|
||||
return
|
||||
}
|
||||
this.item.close()
|
||||
this.closed()
|
||||
}
|
||||
function closed() {
|
||||
this.sourceComponent = undefined
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: cmpSendTransactionNoEns
|
||||
ChatCommandModal {
|
||||
id: sendTransactionNoEns
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
sendChatCommand: chatColumnLayout.requestAddressForTransaction
|
||||
isRequested: false
|
||||
//% "Send"
|
||||
commandTitle: qsTrId("command-button-send")
|
||||
title: commandTitle
|
||||
//% "Request Address"
|
||||
finalButtonLabel: qsTrId("request-address")
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: Constants.zeroAddress, // Setting as zero address since we don't have the address yet
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
selectRecipient.readOnly: true
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: cmpReceiveTransaction
|
||||
ChatCommandModal {
|
||||
id: receiveTransaction
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
sendChatCommand: chatColumnLayout.requestTransaction
|
||||
isRequested: true
|
||||
//% "Request"
|
||||
commandTitle: qsTrId("wallet-request")
|
||||
title: commandTitle
|
||||
//% "Request"
|
||||
finalButtonLabel: qsTrId("wallet-request")
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: Constants.zeroAddress, // Setting as zero address since we don't have the address yet
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
selectRecipient.readOnly: true
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: cmpSendTransactionWithEns
|
||||
SendModal {
|
||||
id: sendTransactionWithEns
|
||||
onOpened: {
|
||||
walletModel.gasView.getGasPricePredictions()
|
||||
}
|
||||
onClosed: {
|
||||
txModalLoader.closed()
|
||||
}
|
||||
selectRecipient.readOnly: true
|
||||
selectRecipient.selectedRecipient: {
|
||||
return {
|
||||
address: "",
|
||||
alias: chatsModel.channelView.activeChannel.alias,
|
||||
identicon: chatsModel.channelView.activeChannel.identicon,
|
||||
name: chatsModel.channelView.activeChannel.name,
|
||||
type: RecipientSelector.Type.Contact,
|
||||
ensVerified: true
|
||||
}
|
||||
}
|
||||
selectRecipient.selectedType: RecipientSelector.Type.Contact
|
||||
}
|
||||
}
|
||||
|
||||
ActivityCenter {
|
||||
id: activityCenter
|
||||
height: chatColumnLayout.height - (topBar.height * 2) // TODO get screen size
|
||||
y: topBar.height
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatsModel.messageView
|
||||
|
||||
onMessageNotificationPushed: function(chatId, msg, contentType, chatType, timestamp, identicon, username, hasMention, isAddedContact, channelName) {
|
||||
if (contentType == Constants.editType)
|
||||
return;
|
||||
|
||||
if (appSettings.notificationSetting == Constants.notifyAllMessages ||
|
||||
(appSettings.notificationSetting == Constants.notifyJustMentions && hasMention)) {
|
||||
if (chatId === chatsModel.channelView.activeChannel.id && applicationWindow.active === true) {
|
||||
// Do not show the notif if we are in the channel already and the window is active and focused
|
||||
return
|
||||
}
|
||||
|
||||
chatColumnLayout.currentNotificationChatId = chatId
|
||||
chatColumnLayout.currentNotificationCommunityId = null
|
||||
|
||||
let name;
|
||||
if (appSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) {
|
||||
name = "Status"
|
||||
} else if (chatType === Constants.chatTypePublic) {
|
||||
name = chatId
|
||||
} else {
|
||||
name = chatType === Constants.chatTypePrivateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username)
|
||||
}
|
||||
|
||||
let message;
|
||||
if (appSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) {
|
||||
switch(contentType){
|
||||
//% "Image"
|
||||
case Constants.imageType: message = qsTrId("image"); break
|
||||
//% "Sticker"
|
||||
case Constants.stickerType: message = qsTrId("sticker"); break
|
||||
default: message = msg // don't parse emojis here as it emits HTML
|
||||
}
|
||||
} else {
|
||||
//% "You have a new message"
|
||||
message = qsTrId("you-have-a-new-message")
|
||||
}
|
||||
|
||||
currentlyHasANotification = true
|
||||
if (appSettings.useOSNotifications && systemTray.supportsMessages) {
|
||||
systemTray.showMessage(name,
|
||||
message,
|
||||
SystemTrayIcon.NoIcon,
|
||||
Constants.notificationPopupTTL)
|
||||
} else {
|
||||
notificationWindow.notifyUser(chatId, name, message, chatType, identicon, chatColumnLayout.clickOnNotification)
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ SplitView {
|
|||
property alias chatLogView: chatLogView
|
||||
property alias scrollToMessage: chatLogView.scrollToMessage
|
||||
|
||||
property var messageContextMenuInst
|
||||
property var messageList: MessagesData {}
|
||||
property bool loadingMessages: false
|
||||
property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight
|
||||
|
@ -248,11 +249,9 @@ SplitView {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
model: messageListDelegate
|
||||
section.property: "sectionIdentifier"
|
||||
section.criteria: ViewSection.FullString
|
||||
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
|
@ -317,6 +316,8 @@ SplitView {
|
|||
z = index;
|
||||
}
|
||||
}
|
||||
messageContextMenu: svRoot.messageContextMenuInst
|
||||
|
||||
// This is used in order to have access to the previous message and determine the timestamp
|
||||
// we can't rely on the index because the sequence of messages is not ordered on the nim side
|
||||
prevMessageIndex: {
|
||||
|
|
|
@ -7,6 +7,17 @@ import "./MessageComponents"
|
|||
import "../components"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: parent.width
|
||||
anchors.right: !isCurrentUser ? undefined : parent.right
|
||||
height: {
|
||||
switch (contentType) {
|
||||
case Constants.chatIdentifier:
|
||||
return (childrenRect.height + 50);
|
||||
default: return childrenRect.height;
|
||||
}
|
||||
}
|
||||
z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index)
|
||||
property string fromAuthor: "0x0011223344556677889910"
|
||||
property string userName: "Jotaro Kujo"
|
||||
property string alias: ""
|
||||
|
@ -42,15 +53,7 @@ Item {
|
|||
property string replaces: ""
|
||||
property bool isEdited: false
|
||||
property bool showEdit: true
|
||||
|
||||
z: {
|
||||
if (typeof chatLogView === "undefined") {
|
||||
return 1
|
||||
}
|
||||
|
||||
return chatLogView.count - index
|
||||
}
|
||||
|
||||
property var messageContextMenu
|
||||
property string displayUserName: {
|
||||
if (isCurrentUser) {
|
||||
//% "You"
|
||||
|
@ -183,17 +186,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
id: root
|
||||
width: parent.width
|
||||
anchors.right: !isCurrentUser ? undefined : parent.right
|
||||
height: {
|
||||
switch(contentType) {
|
||||
case Constants.chatIdentifier:
|
||||
return childrenRect.height + 50
|
||||
default: return childrenRect.height
|
||||
}
|
||||
}
|
||||
|
||||
property var clickMessage: function(isProfileClick, isSticker = false, isImage = false, image = null, emojiOnly = false, hideEmojiPicker = false) {
|
||||
if (placeholderMessage || activityCenterMessage) {
|
||||
return
|
||||
|
@ -210,17 +202,17 @@ Item {
|
|||
|
||||
// Get contact nickname
|
||||
let nickname = appMain.getUserNickname(fromAuthor)
|
||||
messageContextMenu.messageId = root.messageId
|
||||
messageContextMenu.linkUrls = root.linkUrls
|
||||
messageContextMenu.isProfile = !!isProfileClick
|
||||
messageContextMenu.isSticker = isSticker
|
||||
messageContextMenu.emojiOnly = emojiOnly
|
||||
messageContextMenu.hideEmojiPicker = hideEmojiPicker
|
||||
messageContextMenu.pinnedMessage = pinnedMessage
|
||||
messageContextMenu.show(userName, fromAuthor, root.profileImageSource || identicon, plainText, nickname, emojiReactionsModel)
|
||||
messageContextMenu.messageId = root.messageId;
|
||||
messageContextMenu.linkUrls = root.linkUrls;
|
||||
messageContextMenu.isProfile = !!isProfileClick;
|
||||
messageContextMenu.isSticker = isSticker;
|
||||
messageContextMenu.emojiOnly = emojiOnly;
|
||||
messageContextMenu.hideEmojiPicker = hideEmojiPicker;
|
||||
messageContextMenu.pinnedMessage = pinnedMessage;
|
||||
messageContextMenu.show(userName, fromAuthor, root.profileImageSource || identicon, plainText, nickname, emojiReactionsModel);
|
||||
// Position the center of the menu where the mouse is
|
||||
if (messageContextMenu.x + messageContextMenu.width + Style.current.padding < root.width) {
|
||||
messageContextMenu.x = messageContextMenu.x - messageContextMenu.width / 2
|
||||
messageContextMenu.x = messageContextMenu.x - messageContextMenu.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,6 +438,10 @@ Item {
|
|||
contentType: root.contentType
|
||||
showEdit: root.showEdit
|
||||
container: root
|
||||
messageContextMenu: root.messageContextMenu
|
||||
onAddEmoji: {
|
||||
root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@ import "../../../../../shared/status"
|
|||
import "../../../../../imports"
|
||||
|
||||
Rectangle {
|
||||
id: buttonsContainer
|
||||
property bool parentIsHovered: false
|
||||
property bool showEdit: true
|
||||
signal hoverChanged(bool hovered)
|
||||
property int containerMargin: 2
|
||||
property int contentType: 2
|
||||
property var messageContextMenu
|
||||
|
||||
id: buttonsContainer
|
||||
visible: !activityCenterMessage &&
|
||||
(buttonsContainer.parentIsHovered || isMessageActive)
|
||||
&& contentType !== Constants.transactionType
|
||||
|
@ -65,10 +66,10 @@ Rectangle {
|
|||
setMessageActive(messageId, true)
|
||||
clickMessage(false, false, false, null, true)
|
||||
if (!forceHoverHandler) {
|
||||
messageContextMenu.x = buttonsContainer.x + buttonsContainer.width - messageContextMenu.width
|
||||
buttonsContainer.messageContextMenu.x = buttonsContainer.x + buttonsContainer.width - buttonsContainer.messageContextMenu.width
|
||||
|
||||
// The Math.max is to make sure that the menu is rendered
|
||||
messageContextMenu.y -= Math.max(messageContextMenu.emojiContainer.height, 56) + Style.current.padding
|
||||
buttonsContainer.messageContextMenu.y -= Math.max(buttonsContainer.messageContextMenu.emojiContainer.height, 56) + Style.current.padding
|
||||
}
|
||||
}
|
||||
onHoveredChanged: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import "../../../../../shared/status"
|
|||
import "../../../../../imports"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var clickMessage: function () {}
|
||||
property int chatHorizontalPadding: Style.current.halfPadding
|
||||
property int chatVerticalPadding: 7
|
||||
|
@ -16,8 +17,8 @@ Item {
|
|||
property bool isMessageActive: typeof activeMessage !== "undefined" && activeMessage === messageId
|
||||
property bool headerRepeatCondition: (authorCurrentMsg !== authorPrevMsg || shouldRepeatHeader || dateGroupLbl.visible || chatReply.active)
|
||||
property bool showEdit: true
|
||||
|
||||
id: root
|
||||
property var messageContextMenu
|
||||
signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker)
|
||||
|
||||
width: parent.width
|
||||
height: messageContainer.height + messageContainer.anchors.topMargin
|
||||
|
@ -42,6 +43,7 @@ Item {
|
|||
// This is not exactly like the design because the hover becomes messed up with the buttons on top of another Message
|
||||
anchors.topMargin: -Style.current.halfPadding
|
||||
showEdit: root.showEdit
|
||||
messageContextMenu: root.messageContextMenu
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
@ -410,6 +412,11 @@ Item {
|
|||
sourceComponent: Component {
|
||||
EmojiReactions {
|
||||
onHoverChanged: setHovered(messageId, hovered)
|
||||
onAddEmojiClicked: {
|
||||
root.addEmoji(false, false, false, null, true, false);
|
||||
messageContextMenu.x = (messageContainer.chatText.textField.leftPadding + 4);
|
||||
messageContextMenu.y -= (56 + Style.current.padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@ import "../../../../../shared/status"
|
|||
import "../../../../../imports"
|
||||
|
||||
Item {
|
||||
property int imageMargin: 4
|
||||
signal hoverChanged(bool hovered)
|
||||
|
||||
id: root
|
||||
height: 20
|
||||
width: childrenRect.width
|
||||
|
||||
property int imageMargin: 4
|
||||
signal hoverChanged(bool hovered)
|
||||
signal addEmojiClicked()
|
||||
|
||||
function lastTwoItems(nodes) {
|
||||
//% " and "
|
||||
return nodes.join(qsTrId("-and-"));
|
||||
|
@ -210,7 +211,7 @@ Item {
|
|||
if (typeof isMessageActive !== "undefined") {
|
||||
setMessageActive(messageId, true)
|
||||
}
|
||||
clickMessage(false, false, false, null, true)
|
||||
root.addEmojiClicked();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ import "../../../../shared/status"
|
|||
import "./"
|
||||
|
||||
PopupMenu {
|
||||
id: messageContextMenu
|
||||
width: messageContextMenu.isProfile ? profileHeader.width : emojiContainer.width
|
||||
|
||||
property string messageId
|
||||
property bool isProfile: false
|
||||
property bool isSticker: false
|
||||
|
@ -18,10 +21,6 @@ PopupMenu {
|
|||
property bool isCurrentUser: false
|
||||
property string linkUrls: ""
|
||||
property alias emojiContainer: emojiContainer
|
||||
|
||||
id: messageContextMenu
|
||||
width: messageContextMenu.isProfile ? profileHeader.width : emojiContainer.width
|
||||
|
||||
property var identicon: ""
|
||||
property var userName: ""
|
||||
property string nickname: ""
|
||||
|
@ -29,14 +28,13 @@ PopupMenu {
|
|||
property var text: ""
|
||||
property var emojiReactionsReactedByUser: []
|
||||
property var onClickEdit: function(){}
|
||||
property var reactionModel
|
||||
|
||||
subMenuIcons: [
|
||||
{
|
||||
subMenuIcons: [{
|
||||
source: Qt.resolvedUrl("../../../../shared/img/copy-to-clipboard-icon"),
|
||||
width: 16,
|
||||
height: 16
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
function show(userNameParam, fromAuthorParam, identiconParam, textParam, nicknameParam, emojiReactionsModel) {
|
||||
userName = userNameParam || ""
|
||||
|
@ -50,7 +48,7 @@ PopupMenu {
|
|||
newEmojiReactions[emojiReaction.emojiId] = emojiReaction.currentUserReacted
|
||||
})
|
||||
}
|
||||
emojiReactionsReactedByUser = newEmojiReactions
|
||||
emojiReactionsReactedByUser = newEmojiReactions;
|
||||
|
||||
const numLinkUrls = messageContextMenu.linkUrls.split(" ").length
|
||||
copyLinkMenu.enabled = numLinkUrls > 1
|
||||
|
@ -60,10 +58,9 @@ PopupMenu {
|
|||
|
||||
Item {
|
||||
id: emojiContainer
|
||||
visible: !hideEmojiPicker && (messageContextMenu.emojiOnly || !messageContextMenu.isProfile)
|
||||
width: emojiRow.width
|
||||
height: visible ? emojiRow.height : 0
|
||||
|
||||
visible: !hideEmojiPicker && (messageContextMenu.emojiOnly || !messageContextMenu.isProfile)
|
||||
Row {
|
||||
id: emojiRow
|
||||
spacing: Style.current.smallPadding
|
||||
|
@ -85,15 +82,16 @@ PopupMenu {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
property bool hovered: false
|
||||
|
||||
Item {
|
||||
id: profileHeader
|
||||
visible: messageContextMenu.isProfile
|
||||
width: 200
|
||||
height: visible ? profileImage.height + username.height + Style.current.padding : 0
|
||||
color: hovered ? Style.current.backgroundHover : Style.current.transparent
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: mouseArea.containsMouse
|
||||
color: Style.current.backgroundHover
|
||||
}
|
||||
StatusImageIdenticon {
|
||||
id: profileImage
|
||||
source: identicon
|
||||
|
@ -120,15 +118,10 @@ PopupMenu {
|
|||
}
|
||||
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
profileHeader.hovered = true
|
||||
}
|
||||
onExited: {
|
||||
profileHeader.hovered = false
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
openProfilePopup(userName, fromAuthor, identicon);
|
||||
messageContextMenu.close()
|
||||
|
|
Loading…
Reference in New Issue