status-desktop/ui/app/AppLayouts/Chat/views/ChatContentView.qml

306 lines
10 KiB
QML

import QtQuick 2.13
import Qt.labs.platform 1.1
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.0
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import utils 1.0
import shared 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.controls 1.0
import shared.views.chat 1.0
import "../helpers"
import "../controls"
import "../popups"
import "../panels"
import "../../Wallet"
import "../stores"
ColumnLayout {
id: root
objectName: "chatContentViewColumn"
spacing: 0
// Important:
// Each chat/channel has its own ChatContentModule
property var chatContentModule
property var chatSectionModule
property var rootStore
property var contactsStore
property bool isActiveChannel: false
property bool isConnected: false
property var emojiPopup
property alias textInputField: chatInput
property UsersStore usersStore: UsersStore {}
property Component pinnedMessagesPopupComponent
onChatContentModuleChanged: {
root.usersStore.usersModule = root.chatContentModule.usersModule
}
signal openAppSearch()
signal openStickerPackPopup(string stickerPackId)
property Component sendTransactionNoEnsModal
property Component receiveTransactionModal
property Component sendTransactionWithEnsModal
property bool isBlocked: false
property bool stickersLoaded: false
// NOTE: Used this property change as it is the current way used for displaying new channel/chat data of content view.
// If in the future content is loaded dynamically, input focus should be activated when loaded / created content view.
onHeightChanged: {
if(root.height > 0) {
chatInput.forceInputActiveFocus()
}
}
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 ?
qsTr("Connected") :
qsTr("Disconnected")
}
Connections {
target: mainModule
onOnlineStatusChanged: {
if (connected === isConnected) return;
isConnected = connected;
if(isConnected) {
onlineStatusTimer.start();
} else {
connectedStatusRect.visible = true;
}
}
}
Component.onCompleted: {
isConnected = mainModule.isOnline
if(!isConnected){
connectedStatusRect.visible = true
}
}
}
Timer {
id: onlineStatusTimer
interval: 5000
onTriggered: {
connectedStatusRect.visible = false;
}
}
StatusBanner {
Layout.fillWidth: true
visible: root.isBlocked
type: StatusBanner.Type.Danger
statusText: qsTr("Blocked")
}
MessageStore {
id: messageStore
messageModule: chatContentModule? chatContentModule.messagesModule : null
chatSectionModule: root.rootStore.chatCommunitySectionModule
}
MessageContextMenuView {
id: contextmenu
store: root.rootStore
reactionModel: root.rootStore.emojiReactionsModel
onPinMessage: {
messageStore.pinMessage(messageId)
}
onUnpinMessage: {
messageStore.unpinMessage(messageId)
}
onPinnedMessagesLimitReached: {
if(!chatContentModule) {
console.debug("error on open pinned messages limit reached from message context menu - chat content module is not set")
return
}
Global.openPopup(Global.pinnedMessagesPopup, {
store: rootStore,
messageStore: messageStore,
pinnedMessagesModel: chatContentModule.pinnedMessagesModel,
messageToPin: messageId
})
}
onToggleReaction: {
messageStore.toggleReaction(messageId, emojiId)
}
onOpenProfileClicked: {
Global.openProfilePopup(publicKey, null, state)
}
onDeleteMessage: {
messageStore.deleteMessage(messageId)
}
onEditClicked: messageStore.setEditModeOn(messageId)
onCreateOneToOneChat: {
Global.changeAppSectionBySectionType(Constants.appSection.chat)
root.rootStore.chatCommunitySectionModule.createOneToOneChat("", chatId, ensName)
}
onShowReplyArea: {
let obj = messageStore.getMessageByIdAsJson(messageId)
if (!obj) {
return
}
chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.sticker)
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ChatMessagesView {
id: chatMessages
Layout.fillWidth: true
Layout.fillHeight: true
chatContentModule: root.chatContentModule
rootStore: root.rootStore
contactsStore: root.contactsStore
messageContextMenu: contextmenu
messageStore: messageStore
emojiPopup: root.emojiPopup
usersStore: root.usersStore
stickersLoaded: root.stickersLoaded
isChatBlocked: root.isBlocked
channelEmoji: !chatContentModule ? "" : (chatContentModule.chatDetails.emoji || "")
isActiveChannel: root.isActiveChannel
onShowReplyArea: {
let obj = messageStore.getMessageByIdAsJson(messageId)
if (!obj) {
return
}
chatInput.showReplyArea(messageId, obj.senderDisplayName, obj.messageText, obj.contentType, obj.messageImage, obj.sticker)
}
onOpenStickerPackPopup: {
root.openStickerPackPopup(stickerPackId);
}
}
Item {
id: inputArea
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.fillWidth: true
Layout.preferredHeight: chatInput.implicitHeight
+ chatInput.anchors.topMargin
+ chatInput.anchors.bottomMargin
Loader {
id: loadingMessagesIndicator
active: root.rootStore.loadingHistoryMessagesInProgress
visible: root.rootStore.loadingHistoryMessagesInProgress
sourceComponent: LoadingAnimation { }
anchors {
right: parent.right
bottom: chatInput.top
rightMargin: Style.current.padding
bottomMargin: Style.current.padding
}
}
StatusChatInput {
id: chatInput
anchors.fill: parent
anchors.margins: Style.current.smallPadding
store: root.rootStore
usersStore: root.usersStore
messageContextMenu: contextmenu
emojiPopup: root.emojiPopup
isContactBlocked: root.isBlocked
isActiveChannel: root.isActiveChannel
anchors.bottom: parent.bottom
recentStickers: root.rootStore.stickersModuleInst.recent
stickerPackList: root.rootStore.stickersModuleInst.stickerPacks
chatType: chatContentModule? chatContentModule.chatDetails.type : Constants.chatType.unknown
Binding on chatInputPlaceholder {
when: root.isBlocked
value: qsTr("This user has been blocked.")
}
onSendTransactionCommandButtonClicked: {
if(!chatContentModule) {
console.debug("error on sending transaction command - chat content module is not set")
return
}
if (Utils.getContactDetailsAsJson(chatContentModule.getMyChatId()).ensVerified) {
Global.openPopup(root.sendTransactionWithEnsModal)
} else {
Global.openPopup(root.sendTransactionNoEnsModal)
}
}
onReceiveTransactionCommandButtonClicked: {
Global.openPopup(root.receiveTransactionModal)
}
onStickerSelected: {
root.rootStore.sendSticker(chatContentModule.getMyChatId(),
hashId,
chatInput.isReply ? chatInput.replyMessageId : "",
packId,
url)
}
onSendMessage: {
if (!chatContentModule) {
console.debug("error on sending message - chat content module is not set")
return
}
if(root.rootStore.sendMessage(event,
chatInput.textInput.text,
chatInput.isReply? chatInput.replyMessageId : "",
chatInput.fileUrls
))
{
Global.sendMessageSound.stop();
Qt.callLater(Global.sendMessageSound.play);
chatInput.textInput.clear();
chatInput.textInput.textFormat = TextEdit.PlainText;
chatInput.textInput.textFormat = TextEdit.RichText;
}
}
onUnblockChat: {
chatContentModule.unblockChat()
}
}
}
}
}