diff --git a/ui/app/AppLayouts/Chat/ChatLayout.qml b/ui/app/AppLayouts/Chat/ChatLayout.qml index f8dfd215d1..392bc3522c 100644 --- a/ui/app/AppLayouts/Chat/ChatLayout.qml +++ b/ui/app/AppLayouts/Chat/ChatLayout.qml @@ -86,7 +86,7 @@ StatusAppThreePanelLayout { showRightPanel: { // Check if user list is available as an option for particular chat content module. - let usersListAvailable = currentChatContentModule().isUsersListAvailable() + let usersListAvailable = currentChatContentModule().chatDetails.isUsersListAvailable return localAccountSensitiveSettings.showOnlineUsers && usersListAvailable && localAccountSensitiveSettings.expandUsersList } diff --git a/ui/app/AppLayouts/Chat/controls/activityCenter/ChannelBadge.qml b/ui/app/AppLayouts/Chat/controls/activityCenter/ChannelBadge.qml index 2527fd4b1b..d57c4c8d38 100644 --- a/ui/app/AppLayouts/Chat/controls/activityCenter/ChannelBadge.qml +++ b/ui/app/AppLayouts/Chat/controls/activityCenter/ChannelBadge.qml @@ -25,7 +25,7 @@ Item { width: 16 height: 16 fillMode: Image.PreserveAspectFit - source: Style.svg("channel-icon-" + (realChatType === Constants.chatTypePublic ? "public-chat" : "group")) + source: Style.svg("channel-icon-" + (realChatType === Constants.chatType.publicChat ? "public-chat" : "group")) anchors.left: parent.left anchors.verticalCenter:parent.verticalCenter } @@ -51,7 +51,7 @@ Item { StyledText { id: contactInfo - text: realChatType !== Constants.chatTypePublic ? + text: realChatType !== Constants.chatType.publicChat ? Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(name))) : "#" + Utils.filterXSS(name) anchors.left: contactImage.right diff --git a/ui/app/AppLayouts/Chat/panels/BadgeContentPanel.qml b/ui/app/AppLayouts/Chat/panels/BadgeContentPanel.qml index 047f5b4c0c..90c1521dcf 100644 --- a/ui/app/AppLayouts/Chat/panels/BadgeContentPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/BadgeContentPanel.qml @@ -20,14 +20,14 @@ Item { property bool hideSecondIcon: false property int chatType: chatsModel.channelView.chats.getChannelType(chatId) property int realChatType: { - if (chatType === Constants.chatTypeCommunity) { + if (chatType === Constants.chatType.communityChat) { // TODO add a check for private community chats once it is created - return Constants.chatTypePubliccommunityComponent + return Constants.chatType.publicChatcommunityComponent } return chatType } - property string profileImage: realChatType === Constants.chatTypeOneToOne ? appMain.getProfileImage(chatId) || "" : "" + property string profileImage: realChatType === Constants.chatType.oneToOne ? appMain.getProfileImage(chatId) || "" : "" height: 24 width: childrenRect.width @@ -161,7 +161,7 @@ Item { height: parent.height Connections { - enabled: realChatType === Constants.chatTypeOneToOne + enabled: realChatType === Constants.chatType.oneToOne // TODO use a store once it is available target: contactsModule.model.list onContactChanged: { @@ -176,7 +176,7 @@ Item { width: 16 height: 16 fillMode: Image.PreserveAspectFit - source: Style.svg("channel-icon-" + (wrapper.realChatType === Constants.chatTypePublic ? "public-chat" : "group")) + source: Style.svg("channel-icon-" + (wrapper.realChatType === Constants.chatType.publicChat ? "public-chat" : "group")) anchors.left: parent.left anchors.verticalCenter:parent.verticalCenter } @@ -202,7 +202,7 @@ Item { StyledText { id: contactInfo - text: wrapper.realChatType !== Constants.chatTypePublic ? + text: wrapper.realChatType !== Constants.chatType.publicChat ? Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(wrapper.name))) : "#" + Utils.filterXSS(wrapper.name) anchors.left: contactImage.right diff --git a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml index 92ede3b98f..86be960382 100644 --- a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml @@ -13,7 +13,7 @@ Item { anchors.fill: parent // Important: - // Each chat/community has its own ChatContentModule and each ChatContentModule has a single usersModule + // Each chat/channel has its own ChatContentModule and each ChatContentModule has a single usersModule // usersModule on the backend contains everything needed for this component property var usersModule property var messageContextMenu diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityUserListPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityUserListPanel.qml index af398ffe64..6387d27f7b 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityUserListPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityUserListPanel.qml @@ -16,7 +16,7 @@ Item { anchors.fill: parent // Important: - // Each chat/community has its own ChatContentModule and each ChatContentModule has a single usersModule + // Each chat/channel has its own ChatContentModule and each ChatContentModule has a single usersModule // usersModule on the backend contains everything needed for this component property var usersModule property var messageContextMenu diff --git a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml index 983b444b3a..0877d47e7c 100644 --- a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml @@ -22,10 +22,11 @@ ModalPopup { property var chatSectionModule property bool userCanPin: { switch (popup.rootStore.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypePublic: return false - case Constants.chatTypeOneToOne: return true - case Constants.chatTypePrivateGroupChat: return popup.rootStore.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) - case Constants.chatTypeCommunity: return popup.rootStore.chatsModelInst.communities.activeCommunity.admin + case Constants.chatType.publicChat: return false + case Constants.chatType.profile: return false + case Constants.chatType.oneToOne: return true + case Constants.chatType.privateGroupChat: return popup.rootStore.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) + case Constants.chatType.communityChat: return popup.rootStore.chatsModelInst.communities.activeCommunity.admin default: return false } } @@ -118,69 +119,69 @@ ModalPopup { MessageView { id: messageItem - rootStore: popup.rootStore - messageStore: popup.messageStore +// rootStore: popup.rootStore +// messageStore: popup.messageStore /////////////TODO Remove - fromAuthor: model.fromAuthor - chatId: model.chatId - userName: model.userName - alias: model.alias - localName: model.localName - message: model.message - plainText: model.plainText - identicon: model.identicon - isCurrentUser: model.isCurrentUser - timestamp: model.timestamp - sticker: model.sticker - contentType: model.contentType - outgoingStatus: model.outgoingStatus - responseTo: model.responseTo - imageClick: imagePopup.openPopup.bind(imagePopup) - messageId: model.messageId - emojiReactions: model.emojiReactions - linkUrls: model.linkUrls - communityId: model.communityId - hasMention: model.hasMention - stickerPackId: model.stickerPackId - timeout: model.timeout - pinnedMessage: true - pinnedBy: model.pinnedBy - forceHoverHandler: !messageToPin - activityCenterMessage: false - isEdited: model.isEdited - showEdit: false - messageContextMenu: msgContextMenu - Component.onCompleted: { - messageStore.fromAuthor = model.fromAuthor; - messageStore.chatId = model.chatId; - messageStore.userName = model.userName; - messageStore.alias = model.alias; - messageStore.localName = model.localName; - messageStore.message = model.message; - messageStore.plainText = model.plainText; - messageStore.identicon = model.identicon; - messageStore.isCurrentUser = model.isCurrentUser; - messageStore.timestamp = model.timestamp; - messageStore.sticker = model.sticker; - messageStore.contentType = model.contentType; - messageStore.outgoingStatus = model.outgoingStatus; - messageStore.responseTo = model.responseTo; - messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); - messageStore.messageId = model.messageId; - messageStore.emojiReactions = model.emojiReactions; - messageStore.linkUrls = model.linkUrls; - messageStore.communityId = model.communityId; - messageStore.hasMention = model.hasMention; - messageStore.stickerPackId = model.stickerPackId; - messageStore.timeout = model.timeout; - messageStore.pinnedMessage = true; - messageStore.pinnedBy = model.pinnedBy; - messageStore.forceHoverHandler = !messageToPin; - messageStore.activityCenterMessage = false; - messageStore.isEdited = model.isEdited; - messageStore.showEdit = false; - messageStore.messageContextMenu = msgContextMenu; - } +// fromAuthor: model.fromAuthor +// chatId: model.chatId +// userName: model.userName +// alias: model.alias +// localName: model.localName +// message: model.message +// plainText: model.plainText +// identicon: model.identicon +// isCurrentUser: model.isCurrentUser +// timestamp: model.timestamp +// sticker: model.sticker +// contentType: model.contentType +// outgoingStatus: model.outgoingStatus +// responseTo: model.responseTo +// imageClick: imagePopup.openPopup.bind(imagePopup) +// messageId: model.messageId +// emojiReactions: model.emojiReactions +// linkUrls: model.linkUrls +// communityId: model.communityId +// hasMention: model.hasMention +// stickerPackId: model.stickerPackId +// timeout: model.timeout +// pinnedMessage: true +// pinnedBy: model.pinnedBy +// forceHoverHandler: !messageToPin +// activityCenterMessage: false +// isEdited: model.isEdited +// showEdit: false +// messageContextMenu: msgContextMenu +// Component.onCompleted: { +// messageStore.fromAuthor = model.fromAuthor; +// messageStore.chatId = model.chatId; +// messageStore.userName = model.userName; +// messageStore.alias = model.alias; +// messageStore.localName = model.localName; +// messageStore.message = model.message; +// messageStore.plainText = model.plainText; +// messageStore.identicon = model.identicon; +// messageStore.isCurrentUser = model.isCurrentUser; +// messageStore.timestamp = model.timestamp; +// messageStore.sticker = model.sticker; +// messageStore.contentType = model.contentType; +// messageStore.outgoingStatus = model.outgoingStatus; +// messageStore.responseTo = model.responseTo; +// messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); +// messageStore.messageId = model.messageId; +// messageStore.emojiReactions = model.emojiReactions; +// messageStore.linkUrls = model.linkUrls; +// messageStore.communityId = model.communityId; +// messageStore.hasMention = model.hasMention; +// messageStore.stickerPackId = model.stickerPackId; +// messageStore.timeout = model.timeout; +// messageStore.pinnedMessage = true; +// messageStore.pinnedBy = model.pinnedBy; +// messageStore.forceHoverHandler = !messageToPin; +// messageStore.activityCenterMessage = false; +// messageStore.isEdited = model.isEdited; +// messageStore.showEdit = false; +// messageStore.messageContextMenu = msgContextMenu; +// } } MouseArea { diff --git a/ui/app/AppLayouts/Chat/stores/MessageStore.qml b/ui/app/AppLayouts/Chat/stores/MessageStore.qml new file mode 100644 index 0000000000..5c6e285a90 --- /dev/null +++ b/ui/app/AppLayouts/Chat/stores/MessageStore.qml @@ -0,0 +1,35 @@ +import QtQuick 2.13 + +QtObject { + id: root + + property var messageModule + + function getMessageByIdAsJson (id) { + if(!messageModule) + return false + + let jsonObj = messageModule.getMessageByIdAsJson(id) + let obj = JSON.parse(jsonObj) + if (obj.error) { + console.debug("error parsing message for index: ", id, " error: ", obj.error) + return false + } + + return obj + } + + function getMessageByIndexAsJson (index) { + if(!messageModule) + return false + + let jsonObj = messageModule.getMessageByIndexAsJson(index) + let obj = JSON.parse(jsonObj) + if (obj.error) { + console.debug("error parsing message for index: ", index, " error: ", obj.error) + return false + } + + return obj + } +} diff --git a/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml b/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml index f81782f4fb..15950593f1 100644 --- a/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml +++ b/ui/app/AppLayouts/Chat/views/ActivityCenterMessageComponentView.qml @@ -106,96 +106,96 @@ Item { MessageView { id: notificationMessage anchors.right: undefined - rootStore: root.store - messageStore: root.store.messageStore +// rootStore: root.store +// messageStore: root.store.messageStore //TODO Remove - fromAuthor: model.message.fromAuthor - chatId: model.message.chatId - userName: model.message.userName - alias: model.message.alias - localName: model.message.localName - message: model.message.message - plainText: model.message.plainText - identicon: model.message.identicon - isCurrentUser: model.message.isCurrentUser - timestamp: model.message.timestamp - sticker: model.message.sticker - contentType: model.message.contentType - outgoingStatus: model.message.outgoingStatus - responseTo: model.message.responseTo - imageClick: imagePopup.openPopup.bind(imagePopup) - messageId: model.message.messageId - linkUrls: model.message.linkUrls - communityId: model.message.communityId - hasMention: model.message.hasMention - stickerPackId: model.message.stickerPackId - pinnedBy: model.message.pinnedBy - pinnedMessage: model.message.isPinned - activityCenterMessage: true - read: model.read - clickMessage: function (isProfileClick) { - if (isProfileClick) { - const pk = model.message.fromAuthor - const userProfileImage = appMain.getProfileImage(pk) - return openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) - } +// fromAuthor: model.message.fromAuthor +// chatId: model.message.chatId +// userName: model.message.userName +// alias: model.message.alias +// localName: model.message.localName +// message: model.message.message +// plainText: model.message.plainText +// identicon: model.message.identicon +// isCurrentUser: model.message.isCurrentUser +// timestamp: model.message.timestamp +// sticker: model.message.sticker +// contentType: model.message.contentType +// outgoingStatus: model.message.outgoingStatus +// responseTo: model.message.responseTo +// imageClick: imagePopup.openPopup.bind(imagePopup) +// messageId: model.message.messageId +// linkUrls: model.message.linkUrls +// communityId: model.message.communityId +// hasMention: model.message.hasMention +// stickerPackId: model.message.stickerPackId +// pinnedBy: model.message.pinnedBy +// pinnedMessage: model.message.isPinned +// activityCenterMessage: true +// read: model.read +// clickMessage: function (isProfileClick) { +// if (isProfileClick) { +// const pk = model.message.fromAuthor +// const userProfileImage = appMain.getProfileImage(pk) +// return openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) +// } - activityCenter.close() +// activityCenter.close() - if (model.message.communityId) { - root.store.chatsModelInst.communities.setActiveCommunity(model.message.communityId) - } +// if (model.message.communityId) { +// root.store.chatsModelInst.communities.setActiveCommunity(model.message.communityId) +// } - root.store.chatsModelInst.channelView.setActiveChannel(model.message.chatId) - positionAtMessage(model.message.messageId) - } +// root.store.chatsModelInst.channelView.setActiveChannel(model.message.chatId) +// positionAtMessage(model.message.messageId) +// } - prevMessageIndex: previousNotificationIndex - prevMsgTimestamp: previousNotificationTimestamp - Component.onCompleted: { - messageStore.activityCenterMessage = true; - messageStore.fromAuthor = model.message.fromAuthor; - messageStore.chatId = model.message.chatId; - messageStore.userName = model.message.userName; - messageStore.alias = model.message.alias; - messageStore.localName = model.message.localName; - messageStore.message = model.message.message; - messageStore.plainText = model.message.plainText; - messageStore.identicon = model.message.identicon; - messageStore.isCurrentUser = model.message.isCurrentUser; - messageStore.timestamp = model.message.timestamp; - messageStore.sticker = model.message.sticker; - messageStore.contentType = model.message.contentType; - messageStore.outgoingStatus = model.message.outgoingStatus; - messageStore.responseTo = model.message.responseTo; - messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); - messageStore.messageId = model.message.messageId; - messageStore.linkUrls = model.message.linkUrls; - messageStore.communityId = model.message.communityId; - messageStore.hasMention = model.message.hasMention; - messageStore.stickerPackId = model.message.stickerPackId; - messageStore.pinnedBy = model.message.pinnedBy; - messageStore.pinnedMessage = model.message.isPinned; - messageStore.read = model.read; - messageStore.prevMessageIndex = previousNotificationIndex; - messageStore.prevMsgTimestamp = previousNotificationTimestamp; - messageStore.clickMessage = function (isProfileClick) { - if (isProfileClick) { - const pk = model.message.fromAuthor - const userProfileImage = appMain.getProfileImage(pk) - return openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) - } +// prevMessageIndex: previousNotificationIndex +// prevMsgTimestamp: previousNotificationTimestamp +// Component.onCompleted: { +// messageStore.activityCenterMessage = true; +// messageStore.fromAuthor = model.message.fromAuthor; +// messageStore.chatId = model.message.chatId; +// messageStore.userName = model.message.userName; +// messageStore.alias = model.message.alias; +// messageStore.localName = model.message.localName; +// messageStore.message = model.message.message; +// messageStore.plainText = model.message.plainText; +// messageStore.identicon = model.message.identicon; +// messageStore.isCurrentUser = model.message.isCurrentUser; +// messageStore.timestamp = model.message.timestamp; +// messageStore.sticker = model.message.sticker; +// messageStore.contentType = model.message.contentType; +// messageStore.outgoingStatus = model.message.outgoingStatus; +// messageStore.responseTo = model.message.responseTo; +// messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); +// messageStore.messageId = model.message.messageId; +// messageStore.linkUrls = model.message.linkUrls; +// messageStore.communityId = model.message.communityId; +// messageStore.hasMention = model.message.hasMention; +// messageStore.stickerPackId = model.message.stickerPackId; +// messageStore.pinnedBy = model.message.pinnedBy; +// messageStore.pinnedMessage = model.message.isPinned; +// messageStore.read = model.read; +// messageStore.prevMessageIndex = previousNotificationIndex; +// messageStore.prevMsgTimestamp = previousNotificationTimestamp; +// messageStore.clickMessage = function (isProfileClick) { +// if (isProfileClick) { +// const pk = model.message.fromAuthor +// const userProfileImage = appMain.getProfileImage(pk) +// return openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) +// } - activityCenter.close() +// activityCenter.close() - if (model.message.communityId) { - root.store.chatsModelInst.communities.setActiveCommunity(model.message.communityId) - } +// if (model.message.communityId) { +// root.store.chatsModelInst.communities.setActiveCommunity(model.message.communityId) +// } - root.store.chatsModelInst.channelView.setActiveChannel(model.message.chatId) - positionAtMessage(model.message.messageId) - } - } +// root.store.chatsModelInst.channelView.setActiveChannel(model.message.chatId) +// positionAtMessage(model.message.messageId) +// } +// } } Rectangle { @@ -239,13 +239,13 @@ Item { repliedMessageContent: replyMessageIndex > -1 ? root.store.chatsModelInst.messageView.getMessageData(chatId, replyMessageIndex, "message") : "" realChatType: { var chatType = root.store.chatsModelInst.channelView.chats.getChannelType(model.chatId) - if (chatType === Constants.chatTypeCommunity) { + if (chatType === Constants.chatType.communityChat) { // TODO add a check for private community chats once it is created - return Constants.chatTypePublic + return Constants.chatType.publicChat } return chatType } - profileImage: realChatType === Constants.chatTypeOneToOne ? appMain.getProfileImage(chatId) || "" : "" + profileImage: realChatType === Constants.chatType.oneToOne ? appMain.getProfileImage(chatId) || "" : "" channelName: root.store.chatsModelInst.getChannelNameById(badge.chatId) communityName: root.communityIndex > -1 ? root.store.chatsModelInst.communities.joinedCommunities.rowData(root.communityIndex, "name") : "" communityThumbnailImage: root.communityIndex > -1 ? root.store.chatsModelInst.communities.joinedCommunities.rowData(root.communityIndex, "thumbnailImage") : "" @@ -260,7 +260,7 @@ Item { } Connections { - enabled: badge.realChatType === Constants.chatTypeOneToOne + enabled: badge.realChatType === Constants.chatType.oneToOne target: root.store.allContacts onContactChanged: { if (pubkey === badge.chatId) { diff --git a/ui/app/AppLayouts/Chat/views/ChatColumnView.qml b/ui/app/AppLayouts/Chat/views/ChatColumnView.qml index 3080d62b46..dda9063cf0 100644 --- a/ui/app/AppLayouts/Chat/views/ChatColumnView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatColumnView.qml @@ -3,6 +3,7 @@ import Qt.labs.platform 1.1 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.13 import QtGraphicalEffects 1.0 +import Qt.labs.qmlmodels 1.0 import StatusQ.Core.Theme 0.1 import StatusQ.Components 0.1 @@ -26,20 +27,8 @@ Item { anchors.fill: parent // Important: we have parent module in this context only cause qml components - // don't follow struct from we have on the backend. + // don't follow struct we have on the backend. property var parentModule - // Since qml component doesn't follow encaptulation from the backend side, we're introducing - // a method which will return appropriate chat content module for selected chat/channel - function currentChatContentModule(){ - // When we decide to have the same struct as it's on the backend we will remove this function. - // So far this is a way to deal with refactord backend from the current qml structure. - if(parentModule.activeItem.isSubItemActive) - parentModule.prepareChatContentModuleForChatId(chatCommunitySectionModule.activeItem.activeSubItem.id) - else - parentModule.prepareChatContentModuleForChatId(chatCommunitySectionModule.activeItem.id) - - return parentModule.getChatContentModule() - } property var rootStore property alias pinnedMessagesPopupComponent: pinnedMessagesPopupComponent @@ -60,17 +49,14 @@ Item { property var idMap: ({}) property Timer timer: Timer { } property var userList -// property var onActivated: function () { -// if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) -// stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason) -// } signal openAppSearch() - function hideChatInputExtendedArea () { - if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) - stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.hideExtendedArea() - } + // Not Refactored Yet +// function hideChatInputExtendedArea () { +// if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) +// stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.hideExtendedArea() +// } function showReplyArea() { isReply = true; @@ -84,8 +70,9 @@ Item { let sticker = root.rootStore.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "sticker") let contentType = root.rootStore.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "contentType") - if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) - stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.showReplyArea(userName, message, identicon, contentType, image, sticker) + // Not Refactored Yet +// if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) +// stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.showReplyArea(userName, message, identicon, contentType, image, sticker) } function requestAddressForTransaction(address, amount, tokenAddress, tokenDecimals = 18) { @@ -117,7 +104,8 @@ Item { } function positionAtMessage(messageId, isSearch = false) { - stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].message.scrollToMessage(messageId, isSearch); + // Not Refactored Yet +// stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].message.scrollToMessage(messageId, isSearch); } Timer { @@ -154,293 +142,77 @@ Item { StackLayout { anchors.fill: parent - currentIndex: parentModule.model.count === 0? 0 : 1 + currentIndex: { + if(chatCommunitySectionModule.activeItem.id !== "") + { + for(let i = 1; i < this.children.length; i++) + { + var obj = this.children[i]; + if(obj && obj.chatContentModule) + { + let myChatId = obj.chatContentModule.getMyChatId() + if(myChatId == parentModule.activeItem.id || myChatId == parentModule.activeItem.activeSubItem.id) + return i + } + } + + // Should never be here, correct index must be returned from the `for` loop above + console.error("Wrong chat/channel index, active item id: ", parentModule.activeItem.id, + " active subitem id: ", parentModule.activeItem.activeSubItem.id) + } + + return 0 + } EmptyChatPanel { onShareChatKeyClicked: openProfilePopup(userProfile.name, userProfile.pubKey, userProfile.icon); } - ColumnLayout { - spacing: 0 + // This is kind of a solution for applying backend refactored changes with the minimal qml changes. + // The best would be if we made qml to follow the struct we have on the backend side. + Repeater { + model: parentModule.model + delegate: delegateChooser - StatusChatToolBar { - id: topBar - Layout.fillWidth: true - - property string chatId: root.rootStore.chatsModelInst.channelView.activeChannel.id - property string profileImage: appMain.getProfileImage(chatId) || "" - - chatInfoButton.title: Utils.removeStatusEns(root.rootStore.chatsModelInst.channelView.activeChannel.name) - chatInfoButton.subTitle: { - switch (root.rootStore.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypeOneToOne: - return (root.rootStore.contactsModuleInst.model.isAdded(topBar.chatId) ? - //% "Contact" - qsTrId("chat-is-a-contact") : - //% "Not a contact" - qsTrId("chat-is-not-a-contact")) - case Constants.chatTypePublic: - //% "Public chat" - return qsTrId("public-chat") - case Constants.chatTypePrivateGroupChat: - let cnt = root.rootStore.chatsModelInst.channelView.activeChannel.members.rowCount(); - //% "%1 members" - if(cnt > 1) return qsTrId("-1-members").arg(cnt); - //% "1 member" - return qsTrId("1-member"); - case Constants.chatTypeCommunity: - return Utils.linkifyAndXSS(root.rootStore.chatsModelInst.channelView.activeChannel.description).trim() - default: - return "" - } - } - chatInfoButton.image.source: profileImage || root.rootStore.chatsModelInst.channelView.activeChannel.identicon - chatInfoButton.image.isIdenticon: !!!profileImage && root.rootStore.chatsModelInst.channelView.activeChannel.identicon - chatInfoButton.icon.color: root.rootStore.chatsModelInst.channelView.activeChannel.color - chatInfoButton.type: root.rootStore.chatsModelInst.channelView.activeChannel.chatType - chatInfoButton.pinnedMessagesCount: root.rootStore.chatsModelInst.messageView.pinnedMessagesList.count - chatInfoButton.muted: root.rootStore.chatsModelInst.channelView.activeChannel.muted - - chatInfoButton.onPinnedMessagesCountClicked: Global.openPopup(pinnedMessagesPopupComponent) - chatInfoButton.onUnmute: root.rootStore.chatsModelInst.channelView.unmuteChatItem(chatsModel.channelView.activeChannel.id) - - chatInfoButton.sensor.enabled: root.rootStore.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatTypePublic && - root.rootStore.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatTypeCommunity - chatInfoButton.onClicked: { - switch (root.rootStore.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypePrivateGroupChat: - Global.openPopup(groupInfoPopupComponent, { - channelType: GroupInfoPopup.ChannelType.ActiveChannel, - channel: root.rootStore.chatsModelInst.channelView.activeChannel - }) - break; - case Constants.chatTypeOneToOne: - openProfilePopup(root.rootStore.chatsModelInst.userNameOrAlias(chatsModel.channelView.activeChannel.id), - root.rootStore.chatsModelInst.channelView.activeChannel.id, profileImage - || root.rootStore.chatsModelInst.channelView.activeChannel.identicon, - "", root.rootStore.chatsModelInst.channelView.activeChannel.nickname) - break; - } - } - - membersButton.visible: { - // Check if user list is available as an option for particular chat content module. - let usersListAvailable = currentChatContentModule().isUsersListAvailable() - return localAccountSensitiveSettings.showOnlineUsers && usersListAvailable - } - membersButton.highlighted: localAccountSensitiveSettings.expandUsersList - notificationButton.visible: localAccountSensitiveSettings.isActivityCenterEnabled - notificationButton.tooltip.offset: localAccountSensitiveSettings.expandUsersList ? 0 : 14 - notificationCount: root.rootStore.chatsModelInst.activityNotificationList.unreadCount - - onSearchButtonClicked: root.openAppSearch() - - onMembersButtonClicked: localAccountSensitiveSettings.expandUsersList = !localAccountSensitiveSettings.expandUsersList - onNotificationButtonClicked: activityCenter.open() - - popupMenu: ChatContextMenuView { - store: root.rootStore - chatSectionModule: parentModule - onOpened: { - chatItem = root.rootStore.chatsModelInst.channelView.activeChannel - } - } - } - - 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") - } - - Connections { - target: root.rootStore.chatsModelInst - onOnlineStatusChanged: { - if (connected == isConnected) return; - isConnected = connected; - if(isConnected){ - timer.setTimeout(function(){ - connectedStatusRect.visible = false; - }, 5000); - } else { - connectedStatusRect.visible = true; - } - } - } - Component.onCompleted: { - isConnected = root.rootStore.chatsModelInst.isOnline - if(!isConnected){ - connectedStatusRect.visible = true - } - } - } - - // Blocked User Status Bar - StatusBanner { - id: blockedUsrBar - width: parent.width - visible: isBlocked - type: StatusBanner.Type.Danger - statusText: qsTr("Blocked") - } - - StackLayout { - id: stackLayoutChatMessages - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - currentIndex: root.rootStore.chatsModelInst.messageView.getMessageListIndex(root.rootStore.chatsModelInst.channelView.activeChannelIndex) - Repeater { - model: root.rootStore.chatsModelInst.messageView - ColumnLayout { - property alias chatInput: chatInput - property alias message: messageLoader.item - Loader { - id: messageLoader - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom - Layout.fillWidth: true - Layout.fillHeight: true - Layout.preferredWidth: parent.width - - active: stackLayoutChatMessages.currentIndex === index - sourceComponent: ChatMessagesView { - id: chatMessages - store: root.rootStore - messageList: messages - messageContextMenuInst: contextmenu - Component.onCompleted: { - root.userList = chatMessages.messageList.userList; - } - } - } - Item { - id: inputArea - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom - Layout.fillWidth: true - Layout.preferredWidth: parent.width - height: chatInput.height - Layout.preferredHeight: height - - Loader { - id: loadingMessagesIndicator - active: root.rootStore.chatsModelInst.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 (root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypePrivateGroupChat) { - return root.rootStore.chatsModelInst.channelView.activeChannel.isMember - } - if (root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) { - return isContact - } - const community = root.rootStore.chatsModelInst.communities.activeCommunity - return !community.active || - community.access === Constants.communityChatPublicAccess || - community.admin || - root.rootStore.chatsModelInst.channelView.activeChannel.canPost - } - isContactBlocked: 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: root.rootStore.stickersModuleInst.recent - stickerPackList: root.rootStore.stickersModuleInst.stickerPacks - chatType: root.rootStore.chatsModelInst.channelView.activeChannel.chatType - onSendTransactionCommandButtonClicked: { - if (root.rootStore.chatsModelInst.channelView.activeChannel.ensVerified) { - txModalLoader.sourceComponent = cmpSendTransactionWithEns - } else { - txModalLoader.sourceComponent = cmpSendTransactionNoEns - } - txModalLoader.item.open() - } - onReceiveTransactionCommandButtonClicked: { - txModalLoader.sourceComponent = cmpReceiveTransaction - txModalLoader.item.open() - } - onStickerSelected: { - root.rootStore.stickersModuleInst.send(root.rootStore.chatsModelInst.channelView.activeChannel.id, - hashId, - chatInput.isReply ? SelectedMessage.messageId : "", - packId) - } - onSendMessage: { - if (chatInput.fileUrls.length > 0) { - let inputAreaModule = parentModule.getChatContentModule.getInputAreaModule() - inputAreaModule.sendImages(JSON.stringify(fileUrls)); - return - } - let msg = root.rootStore.chatsModelInst.plainText(Emoji.deparse(chatInput.textInput.text)) - if (msg.length > 0){ - msg = chatInput.interpretMessage(msg) - root.rootStore.chatsModelInst.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false); - if(event) event.accepted = true - sendMessageSound.stop(); - Qt.callLater(sendMessageSound.play); - - chatInput.textInput.clear(); - chatInput.textInput.textFormat = TextEdit.PlainText; - chatInput.textInput.textFormat = TextEdit.RichText; - } - } - } - } - Connections { - target: root.rootStore.chatsModelInst.channelView - onActiveChannelChanged: { - isBlocked = root.rootStore.contactsModuleInst.model.isContactBlocked(activeChatId); - chatInput.suggestions.hide(); - if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) - stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason) + DelegateChooser { + id: delegateChooser + role: "type" + DelegateChoice { // In case of category + roleValue: Constants.chatType.unknown + delegate: Repeater { + model: subItems + delegate: ChatContentView { + Component.onCompleted: { + parentModule.prepareChatContentModuleForChatId(model.itemId) + chatContentModule = parentModule.getChatContentModule() } } } } - } - - ChatRequestMessagePanel { - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom - Layout.fillWidth: true - Layout.bottomMargin: Style.current.bigPadding - isContact: root.isContact - visible: root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne - && (!root.isContact /*|| !contactRequestReceived*/) - onAddContactClicked: { - root.rootStore.addContact(activeChatId); + DelegateChoice { // In all other cases + delegate: ChatContentView { + Component.onCompleted: { + parentModule.prepareChatContentModuleForChatId(itemId) + chatContentModule = parentModule.getChatContentModule() + } + } } } } } + ChatRequestMessagePanel { + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.fillWidth: true + Layout.bottomMargin: Style.current.bigPadding + isContact: root.isContact + visible: root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne + && (!root.isContact /*|| !contactRequestReceived*/) + onAddContactClicked: { + root.rootStore.addContact(activeChatId); + } + } + Loader { id: txModalLoader function close() { @@ -540,8 +312,8 @@ Item { ActivityCenterPopup { id: activityCenter - height: root.height - (topBar.height * 2) // TODO get screen size - y: topBar.height + height: root.height - 56 * 2 // TODO get screen size // Taken from old code top bar height was fixed there to 56 + y: 56 store: root.rootStore } @@ -556,6 +328,7 @@ Item { Connections { target: root.rootStore.chatsModelInst.channelView onActiveChannelChanged: { + root.rootStore.chatsModelInst.messageView.hideLoadingIndicator() SelectedMessage.reset(); chatColumn.isReply = false; } @@ -600,19 +373,19 @@ Item { let name; if (localAccountSensitiveSettings.notificationMessagePreviewSetting === Constants.notificationPreviewAnonymous) { name = "Status" - } else if (chatType === Constants.chatTypePublic) { + } else if (chatType === Constants.chatType.publicChat) { name = chatId } else { - name = chatType === Constants.chatTypePrivateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username) + name = chatType === Constants.chatType.privateGroupChat ? Utils.filterXSS(channelName) : Utils.removeStatusEns(username) } let message; if (localAccountSensitiveSettings.notificationMessagePreviewSetting > Constants.notificationPreviewNameOnly) { switch(contentType){ //% "Image" - case Constants.imageType: message = qsTrId("image"); break + case Constants.messageContentType.imageType: message = qsTrId("image"); break //% "Sticker" - case Constants.stickerType: message = qsTrId("sticker"); break + case Constants.messageContentType.stickerType: message = qsTrId("sticker"); break default: message = msg // don't parse emojis here as it emits HTML } } else { @@ -641,11 +414,6 @@ Item { } } - Component.onCompleted: { - if(stackLayoutChatMessages.currentIndex >= 0 && stackLayoutChatMessages.currentIndex < stackLayoutChatMessages.children.length) - stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].chatInput.textInput.forceActiveFocus(Qt.MouseFocusReason) - } - Connections { target: root.rootStore.chatsModelInst.stickers onTransactionWasSent: { diff --git a/ui/app/AppLayouts/Chat/views/ChatContentView.qml b/ui/app/AppLayouts/Chat/views/ChatContentView.qml new file mode 100644 index 0000000000..1733811fcc --- /dev/null +++ b/ui/app/AppLayouts/Chat/views/ChatContentView.qml @@ -0,0 +1,303 @@ +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.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: chatContentRoot + spacing: 0 + + // Important: + // Each chat/channel has its own ChatContentModule + property var chatContentModule + + StatusChatToolBar { + id: topBar + Layout.fillWidth: true + + chatInfoButton.title: chatContentModule.chatDetails.name + chatInfoButton.subTitle: { + // In some moment in future this should be part of the backend logic. + // (once we add transaltion on the backend side) + switch (chatContentModule.chatDetails.type) { + case Constants.chatType.oneToOne: + return (chatContentModule.isMyContact(chatContentModule.chatDetails.id) ? + //% "Contact" + qsTrId("chat-is-a-contact") : + //% "Not a contact" + qsTrId("chat-is-not-a-contact")) + case Constants.chatType.publicChat: + //% "Public chat" + return qsTrId("public-chat") + case Constants.chatType.privateGroupChat: + let cnt = chatContentModule.usersModule.model.count + //% "%1 members" + if(cnt > 1) return qsTrId("-1-members").arg(cnt); + //% "1 member" + return qsTrId("1-member"); + case Constants.chatType.communityChat: + return Utils.linkifyAndXSS(chatContentModule.chatDetails.description).trim() + default: + return "" + } + } + chatInfoButton.image.source: chatContentModule.chatDetails.icon + chatInfoButton.image.isIdenticon: chatContentModule.chatDetails.isIdenticon + chatInfoButton.icon.color: chatContentModule.chatDetails.color + chatInfoButton.type: chatContentModule.chatDetails.type + chatInfoButton.pinnedMessagesCount: chatContentModule.pinnedMessagesModel.count + chatInfoButton.muted: chatContentModule.chatDetails.muted + + chatInfoButton.onPinnedMessagesCountClicked: openPopup(pinnedMessagesPopupComponent) + chatInfoButton.onUnmute: chatContentModule.unmuteChat() + + chatInfoButton.sensor.enabled: chatContentModule.chatDetails.type !== Constants.chatType.publicChat && + chatContentModule.chatDetails.type !== Constants.chatType.communityChat + chatInfoButton.onClicked: { + // Not Refactored Yet +// switch (root.rootStore.chatsModelInst.channelView.activeChannel.chatType) { +// case Constants.chatType.privateGroupChat: +// openPopup(groupInfoPopupComponent, { +// channelType: GroupInfoPopup.ChannelType.ActiveChannel, +// channel: root.rootStore.chatsModelInst.channelView.activeChannel +// }) +// break; +// case Constants.chatType.oneToOne: +// openProfilePopup(root.rootStore.chatsModelInst.userNameOrAlias(chatsModel.channelView.activeChannel.id), +// root.rootStore.chatsModelInst.channelView.activeChannel.id, profileImage +// || root.rootStore.chatsModelInst.channelView.activeChannel.identicon, +// "", root.rootStore.chatsModelInst.channelView.activeChannel.nickname) +// break; +// } + } + + membersButton.visible: localAccountSensitiveSettings.showOnlineUsers && chatContentModule.chatDetails.isUsersListAvailable + membersButton.highlighted: localAccountSensitiveSettings.expandUsersList + notificationButton.visible: localAccountSensitiveSettings.isActivityCenterEnabled + notificationButton.tooltip.offset: localAccountSensitiveSettings.expandUsersList ? 0 : 14 + + notificationCount: chatContentModule.chatDetails.notificationCount + + onSearchButtonClicked: root.openAppSearch() + + onMembersButtonClicked: localAccountSensitiveSettings.expandUsersList = !localAccountSensitiveSettings.expandUsersList + onNotificationButtonClicked: activityCenter.open() + + popupMenu: ChatContextMenuView { + isCommunityChat: chatContentModule.chatDetails.belongsToCommunity + chatId: chatContentModule.chatDetails.id + chatName: chatContentModule.chatDetails.name + chatType: chatContentModule.chatDetails.type + chatMuted: chatContentModule.chatDetails.muted + + // TODO + //currentFleet + } + } + + 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") + } + + // Not Refactored Yet +// Connections { +// target: root.rootStore.chatsModelInst +// onOnlineStatusChanged: { +// if (connected == isConnected) return; +// isConnected = connected; +// if(isConnected){ +// timer.setTimeout(function(){ +// connectedStatusRect.visible = false; +// }, 5000); +// } else { +// connectedStatusRect.visible = true; +// } +// } +// } +// Component.onCompleted: { +// isConnected = root.rootStore.chatsModelInst.isOnline +// if(!isConnected){ +// connectedStatusRect.visible = true +// } +// } + } + + Item { + Layout.fillWidth: true + Layout.preferredHeight: 40 + Layout.alignment: Qt.AlignHCenter + visible: isBlocked + + Rectangle { + id: blockedBanner + anchors.fill: parent + color: Style.current.red + opacity: 0.1 + } + + Text { + id: blockedText + anchors.centerIn: blockedBanner + color: Style.current.red + text: qsTr("Blocked") + } + } + + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + + ChatMessagesView { + id: chatMessages + Layout.fillWidth: true + Layout.fillHeight: true + store: root.rootStore + messageContextMenuInst: contextmenu + messageStore: MessageStore{ + messageModule: chatContentModule.messagesModule + } + } + + Item { + id: inputArea + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.fillWidth: true + Layout.preferredWidth: parent.width + height: chatInput.height + Layout.preferredHeight: height + + // Not Refactored Yet +// Connections { +// target: root.rootStore.chatsModelInst.messageView +// onLoadingMessagesChanged: +// if(value){ +// loadingMessagesIndicator.active = true +// } else { +// timer.setTimeout(function(){ +// loadingMessagesIndicator.active = false; +// }, 5000); +// } +// } + + // Not Refactored Yet +// Loader { +// id: loadingMessagesIndicator +// active: root.rootStore.chatsModelInst.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: { + // Not Refactored Yet + return true + // if (root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.privateGroupChat) { + // return root.rootStore.chatsModelInst.channelView.activeChannel.isMember + // } + // if (root.rootStore.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne) { + // return isContact + // } + // const community = root.rootStore.chatsModelInst.communities.activeCommunity + // return !community.active || + // community.access === Constants.communityChatPublicAccess || + // community.admin || + // root.rootStore.chatsModelInst.channelView.activeChannel.canPost + } + isContactBlocked: 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: root.rootStore.stickersModuleInst.recent + stickerPackList: root.rootStore.stickersModuleInst.stickerPacks + chatType: root.rootStore.chatsModelInst.channelView.activeChannel.chatType + onSendTransactionCommandButtonClicked: { + // Not Refactored Yet + // if (root.rootStore.chatsModelInst.channelView.activeChannel.ensVerified) { + // txModalLoader.sourceComponent = cmpSendTransactionWithEns + // } else { + // txModalLoader.sourceComponent = cmpSendTransactionNoEns + // } + // txModalLoader.item.open() + } + onReceiveTransactionCommandButtonClicked: { + // Not Refactored Yet + // txModalLoader.sourceComponent = cmpReceiveTransaction + // txModalLoader.item.open() + } + onStickerSelected: { + // Not Refactored Yet + // root.rootStore.stickersModuleInst.send(root.rootStore.chatsModelInst.channelView.activeChannel.id, + // hashId, + // chatInput.isReply ? SelectedMessage.messageId : "", + // packId) + } + onSendMessage: { + // Not Refactored Yet + // if (chatInput.fileUrls.length > 0){ + // root.rootStore.chatsModelInst.sendImages(JSON.stringify(fileUrls)); + // } + // let msg = root.rootStore.chatsModelInst.plainText(Emoji.deparse(chatInput.textInput.text)) + // if (msg.length > 0){ + // msg = chatInput.interpretMessage(msg) + // root.rootStore.chatsModelInst.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.messageContentType.emojiType : Constants.messageContentType.messageType, false); + // if(event) event.accepted = true + // sendMessageSound.stop(); + // Qt.callLater(sendMessageSound.play); + + // chatInput.textInput.clear(); + // chatInput.textInput.textFormat = TextEdit.PlainText; + // chatInput.textInput.textFormat = TextEdit.RichText; + // } + } + } + } + } +} diff --git a/ui/app/AppLayouts/Chat/views/ChatContextMenuView.qml b/ui/app/AppLayouts/Chat/views/ChatContextMenuView.qml index 01e7eca3e4..38933d2a43 100644 --- a/ui/app/AppLayouts/Chat/views/ChatContextMenuView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatContextMenuView.qml @@ -11,48 +11,61 @@ import "../popups" StatusPopupMenu { id: root - property var chatItem - property var store - property var chatSectionModule - // Not Refactored Yet - property bool communityActive: false // root.store.chatsModelInst.communities.activeCommunity.active + + property string currentFleet: "" + property bool isCommunityChat: false + property bool isCommunityAdmin: false + property string chatId: "" + property string chatName: "" + property string chatIcon: "" + property int chatType: -1 + property bool chatMuted: false + + signal viewGroupOrProfile(string id) + signal requestAllHistoricMessages(string id) + signal unmuteChat(string id) + signal muteChat(string id) + signal markAsRead(string id) + signal clearChatHistory(string id) + signal editChannel(string id) + signal downloadMessages(string file) + signal deleteChat(string id) StatusMenuItem { id: viewProfileMenuItem text: { - if (chatItem) { - switch (chatItem.chatType) { - case Constants.chatTypeOneToOne: - //% "View Profile" - return qsTrId("view-profile") - case Constants.chatTypePrivateGroupChat: - //% "View Group" - return qsTrId("view-group") - } + switch (root.chatType) { + case Constants.chatType.oneToOne: + //% "View Profile" + return qsTrId("view-profile") + case Constants.chatType.privateGroupChat: + //% "View Group" + return qsTrId("view-group") + default: + return "" } - return "" } icon.name: "group-chat" - enabled: chatItem && - (chatItem.chatType === Constants.chatTypeOneToOne || - chatItem.chatType === Constants.chatTypePrivateGroupChat) + enabled: root.chatType === Constants.chatType.oneToOne || + root.chatType === Constants.chatType.privateGroupChat onTriggered: { - if (chatItem.chatType === Constants.chatTypeOneToOne) { - const userProfileImage = appMain.getProfileImage(chatItem.id) + if (root.chatType === Constants.chatType.oneToOne) { + const userProfileImage = appMain.getProfileImage(root.chatId) return openProfilePopup( - chatItem.name, - chatItem.id, - userProfileImage || chatItem.identicon, + root.chatName, + root.chatId, + root.chatIcon, "", - chatItem.name + root.chatName ) } - if (chatItem.chatType === Constants.chatTypePrivateGroupChat) { - return Global.openPopup(groupInfoPopupComponent, { - channel: chatItem, - channelType: GroupInfoPopup.ChannelType.ContextChannel - }) - } + // Not Refactored Yet +// if (root.chatType === Constants.chatType.privateGroupChat) { +// return Global.openPopup(groupInfoPopupComponent, { +// channel: chatItem, +// channelType: GroupInfoPopup.ChannelType.ContextChannel +// }) +// } } } @@ -60,27 +73,36 @@ StatusPopupMenu { visible: viewProfileMenuItem.enabled } - Action { - enabled: root.store.profileModelInst.fleets.fleet == Constants.waku_prod || root.store.profileModelInst.fleets.fleet === Constants.waku_test + enabled: root.currentFleet + + // Will be deleted later +// enabled: root.store.profileModelInst.fleets.fleet == Constants.waku_prod || +// root.store.profileModelInst.fleets.fleet === Constants.waku_test + //% "Test WakuV2 - requestAllHistoricMessages" text: qsTrId("test-wakuv2---requestallhistoricmessages") - onTriggered: root.store.chatsModelInst.requestAllHistoricMessages() + onTriggered: { + root.requestAllHistoricMessages(root.chatId) + } + + // Will be deleted later + //onTriggered: root.store.chatsModelInst.requestAllHistoricMessages() } StatusMenuItem { - text: chatItem && chatItem.muted ? + text: root.chatMuted ? //% "Unmute chat" qsTrId("unmute-chat") : //% "Mute chat" qsTrId("mute-chat") icon.name: "notification" - enabled: chatItem && chatItem.chatType !== Constants.chatTypePrivateGroupChat + enabled: root.chatType !== Constants.chatType.privateGroupChat onTriggered: { - if (chatItem && chatItem.muted) { - return root.store.chatsModelInst.channelView.unmuteChatItem(chatItem.id) - } - root.store.chatsModelInst.channelView.muteChatItem(chatItem.id) + if(root.chatMuted) + root.unmuteChat(root.chatId) + else + root.muteChat(root.chatId) } } @@ -88,15 +110,25 @@ StatusPopupMenu { //% "Mark as Read" text: qsTrId("mark-as-read") icon.name: "checkmark-circle" - enabled: chatItem && chatItem.chatType !== Constants.chatTypePrivateGroupChat - onTriggered: root.store.chatsModelInst.channelView.markChatItemAsRead(chatItem.id) + enabled: root.chatType !== Constants.chatType.privateGroupChat + onTriggered: { + root.markAsRead(root.chatId) + } + + // Will be deleted later + //onTriggered: root.store.chatsModelInst.channelView.markChatItemAsRead(chatItem.id) } StatusMenuItem { //% "Clear history" text: qsTrId("clear-history") icon.name: "close-circle" - onTriggered: root.store.chatsModelInst.channelView.clearChatHistory(chatItem.id) + onTriggered: { + root.clearChatHistory(root.chatId) + } + + // Will be deleted later + //onTriggered: root.store.chatsModelInst.channelView.clearChatHistory(chatItem.id) } StatusMenuItem { @@ -105,11 +137,12 @@ StatusPopupMenu { icon.name: "edit" enabled: communityActive && root.store.chatsModelInst.communities.activeCommunity.admin - onTriggered: Global.openPopup(editChannelPopup, { - store: root.store, - communityId: root.store.chatsModelInst.communities.activeCommunity.id, - channel: chatItem - }) + // Not Refactored Yet +// onTriggered: Global.openPopup(editChannelPopup, { +// store: root.store, +// communityId: root.store.chatsModelInst.communities.activeCommunity.id, +// channel: chatItem +// }) } StatusMenuItem { @@ -126,25 +159,28 @@ StatusPopupMenu { StatusMenuItem { id: deleteOrLeaveMenuItem text: { - if (communityActive) { + if (isCommunityChat) { return qsTr("Delete Channel") } - return chatItem && chatItem.chatType === Constants.chatTypeOneToOne ? + return root.chatType === Constants.chatType.oneToOne ? //% "Delete chat" qsTrId("delete-chat") : //% "Leave chat" qsTrId("leave-chat") } - icon.name: chatItem && chatItem.chatType === Constants.chatTypeOneToOne || communityActive ? "delete" : "arrow-right" - icon.width: chatItem && chatItem.chatType === Constants.chatTypeOneToOne || communityActive ? 18 : 14 - iconRotation: chatItem && chatItem.chatType === Constants.chatTypeOneToOne || communityActive ? 0 : 180 + icon.name: root.chatType === Constants.chatType.oneToOne || isCommunityChat ? "delete" : "arrow-right" + icon.width: root.chatType === Constants.chatType.oneToOne || isCommunityChat ? 18 : 14 + iconRotation: root.chatType === Constants.chatType.oneToOne || isCommunityChat ? 0 : 180 type: StatusMenuItem.Type.Danger onTriggered: { Global.openPopup(deleteChatConfirmationDialogComponent) } - enabled: !communityActive || root.store.chatsModelInst.communities.activeCommunity.admin + enabled: !isCommunityChat || isCommunityAdmin + + // Will be deleted later +// enabled: !communityActive || root.store.chatsModelInst.communities.activeCommunity.admin } FileDialog { @@ -154,28 +190,33 @@ StatusPopupMenu { title: qsTr("Download messages") currentFile: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) + "/messages.json" defaultSuffix: "json" + onAccepted: { - root.store.chatsModelInst.messageView.downloadMessages(downdloadDialog.currentFile) + root.downloadMessages(downdloadDialog.currentFile) } + + // Will be deleted later +// onAccepted: { +// root.store.chatsModelInst.messageView.downloadMessages(downdloadDialog.currentFile) +// } } Component { id: deleteChatConfirmationDialogComponent ConfirmationDialog { - property string chatId: !!chatItem ? chatItem.id : "" btnType: "warn" - header.title: communityActive && chatItem ? qsTr("Delete #%1").arg(chatItem.name) : - chatItem && chatItem.chatType === Constants.chatTypeOneToOne ? + header.title: isCommunityChat ? qsTr("Delete #%1").arg(root.chatName) : + root.chatType === Constants.chatType.oneToOne ? //% "Delete chat" qsTrId("delete-chat") : //% "Leave chat" qsTrId("leave-chat") - confirmButtonLabel: communityActive ? qsTr("Delete") : header.title - confirmationText: communityActive && chatItem ? qsTr("Are you sure you want to delete #%1 channel?").arg(chatItem.name) : - chatItem && chatItem.chatType === Constants.chatTypeOneToOne ? + confirmButtonLabel: isCommunityChat ? qsTr("Delete") : header.title + confirmationText: isCommunityChat ? qsTr("Are you sure you want to delete #%1 channel?").arg(root.chatName) : + root.chatType === Constants.chatType.oneToOne ? qsTr("Are you sure you want to delete this chat?"): qsTr("Are you sure you want to leave this chat?") - showCancelButton: communityActive + showCancelButton: isCommunityChat onClosed: { destroy() @@ -184,13 +225,18 @@ StatusPopupMenu { close() } onConfirmButtonClicked: { - if (communityActive) { - root.store.chatsModelInst.communities.deleteCommunityChat(root.store.chatsModelInst.communities.activeCommunity.id, chatId) - } else { - chatSectionModule.leaveChat(chatId) - } - close(); + root.deleteChat(root.chatId) } + + // Will be deleted later +// onConfirmButtonClicked: { +// if (communityActive) { +// root.store.chatsModelInst.communities.deleteCommunityChat(root.store.chatsModelInst.communities.activeCommunity.id, chatId) +// } else { +// root.store.chatsModelInst.channelView.leaveChat(chatId) +// } +// close(); +// } } } } diff --git a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml index ac3c68048b..24b42d3b55 100644 --- a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml @@ -16,20 +16,18 @@ import shared.controls 1.0 import shared.views.chat 1.0 import "../controls" -//TODO REMOVE -import "../stores" Item { id: root - anchors.fill: parent + //anchors.fill: parent property var store + property var messageStore property alias chatLogView: chatLogView property alias scrollToMessage: chatLogView.scrollToMessage property var messageContextMenuInst - property var messageList: MessagesData {} property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight property int newMessages: 0 @@ -64,238 +62,245 @@ Item { } property var scrollToMessage: function (messageId, isSearch = false) { - delayPositioningViewTimer.msgId = messageId; - delayPositioningViewTimer.isSearch = isSearch; - delayPositioningViewTimer.restart(); + // Not Refactored Yet +// delayPositioningViewTimer.msgId = messageId; +// delayPositioningViewTimer.isSearch = isSearch; +// delayPositioningViewTimer.restart(); } - Timer { - id: delayPositioningViewTimer - interval: 1000 - property string msgId - property bool isSearch - onTriggered: { - let item - for (let i = 0; i < messages.rowCount(); i++) { - item = messageListDelegate.items.get(i); - if (item.model.messageId === msgId) { - chatLogView.positionViewAtIndex(i, ListView.Beginning); - if (localAccountSensitiveSettings.useCompactMode && isSearch) { - chatLogView.itemAtIndex(i).startMessageFoundAnimation(); - } - } - } - msgId = ""; - isSearch = false; - } - } +// Timer { +// id: delayPositioningViewTimer +// interval: 1000 +// property string msgId +// property bool isSearch +// onTriggered: { +// let item +// for (let i = 0; i < messages.rowCount(); i++) { +// item = messageListDelegate.items.get(i); +// if (item.model.messageId === msgId) { +// chatLogView.positionViewAtIndex(i, ListView.Beginning); +// if (localAccountSensitiveSettings.useCompactMode && isSearch) { +// chatLogView.itemAtIndex(i).startMessageFoundAnimation(); +// } +// } +// } +// msgId = ""; +// isSearch = false; +// } +// } - ScrollBar.vertical: ScrollBar { - visible: chatLogView.visibleArea.heightRatio < 1 - } +// ScrollBar.vertical: ScrollBar { +// visible: chatLogView.visibleArea.heightRatio < 1 +// } - Connections { - id: contentHeightConnection - enabled: true - target: chatLogView - onContentHeightChanged: { - chatLogView.checkHeaderHeight() - } - onHeightChanged: { - chatLogView.checkHeaderHeight() - } - } +// Connections { +// id: contentHeightConnection +// enabled: true +// target: chatLogView +// onContentHeightChanged: { +// chatLogView.checkHeaderHeight() +// } +// onHeightChanged: { +// chatLogView.checkHeaderHeight() +// } +// } Timer { id: timer } - Button { - readonly property int buttonPadding: 5 +// Button { +// readonly property int buttonPadding: 5 - id: scrollDownButton - visible: false - height: 32 - width: nbMessages.width + arrowImage.width + 2 * Style.current.halfPadding + (nbMessages.visible ? scrollDownButton.buttonPadding : 0) - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.rightMargin: Style.current.padding - background: Rectangle { - color: Style.current.buttonSecondaryColor - border.width: 0 - radius: 16 - } - onClicked: { - newMessages = 0 - scrollDownButton.visible = false - chatLogView.scrollToBottom(true) - } +// id: scrollDownButton +// visible: false +// height: 32 +// width: nbMessages.width + arrowImage.width + 2 * Style.current.halfPadding + (nbMessages.visible ? scrollDownButton.buttonPadding : 0) +// anchors.bottom: parent.bottom +// anchors.right: parent.right +// anchors.rightMargin: Style.current.padding +// background: Rectangle { +// color: Style.current.buttonSecondaryColor +// border.width: 0 +// radius: 16 +// } +// onClicked: { +// newMessages = 0 +// scrollDownButton.visible = false +// chatLogView.scrollToBottom(true) +// } - StyledText { - id: nbMessages - visible: newMessages > 0 - width: visible ? implicitWidth : 0 - text: newMessages - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - color: Style.current.pillButtonTextColor - font.pixelSize: 15 - anchors.leftMargin: Style.current.halfPadding - } +// StyledText { +// id: nbMessages +// visible: newMessages > 0 +// width: visible ? implicitWidth : 0 +// text: newMessages +// anchors.verticalCenter: parent.verticalCenter +// anchors.left: parent.left +// color: Style.current.pillButtonTextColor +// font.pixelSize: 15 +// anchors.leftMargin: Style.current.halfPadding +// } - SVGImage { - id: arrowImage - width: 24 - height: 24 - anchors.verticalCenter: parent.verticalCenter - anchors.left: nbMessages.right - source: Style.svg("leave_chat") - anchors.leftMargin: nbMessages.visible ? scrollDownButton.buttonPadding : 0 - rotation: -90 +// SVGImage { +// id: arrowImage +// width: 24 +// height: 24 +// anchors.verticalCenter: parent.verticalCenter +// anchors.left: nbMessages.right +// source: Style.svg("leave_chat") +// anchors.leftMargin: nbMessages.visible ? scrollDownButton.buttonPadding : 0 +// rotation: -90 - ColorOverlay { - anchors.fill: parent - source: parent - color: Style.current.pillButtonTextColor - } - } +// ColorOverlay { +// anchors.fill: parent +// source: parent +// color: Style.current.pillButtonTextColor +// } +// } - MouseArea { - cursorShape: Qt.PointingHandCursor - anchors.fill: parent - onPressed: mouse.accepted = false - } - } +// MouseArea { +// cursorShape: Qt.PointingHandCursor +// anchors.fill: parent +// onPressed: mouse.accepted = false +// } +// } function scrollToBottom(force, caller) { - if (!force && !chatLogView.atYEnd) { - // User has scrolled up, we don't want to scroll back - return false - } - if (caller && caller !== chatLogView.itemAtIndex(chatLogView.count - 1)) { - // If we have a caller, only accept its request if it's the last message - return false - } - // Call this twice and with a timer since the first scroll to bottom might have happened before some stuff loads - // meaning that the scroll will not actually be at the bottom on switch - // Add a small delay because images, even though they say they say they are loaed, they aren't shown yet - Qt.callLater(chatLogView.positionViewAtBeginning) - timer.setTimeout(function() { - Qt.callLater(chatLogView.positionViewAtBeginning) - }, 100); + // Not Refactored Yet +// if (!force && !chatLogView.atYEnd) { +// // User has scrolled up, we don't want to scroll back +// return false +// } +// if (caller && caller !== chatLogView.itemAtIndex(chatLogView.count - 1)) { +// // If we have a caller, only accept its request if it's the last message +// return false +// } +// // Call this twice and with a timer since the first scroll to bottom might have happened before some stuff loads +// // meaning that the scroll will not actually be at the bottom on switch +// // Add a small delay because images, even though they say they say they are loaed, they aren't shown yet +// Qt.callLater(chatLogView.positionViewAtBeginning) +// timer.setTimeout(function() { +// Qt.callLater(chatLogView.positionViewAtBeginning) +// }, 100); return true } - Connections { - target: root.store.chatsModelInst +// Connections { + // Not Refactored Yet +// target: root.store.chatsModelInst - onAppReady: { - chatLogView.scrollToBottom(true) - } - } +// onAppReady: { +// chatLogView.scrollToBottom(true) +// } +// } - Connections { - target: root.store.chatsModelInst.messageView +// Connections { + // Not Refactored Yet +// target: root.store.chatsModelInst.messageView - onSendingMessageSuccess: { - chatLogView.scrollToBottom(true) - } +// onSendingMessageSuccess: { +// chatLogView.scrollToBottom(true) +// } - onSendingMessageFailed: { - sendingMsgFailedPopup.open(); - } +// onSendingMessageFailed: { +// sendingMsgFailedPopup.open(); +// } - onNewMessagePushed: { - if (!chatLogView.scrollToBottom()) { - newMessages++ - } - } - } +// onNewMessagePushed: { +// if (!chatLogView.scrollToBottom()) { +// newMessages++ +// } +// } +// } - Connections { - target: root.store.chatsModelInst.communities +// Connections { + // Not Refactored Yet +// target: root.store.chatsModelInst.communities - // Note: - // Whole this Connection object (both slots) should be moved to the nim side. - // Left here only cause we don't have a way to deal with translations on the nim side. +// // Note: +// // Whole this Connection object (both slots) should be moved to the nim side. +// // Left here only cause we don't have a way to deal with translations on the nim side. - onMembershipRequestChanged: function (communityId, communityName, accepted) { - chatColumnLayout.currentNotificationChatId = null - chatColumnLayout.currentNotificationCommunityId = communityId +// onMembershipRequestChanged: function (communityId, communityName, accepted) { +// chatColumnLayout.currentNotificationChatId = null +// chatColumnLayout.currentNotificationCommunityId = communityId - const title = "Status" - const message = //% "You have been accepted into the ‘%1’ community" - accepted ? qsTrId("you-have-been-accepted-into-the---1--community").arg(communityName) : - //% "Your request to join the ‘%1’ community was declined" - qsTrId("your-request-to-join-the---1--community-was-declined").arg(communityName) +// const title = "Status" +// const message = //% "You have been accepted into the ‘%1’ community" +// accepted ? qsTrId("you-have-been-accepted-into-the---1--community").arg(communityName) : +// //% "Your request to join the ‘%1’ community was declined" +// qsTrId("your-request-to-join-the---1--community-was-declined").arg(communityName) - if (Qt.platform.os === "linux") { - // Linux Notifications are not implemented in Nim/C++ yet - return systemTray.showMessage(title, message, systemTray.icon.source, 4000) - } +// if (Qt.platform.os === "linux") { +// // Linux Notifications are not implemented in Nim/C++ yet +// return systemTray.showMessage(title, message, systemTray.icon.source, 4000) +// } - root.store.chatsModelInst.showOSNotification(title, - message, - accepted? Constants.osNotificationType.acceptedIntoCommunity : - Constants.osNotificationType.rejectedByCommunity, - communityId, - "", - "", - localAccountSensitiveSettings.useOSNotifications) - } +// root.store.chatsModelInst.showOSNotification(title, +// message, +// accepted? Constants.osNotificationType.acceptedIntoCommunity : +// Constants.osNotificationType.rejectedByCommunity, +// communityId, +// "", +// "", +// localAccountSensitiveSettings.useOSNotifications) +// } - onMembershipRequestPushed: function (communityId, communityName, pubKey) { - chatColumnLayout.currentNotificationChatId = null - chatColumnLayout.currentNotificationCommunityId = communityId +// onMembershipRequestPushed: function (communityId, communityName, pubKey) { +// chatColumnLayout.currentNotificationChatId = null +// chatColumnLayout.currentNotificationCommunityId = communityId - //% "New membership request" - const title = qsTrId("new-membership-request") - //% "%1 asks to join ‘%2’" - const message = qsTrId("-1-asks-to-join---2-").arg(Utils.getDisplayName(pubKey)).arg(communityName) +// //% "New membership request" +// const title = qsTrId("new-membership-request") +// //% "%1 asks to join ‘%2’" +// const message = qsTrId("-1-asks-to-join---2-").arg(Utils.getDisplayName(pubKey)).arg(communityName) - if (Qt.platform.os === "linux") { - // Linux Notifications are not implemented in Nim/C++ yet - return systemTray.showMessage(title, message, systemTray.icon.source, 4000) - } +// if (Qt.platform.os === "linux") { +// // Linux Notifications are not implemented in Nim/C++ yet +// return systemTray.showMessage(title, message, systemTray.icon.source, 4000) +// } - root.store.chatsModelInst.showOSNotification(title, - message, - Constants.osNotificationType.joinCommunityRequest, - communityId, - "", - "", - localAccountSensitiveSettings.useOSNotifications) - } - } +// root.store.chatsModelInst.showOSNotification(title, +// message, +// Constants.osNotificationType.joinCommunityRequest, +// communityId, +// "", +// "", +// localAccountSensitiveSettings.useOSNotifications) +// } +// } - property var loadMsgs : Backpressure.oneInTime(chatLogView, 500, function() { - if(!messages.initialMessagesLoaded || messages.loadingHistoryMessages) - return + // Not Refactored Yet +// property var loadMsgs : Backpressure.oneInTime(chatLogView, 500, function() { +// if(!messages.initialMessagesLoaded || messages.loadingHistoryMessages) +// return - root.store.chatsModelInst.messageView.loadMoreMessages(chatId); - }); +// root.store.chatsModelInst.messageView.loadMoreMessages(chatId); +// }); - onContentYChanged: { - scrollDownButton.visible = (contentHeight - (scrollY + height) > 400) - if(scrollDownButton.visible && scrollY < 500){ - loadMsgs(); - } - } +// onContentYChanged: { +// scrollDownButton.visible = (contentHeight - (scrollY + height) > 400) +// if(scrollDownButton.visible && scrollY < 500){ +// loadMsgs(); +// } +// } model: messageListDelegate section.property: "sectionIdentifier" section.criteria: ViewSection.FullString - Component.onCompleted: scrollToBottom(true) + // Not Refactored Yet + //Component.onCompleted: scrollToBottom(true) } - MessageDialog { - id: sendingMsgFailedPopup - standardButtons: StandardButton.Ok - //% "Failed to send message." - text: qsTrId("failed-to-send-message-") - icon: StandardIcon.Critical - } +// MessageDialog { +// id: sendingMsgFailedPopup +// standardButtons: StandardButton.Ok +// //% "Failed to send message." +// text: qsTrId("failed-to-send-message-") +// icon: StandardIcon.Critical +// } Timer { id: modelLoadingDelayTimer @@ -311,108 +316,150 @@ Item { function(left, right) { return left.clock > right.clock } ] - model: messages + model: messageStore.messageModule.model delegate: MessageView { id: msgDelegate rootStore: root.store - messageStore: root.store.messageStore - /////////////TODO Remove - fromAuthor: model.fromAuthor - chatId: model.chatId - userName: model.userName - alias: model.alias - localName: model.localName - message: model.message - plainText: model.plainText - identicon: model.identicon - isCurrentUser: model.isCurrentUser - timestamp: model.timestamp - sticker: model.sticker - contentType: model.contentType - replaces: model.replaces - isEdited: model.isEdited - outgoingStatus: model.outgoingStatus - responseTo: model.responseTo - authorCurrentMsg: msgDelegate.ListView.section - // The previous message is actually the nextSection since we reversed the list order - authorPrevMsg: msgDelegate.ListView.nextSection - imageClick: imagePopup.openPopup.bind(imagePopup) - messageId: model.messageId - emojiReactions: model.emojiReactions - linkUrls: model.linkUrls - communityId: model.communityId - hasMention: model.hasMention - stickerPackId: model.stickerPackId - pinnedMessage: model.isPinned - pinnedBy: model.pinnedBy - gapFrom: model.gapFrom - gapTo: model.gapTo - visible: !model.hide - messageContextMenu: root.messageContextMenuInst + messageStore: root.messageStore + + messageId: model.id + responseToMessageWithId: model.responseToMessageWithId + senderId: model.senderId + senderDisplayName: model.senderDisplayName + senderLocalName: model.senderLocalName + senderIcon: model.senderIcon + isSenderIconIdenticon: model.isSenderIconIdenticon + amISender: model.amISender + message: model.messageText + messageImage: model.messageImage + messageTimestamp: model.timestamp + messageOutgoingStatus: model.outgoingStatus + messageContentType: model.contentType + pinnedMessage: model.pinned + + // 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. + prevMessageIndex: index - 1 + prevMessageAsJsonObj: messageStore.getMessageByIndexAsJson(index - 1) + nextMessageIndex: index + 1 + nextMessageAsJsonObj: messageStore.getMessageByIndexAsJson(index + 1) + + + /////////////TODO Remove +// fromAuthor: model.fromAuthor +// chatId: model.chatId +// userName: model.userName +// alias: model.alias +// localName: model.localName +// message: model.message +// plainText: model.plainText +// identicon: model.identicon +// isCurrentUser: model.isCurrentUser +// timestamp: model.timestamp +// sticker: model.sticker +// contentType: model.contentType +// replaces: model.replaces +// isEdited: model.isEdited +// outgoingStatus: model.outgoingStatus +// responseTo: model.responseTo +// authorCurrentMsg: msgDelegate.ListView.section +// // The previous message is actually the nextSection since we reversed the list order +// authorPrevMsg: msgDelegate.ListView.nextSection +// imageClick: imagePopup.openPopup.bind(imagePopup) +// messageId: model.messageId +// emojiReactions: model.emojiReactions +// linkUrls: model.linkUrls +// communityId: model.communityId +// hasMention: model.hasMention +// stickerPackId: model.stickerPackId +// pinnedMessage: model.isPinned +// pinnedBy: model.pinnedBy +// gapFrom: model.gapFrom +// gapTo: model.gapTo +// visible: !model.hide +// messageContextMenu: root.messageContextMenuInst + +// prevMessageIndex: { +// // 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 +// if (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) { +// return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index +// } +// return -1; +// } +// nextMessageIndex: { +// if (msgDelegate.DelegateModel.itemsIndex < 1) { +// return -1 +// } +// return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index +// } +// scrollToBottom: chatLogView.scrollToBottom +// timeout: model.timeout - prevMessageIndex: { - // 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 - if (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) { - return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index - } - return -1; - } - nextMessageIndex: { - if (msgDelegate.DelegateModel.itemsIndex < 1) { - return -1 - } - return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index - } - scrollToBottom: chatLogView.scrollToBottom - timeout: model.timeout Component.onCompleted: { if ((root.countOnStartUp > 0) && (root.countOnStartUp - 1) < index) { //new message, increment z order z = index; } - messageStore.fromAuthor = model.fromAuthor; - messageStore.chatId = model.chatId; - messageStore.userName = model.userName; - messageStore.alias = model.alias; - messageStore.localName = model.localName; - messageStore.message = model.message; - messageStore.plainText = model.plainText; - messageStore.identicon = model.identicon; - messageStore.isCurrentUser = model.isCurrentUser; - messageStore.timestamp = model.timestamp; - messageStore.sticker = model.sticker; - messageStore.contentType = model.contentType; - messageStore.replaces = model.replaces; - messageStore.isEdited = model.isEdited; - messageStore.outgoingStatus = model.outgoingStatus; - messageStore.responseTo = model.responseTo; - messageStore.authorCurrentMsg = msgDelegate.ListView.section; - // The previous message is actually the nextSection since we reversed the list order - messageStore.authorPrevMsg = msgDelegate.ListView.nextSection; - messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); - messageStore.messageId = model.messageId; - messageStore.emojiReactions = model.emojiReactions; - messageStore.linkUrls = model.linkUrls; - messageStore.communityId = model.communityId; - messageStore.hasMention = model.hasMention; - messageStore.stickerPackId = model.stickerPackId; - messageStore.pinnedMessage = model.isPinned; - messageStore.pinnedBy = model.pinnedBy; - messageStore.gapFrom = model.gapFrom; - messageStore.gapTo = model.gapTo; - messageStore.messageContextMenu = root.messageContextMenuInst; - messageStore.prevMessageIndex = - // 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 - (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) ? - messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index - : -1; - messageStore.nextMessageIndex = (msgDelegate.DelegateModel.itemsIndex < 1) ? - -1 : messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index; - messageStore.scrollToBottom = chatLogView.scrollToBottom; - messageStore.timeout = model.timeout; + +// messageStore.messageId = model.id +// messageStore.responseToMessageWithId = model.responseToMessageWithId +// messageStore.senderId = model.senderId +// messageStore.senderDisplayName = model.senderDisplayName +// messageStore.senderLocalName = model.senderLocalName +// messageStore.senderIcon = model.senderIcon +// messageStore.isSenderIconIdenticon = model.isSenderIconIdenticon +// messageStore.amISender = model.amISender +// messageStore.message = model.messageText +// messageStore.messageImage = model.messageImage +// messageStore.messageTimestamp = model.timestamp +// messageStore.messageOutgoingStatus = model.outgoingStatus +// messageStore.messageContentType = model.contentType +// messageStore.pinnedMessage = model.pinned + + +// messageStore.fromAuthor = model.fromAuthor; +// messageStore.chatId = model.chatId; +// messageStore.userName = model.userName; +// messageStore.alias = model.alias; +// messageStore.localName = model.localName; +// messageStore.message = model.message; +// messageStore.plainText = model.plainText; +// messageStore.identicon = model.identicon; +// messageStore.isCurrentUser = model.isCurrentUser; +// messageStore.timestamp = model.timestamp; +// messageStore.sticker = model.sticker; +// messageStore.contentType = model.contentType; +// messageStore.replaces = model.replaces; +// messageStore.isEdited = model.isEdited; +// messageStore.outgoingStatus = model.outgoingStatus; +// messageStore.responseTo = model.responseTo; +// messageStore.authorCurrentMsg = msgDelegate.ListView.section; +// // The previous message is actually the nextSection since we reversed the list order +// messageStore.authorPrevMsg = msgDelegate.ListView.nextSection; +// messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); +// messageStore.messageId = model.messageId; +// messageStore.emojiReactions = model.emojiReactions; +// messageStore.linkUrls = model.linkUrls; +// messageStore.communityId = model.communityId; +// messageStore.hasMention = model.hasMention; +// messageStore.stickerPackId = model.stickerPackId; +// messageStore.pinnedMessage = model.isPinned; +// messageStore.pinnedBy = model.pinnedBy; +// messageStore.gapFrom = model.gapFrom; +// messageStore.gapTo = model.gapTo; +// messageStore.messageContextMenu = root.messageContextMenuInst; +// messageStore.prevMessageIndex = +// // 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 +// (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) ? +// messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index +// : -1; +// messageStore.nextMessageIndex = (msgDelegate.DelegateModel.itemsIndex < 1) ? +// -1 : messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index; +// messageStore.scrollToBottom = chatLogView.scrollToBottom; +// messageStore.timeout = model.timeout; } } Component.onCompleted: { diff --git a/ui/app/AppLayouts/Chat/views/ChatTextView.qml b/ui/app/AppLayouts/Chat/views/ChatTextView.qml index 172fc9ed97..f5fcb1a094 100644 --- a/ui/app/AppLayouts/Chat/views/ChatTextView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatTextView.qml @@ -72,7 +72,7 @@ Item { let obj = JSON.parse(foundChannelObj) - if(obj.chatType === -1 || obj.chatType === Constants.chatTypePublic) + if(obj.chatType === -1 || obj.chatType === Constants.chatType.publicChat) { // Not Refactored Yet // if(root.store.chatsModelInst.communities.activeCommunity.active) { @@ -82,7 +82,7 @@ Item { // root.store.chatsModelInst.channelView.setActiveChannel(channelName); } else if(obj.communityId === root.store.chatsModelInst.communities.activeCommunity.id && - obj.chatType === Constants.chatTypeCommunity && + obj.chatType === Constants.chatType.communityChat && root.store.chatsModelInst.channelView.activeChannel.id !== obj.id ) { @@ -113,7 +113,7 @@ Item { } text: { - if(contentType === Constants.stickerType) return ""; + if(contentType === Constants.messageContentType.stickerType) return ""; let msg = Utils.linkifyAndXSS(message); if(isEmoji) { return Emoji.parse(msg, Emoji.size.middle); diff --git a/ui/app/AppLayouts/Chat/views/CommunityColumnView.qml b/ui/app/AppLayouts/Chat/views/CommunityColumnView.qml index 178146f986..080bac16c7 100644 --- a/ui/app/AppLayouts/Chat/views/CommunityColumnView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunityColumnView.qml @@ -257,12 +257,32 @@ Item { chatListPopupMenu: ChatContextMenuView { id: chatContextMenuView - store: root.store - chatSectionModule: communitySectionModule + openHandler: function (id) { - root.store.chatsModelInst.channelView.setContextChannel(id) - chatContextMenuView.chatItem = root.store.chatsModelInst.channelView.contextChannel - + let jsonObj = root.communitySectionModule.getItemAsJson(id) + let obj = JSON.parse(jsonObj) + if (obj.error) { + console.error("error parsing chat item json object, id: ", id, " error: ", obj.error) + close() + return + } + + isCommunityChat = root.communitySectionModule.isCommunity() + chatId = obj.itemId + chatName = obj.name + chatType = obj.type + chatMuted = obj.muted + + // TODO + //currentFleet + } + + onMuteChat: { + root.communitySectionModule.muteChat(id) + } + + onUnmuteChat: { + root.communitySectionModule.unmuteChat(id) } } } diff --git a/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml b/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml index 5a250a2a33..bbdc605da7 100644 --- a/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml +++ b/ui/app/AppLayouts/Chat/views/ContactsColumnView.qml @@ -252,20 +252,36 @@ Item { model: root.chatSectionModule.model onChatItemSelected: root.chatSectionModule.setActiveItem(id, "") - -// chatListItems.model: root.store.chatsModelInst.channelView.chats -// selectedChatId: root.store.chatsModelInst.channelView.activeChannel.id - -// onChatItemSelected: root.store.chatsModelInst.channelView.setActiveChannel(id) -// onChatItemUnmuted: root.store.chatsModelInst.channelView.unmuteChatItem(id) + onChatItemUnmuted: root.chatSectionModule.unmuteChat(id) popupMenu: ChatContextMenuView { id: chatContextMenuView - store: root.store - chatSectionModule: root.chatSectionModule + openHandler: function (id) { - root.store.chatsModelInst.channelView.setContextChannel(id) - chatContextMenuView.chatItem = root.store.chatsModelInst.channelView.contextChannel + let jsonObj = root.chatSectionModule.getItemAsJson(id) + let obj = JSON.parse(jsonObj) + if (obj.error) { + console.error("error parsing chat item json object, id: ", id, " error: ", obj.error) + close() + return + } + + isCommunityChat = root.chatSectionModule.isCommunity() + chatId = obj.itemId + chatName = obj.name + chatType = obj.type + chatMuted = obj.muted + + // TODO + //currentFleet + } + + onMuteChat: { + root.chatSectionModule.muteChat(id) + } + + onUnmuteChat: { + root.chatSectionModule.unmuteChat(id) } } } diff --git a/ui/app/AppLayouts/Profile/popups/MutedChatsModal.qml b/ui/app/AppLayouts/Profile/popups/MutedChatsModal.qml index c0bd5a6773..62170fbca7 100644 --- a/ui/app/AppLayouts/Profile/popups/MutedChatsModal.qml +++ b/ui/app/AppLayouts/Profile/popups/MutedChatsModal.qml @@ -63,7 +63,7 @@ ModalPopup { StyledText { id: contactInfo - text: model.chatType !== Constants.chatTypePublic ? + text: model.chatType !== Constants.chatType.publicChat ? Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(model.name)), "26x26") : "#" + Utils.filterXSS(model.name) anchors.right: unmuteButton.left diff --git a/ui/app/AppLayouts/Profile/views/AppearanceView.qml b/ui/app/AppLayouts/Profile/views/AppearanceView.qml index 23fe538ede..073fb42bcd 100644 --- a/ui/app/AppLayouts/Profile/views/AppearanceView.qml +++ b/ui/app/AppLayouts/Profile/views/AppearanceView.qml @@ -82,23 +82,23 @@ ScrollView { anchors.topMargin: Style.current.padding*2 anchors.left: parent.left anchors.leftMargin: Style.current.smallPadding - rootStore: root.rootStore - messageStore: root.globalStore.messageStore +// rootStore: root.rootStore +// messageStore: root.globalStore.messageStore ///////////TODO Remove - userName: "@vitalik" - identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAb0lEQVR4Ae3UQQqAIBRF0Wj9ba9Bq6l5JBQqfn/ngDMH3YS3AAB/tO3H+XRG3b9bR/+gVoREI2RapVXpfd5+X5oXERKNkHS+rk3tOpWkeREh0QiZVu91ql2zNC8iJBoh0yqtSqt1slpCghICANDPBc0ESPh0bHkHAAAAAElFTkSuQmCC" - //% "Blockchains will drop search costs, causing a kind of decomposition that allows you to have markets of entities that are horizontally segregated and vertically segregated." - message: qsTrId("blockchains-will-drop-search-costs--causing-a-kind-of-decomposition-that-allows-you-to-have-markets-of-entities-that-are-horizontally-segregated-and-vertically-segregated-") - contentType: Constants.messageType - placeholderMessage: true - Component.onCompleted: { - messageStore.userName = "@vitalik"; - messageStore.identicon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAb0lEQVR4Ae3UQQqAIBRF0Wj9ba9Bq6l5JBQqfn/ngDMH3YS3AAB/tO3H+XRG3b9bR/+gVoREI2RapVXpfd5+X5oXERKNkHS+rk3tOpWkeREh0QiZVu91ql2zNC8iJBoh0yqtSqt1slpCghICANDPBc0ESPh0bHkHAAAAAElFTkSuQmCC"; - //% "Blockchains will drop search costs, causing a kind of decomposition that allows you to have markets of entities that are horizontally segregated and vertically segregated." - messageStore.message = qsTrId("blockchains-will-drop-search-costs--causing-a-kind-of-decomposition-that-allows-you-to-have-markets-of-entities-that-are-horizontally-segregated-and-vertically-segregated-"); - messageStore.contentType = Constants.messageType; - //messageStore.placeholderMessage = true; - } +// userName: "@vitalik" +// identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAb0lEQVR4Ae3UQQqAIBRF0Wj9ba9Bq6l5JBQqfn/ngDMH3YS3AAB/tO3H+XRG3b9bR/+gVoREI2RapVXpfd5+X5oXERKNkHS+rk3tOpWkeREh0QiZVu91ql2zNC8iJBoh0yqtSqt1slpCghICANDPBc0ESPh0bHkHAAAAAElFTkSuQmCC" +// //% "Blockchains will drop search costs, causing a kind of decomposition that allows you to have markets of entities that are horizontally segregated and vertically segregated." +// message: qsTrId("blockchains-will-drop-search-costs--causing-a-kind-of-decomposition-that-allows-you-to-have-markets-of-entities-that-are-horizontally-segregated-and-vertically-segregated-") +// contentType: Constants.messageContentType.messageType +// placeholderMessage: true +// Component.onCompleted: { +// messageStore.userName = "@vitalik"; +// messageStore.identicon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAb0lEQVR4Ae3UQQqAIBRF0Wj9ba9Bq6l5JBQqfn/ngDMH3YS3AAB/tO3H+XRG3b9bR/+gVoREI2RapVXpfd5+X5oXERKNkHS+rk3tOpWkeREh0QiZVu91ql2zNC8iJBoh0yqtSqt1slpCghICANDPBc0ESPh0bHkHAAAAAElFTkSuQmCC"; +// //% "Blockchains will drop search costs, causing a kind of decomposition that allows you to have markets of entities that are horizontally segregated and vertically segregated." +// messageStore.message = qsTrId("blockchains-will-drop-search-costs--causing-a-kind-of-decomposition-that-allows-you-to-have-markets-of-entities-that-are-horizontally-segregated-and-vertically-segregated-"); +// messageStore.contentType = Constants.messageContentType.messageType; +// //messageStore.placeholderMessage = true; +// } } } diff --git a/ui/app/AppLayouts/Profile/views/EnsListView.qml b/ui/app/AppLayouts/Profile/views/EnsListView.qml index 14304730fc..178245d107 100644 --- a/ui/app/AppLayouts/Profile/views/EnsListView.qml +++ b/ui/app/AppLayouts/Profile/views/EnsListView.qml @@ -330,7 +330,6 @@ Item { width: parent.width anchors.right: parent.right store: root.store - messageStore: root.messageStore } RectangleCorner {} diff --git a/ui/app/AppLayouts/Timeline/TimelineLayout.qml b/ui/app/AppLayouts/Timeline/TimelineLayout.qml index b9ef7473ba..e31195437a 100644 --- a/ui/app/AppLayouts/Timeline/TimelineLayout.qml +++ b/ui/app/AppLayouts/Timeline/TimelineLayout.qml @@ -79,7 +79,7 @@ ScrollView { id: statusUpdateInput anchors.top: parent.top anchors.topMargin: 40 - chatType: Constants.chatTypeStatusUpdate + chatType: Constants.chatType.profile imageErrorMessageLocation: StatusChatInput.ImageErrorMessageLocation.Bottom z: 1 onSendMessage: { @@ -91,7 +91,7 @@ ScrollView { var msg = root.store.getPlainTextFromRichText(Emoji.deparse(statusUpdateInput.textInput.text)) if (msg.length > 0){ msg = statusUpdateInput.interpretMessage(msg) - root.store.sendMessage(msg, Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType); + root.store.sendMessage(msg, Utils.isOnlyEmoji(msg) ? Constants.messageContentType.emojiType : Constants.messageContentType.messageType); statusUpdateInput.textInput.text = ""; if(event) event.accepted = true sendMessageSound.stop() @@ -149,74 +149,75 @@ ScrollView { // TODO: Replace with StatusQ component once it lives there. delegate: MessageView { id: msgDelegate - rootStore: root.rootStore - messageStore: root.messageStore - /////////TODO Remove - fromAuthor: model.fromAuthor - chatId: model.chatId - userName: model.userName - alias: model.alias - localName: model.localName - message: model.message - plainText: model.plainText - identicon: model.identicon - isCurrentUser: model.isCurrentUser - timestamp: model.timestamp - sticker: model.sticker - contentType: model.contentType - outgoingStatus: model.outgoingStatus - responseTo: model.responseTo - authorCurrentMsg: msgDelegate.ListView.section - authorPrevMsg: msgDelegate.ListView.previousSection - imageClick: imagePopup.openPopup.bind(imagePopup) - messageId: model.messageId - emojiReactions: model.emojiReactions - isStatusUpdate: true - statusAgeEpoch: ageUpdateTimer.epoch - // 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: { - // 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 - if(msgDelegate.DelegateModel.itemsIndex > 0){ - return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index - } - return -1; - } - timeout: model.timeout - messageContextMenu: msgCntxtMenu - Component.onCompleted: { - messageStore.fromAuthor = model.fromAuthor; - messageStore.chatId = model.chatId; - messageStore.userName = model.userName; - messageStore.alias = model.alias; - messageStore.localName = model.localName; - messageStore.message = model.message; - messageStore.plainText = model.plainText; - messageStore.identicon = model.identicon; - messageStore.isCurrentUser = model.isCurrentUser; - messageStore.timestamp = model.timestamp; - messageStore.sticker = model.sticker; - messageStore.contentType = model.contentType; - messageStore.outgoingStatus = model.outgoingStatus; - messageStore.responseTo = model.responseTo; - messageStore.authorCurrentMsg = msgDelegate.ListView.section; - messageStore.authorPrevMsg = msgDelegate.ListView.previousSection; - messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); - messageStore.messageId = model.messageId; - messageStore.emojiReactions = model.emojiReactions; - messageStore.isStatusUpdate = true; - messageStore.statusAgeEpoch = ageUpdateTimer.epoch; - // 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 - messageStore.prevMessageIndex = - // 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 - (msgDelegate.DelegateModel.itemsIndex > 0) ? - messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index : -1; - messageStore.timeout = model.timeout; - messageStore.messageContextMenu = msgCntxtMenu; - } + // Not Refactored Yet + +// rootStore: root.rootStore +// messageStore: root.messageStore +// fromAuthor: model.fromAuthor +// chatId: model.chatId +// userName: model.userName +// alias: model.alias +// localName: model.localName +// message: model.message +// plainText: model.plainText +// identicon: model.identicon +// isCurrentUser: model.isCurrentUser +// timestamp: model.timestamp +// sticker: model.sticker +// contentType: model.contentType +// outgoingStatus: model.outgoingStatus +// responseTo: model.responseTo +// authorCurrentMsg: msgDelegate.ListView.section +// authorPrevMsg: msgDelegate.ListView.previousSection +// imageClick: imagePopup.openPopup.bind(imagePopup) +// messageId: model.messageId +// emojiReactions: model.emojiReactions +// isStatusUpdate: true +// statusAgeEpoch: ageUpdateTimer.epoch +// // 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: { +// // 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 +// if(msgDelegate.DelegateModel.itemsIndex > 0){ +// return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index +// } +// return -1; +// } +// timeout: model.timeout +// messageContextMenu: msgCntxtMenu +// Component.onCompleted: { +// messageStore.fromAuthor = model.fromAuthor; +// messageStore.chatId = model.chatId; +// messageStore.userName = model.userName; +// messageStore.alias = model.alias; +// messageStore.localName = model.localName; +// messageStore.message = model.message; +// messageStore.plainText = model.plainText; +// messageStore.identicon = model.identicon; +// messageStore.isCurrentUser = model.isCurrentUser; +// messageStore.timestamp = model.timestamp; +// messageStore.sticker = model.sticker; +// messageStore.contentType = model.contentType; +// messageStore.outgoingStatus = model.outgoingStatus; +// messageStore.responseTo = model.responseTo; +// messageStore.authorCurrentMsg = msgDelegate.ListView.section; +// messageStore.authorPrevMsg = msgDelegate.ListView.previousSection; +// messageStore.imageClick = imagePopup.openPopup.bind(imagePopup); +// messageStore.messageId = model.messageId; +// messageStore.emojiReactions = model.emojiReactions; +// messageStore.isStatusUpdate = true; +// messageStore.statusAgeEpoch = ageUpdateTimer.epoch; +// // 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 +// messageStore.prevMessageIndex = +// // 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 +// (msgDelegate.DelegateModel.itemsIndex > 0) ? +// messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index : -1; +// messageStore.timeout = model.timeout; +// messageStore.messageContextMenu = msgCntxtMenu; +// } MessageContextMenuView { id: msgCntxtMenu store: root.store diff --git a/ui/app/AppLayouts/stores/RootStore.qml b/ui/app/AppLayouts/stores/RootStore.qml index 3e8f21113d..c1ff9879c1 100644 --- a/ui/app/AppLayouts/stores/RootStore.qml +++ b/ui/app/AppLayouts/stores/RootStore.qml @@ -20,7 +20,7 @@ QtObject { property var profileModelInst: profileModel property var assets: walletSectionAccountTokens.model - property MessageStore messageStore: MessageStore { } +// property MessageStore messageStore: MessageStore { } property var contactsModuleInst: contactsModule property var addedContacts: contactsModuleInst.model.addedContacts diff --git a/ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml b/ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml index 1bd3615b00..a5519df3e2 100644 --- a/ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml +++ b/ui/imports/shared/controls/chat/FetchMoreMessagesButton.qml @@ -10,6 +10,8 @@ Item { height: childrenRect.height + Style.current.smallPadding * 2 anchors.left: parent.left anchors.right: parent.right + property int nextMessageIndex + property string nextMsgTimestamp signal clicked() signal timerTriggered() Timer { @@ -70,11 +72,7 @@ Item { horizontalAlignment: Text.AlignHCenter color: Style.current.secondaryText //% "before %1" - text: { - let d = chatsModel.channelView.activeChannel.syncedTo == 0 ? new Date() : new Date(chatsModel.channelView.activeChannel.syncedTo * 1000) - return qsTrId("before--1").arg(d.toLocaleString(Qt.locale(localAppSettings.locale))) - } - + text: qsTrId("before--1").arg((nextMessageIndex > -1 ? new Date(nextMsgTimestamp * 1) : new Date()).toLocaleString(Qt.locale(localAppSettings.locale))) } Separator { anchors.top: fetchDate.bottom diff --git a/ui/imports/shared/controls/chat/UserImage.qml b/ui/imports/shared/controls/chat/UserImage.qml index c661f74366..dfa6b9f914 100644 --- a/ui/imports/shared/controls/chat/UserImage.qml +++ b/ui/imports/shared/controls/chat/UserImage.qml @@ -6,16 +6,12 @@ import utils 1.0 Loader { id: root - active: isMessage height: active ? item.height : 0 property int imageHeight: 36 property int imageWidth: 36 - property string profileImage: "" - property string identiconImageSource: "" - property bool isReplyImage: false -// property var messageContextMenu -// property bool isCurrentUser: false -// property bool isMessage: false + property string icon: "" + property bool isIdenticon: false + signal clickMessage(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly, bool hideEmojiPicker, bool isReply) sourceComponent: Component { @@ -28,23 +24,9 @@ Loader { id: identiconImage width: root.imageWidth height: root.imageHeight - border.width: 1 + border.width: root.isIdenticon ? 1 : 0 border.color: Style.current.border - source: { - if (root.isReplyImage) { - if (root.profileImage) { - return root.profileImage - } - if (root.identiconImageSource) { - return root.identiconImageSource - } - } - if (profileImageSource) { - return profileImageSource - } - identiconImage.showLoadingIndicator = false - return !isCurrentUser || isReplyImage ? identicon : userProfile.icon - } + source: root.icon smooth: false antialiasing: true diff --git a/ui/imports/shared/controls/chat/UsernameLabel.qml b/ui/imports/shared/controls/chat/UsernameLabel.qml index 00452a6dd0..b231a9fb70 100644 --- a/ui/imports/shared/controls/chat/UsernameLabel.qml +++ b/ui/imports/shared/controls/chat/UsernameLabel.qml @@ -11,19 +11,17 @@ Item { height: childrenRect.height width: chatName.width + (ensOrAlias.visible ? ensOrAlias.width + ensOrAlias.anchors.leftMargin : 0) property alias label: chatName -// property var messageContextMenu -// property bool isCurrentUser: false -// property string userName: "" -// property string localName: "" -// property string displayUserName: "" + + property string displayName + property string localName + property bool amISender + signal clickMessage(bool isProfileClick) - //TODO remove dynamic scoping - //visible: isMessage && authorCurrentMsg != authorPrevMsg StyledTextEdit { id: chatName - text: displayUserName - color: text.startsWith("@") || isCurrentUser || localName !== "" ? Style.current.blue : Style.current.secondaryText + text: displayName + color: text.startsWith("@") || amISender || localName !== "" ? Style.current.blue : Style.current.secondaryText font.weight: Font.Medium font.pixelSize: Style.current.secondaryTextFontSize font.underline: root.isHovered @@ -55,8 +53,8 @@ Item { StyledText { id: ensOrAlias - visible: localName !== "" && userName.startsWith("@") - text: userName + visible: localName !== "" && displayName.startsWith("@") + text: displayName color: Style.current.secondaryText font.pixelSize: chatName.font.pixelSize anchors.left: chatName.right diff --git a/ui/imports/shared/panels/chat/ChatButtonsPanel.qml b/ui/imports/shared/panels/chat/ChatButtonsPanel.qml index 0787ba25f5..fe91535d7b 100644 --- a/ui/imports/shared/panels/chat/ChatButtonsPanel.qml +++ b/ui/imports/shared/panels/chat/ChatButtonsPanel.qml @@ -21,7 +21,7 @@ Rectangle { visible: !placeholderMessage && !activityCenterMessage && (buttonsContainer.parentIsHovered || isMessageActive) - && contentType !== Constants.transactionType + && contentType !== Constants.messageContentType.transactionType width: buttonRow.width + buttonsContainer.containerMargin * 2 height: 36 radius: Style.current.radius diff --git a/ui/imports/shared/panels/chat/ChatReplyPanel.qml b/ui/imports/shared/panels/chat/ChatReplyPanel.qml index 348f0f56cf..38c586c4e7 100644 --- a/ui/imports/shared/panels/chat/ChatReplyPanel.qml +++ b/ui/imports/shared/panels/chat/ChatReplyPanel.qml @@ -12,47 +12,41 @@ import shared.controls.chat 1.0 Loader { id: root + property bool amISenderOfTheRepliedMessage + property int repliedMessageContentType + property string repliedMessageSenderIcon + property bool repliedMessageSenderIconIsIdenticon + property bool repliedMessageIsEdited + property string repliedMessageSender + property string repliedMessageContent + property string repliedMessageImage + property int nameMargin: 6 property int textFieldWidth: item ? item.textField.width : 0 property int textFieldImplicitWidth: 0 property int authorWidth: item ? item.authorMetrics.width : 0 property bool longReply: false - property color elementsColor: isCurrentUser ? Style.current.chatReplyCurrentUser : Style.current.secondaryText + property color elementsColor: amISenderOfTheRepliedMessage ? Style.current.chatReplyCurrentUser : Style.current.secondaryText property var container property int chatHorizontalPadding property var stickerData - signal clickMessage(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly, bool hideEmojiPicker, bool isReply) -// TODO bring those back and remove dynamic scoping -// property bool isCurrentUser: false -// property int repliedMessageType -// property string repliedMessageImage - property string repliedMessageUserIdenticon: "" -// property bool repliedMessageIsEdited - property string repliedMessageUserImage: "" -// property string repliedMessageAuthor -// property string repliedMessageContent -// property string responseTo: "" -// signal scrollToBottom(bool isit, var container) + signal clickMessage(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly, bool hideEmojiPicker, bool isReply) + signal scrollToBottom(bool isit, var container) sourceComponent: Component { Item { property alias textField: lblReplyMessage property alias authorMetrics: txtAuthorMetrics - property var messageEdited: function(id, content) { - if (responseTo === id){ - lblReplyMessage.text = Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(content + Constants.editLabel), Emoji.size.small), isCurrentUser, localAccountSensitiveSettings.useCompactMode) - } - } id: chatReply // childrenRect.height shows a binding loop for some reason, so we use heights instead height: { const h = userImage.height + 4 - if (repliedMessageType === Constants.imageType) { + if (repliedMessageContentType === Constants.messageContentType.imageType) { return h + imgReplyImage.height } - if (repliedMessageType === Constants.stickerType) { + if (repliedMessageContentType === Constants.messageContentType.stickerType) { return h + stickerLoader.height } return h + lblReplyMessage.height @@ -107,10 +101,8 @@ Loader { active: true anchors.left: replyCorner.right anchors.leftMargin: Style.current.halfPadding - identiconImageSource: repliedMessageUserIdenticon - isReplyImage: true - profileImage: repliedMessageUserImage -// isCurrentUser: isCurrentUser + icon: repliedMessageSenderIcon + isIdenticon: repliedMessageSenderIconIsIdenticon onClickMessage: { root.clickMessage(true, false, false, null, false, false, isReplyImage) } @@ -118,7 +110,7 @@ Loader { StyledTextEdit { id: lblReplyAuthor - text: repliedMessageAuthor + text: repliedMessageSender color: root.elementsColor readOnly: true font.pixelSize: Style.current.secondaryTextFontSize @@ -131,7 +123,7 @@ Loader { StatusChatImage { id: imgReplyImage - visible: repliedMessageType === Constants.imageType + visible: repliedMessageContentType === Constants.messageContentType.imageType imageWidth: 50 imageSource: repliedMessageImage anchors.top: lblReplyAuthor.bottom @@ -144,7 +136,7 @@ Loader { Loader { id: stickerLoader - active: repliedMessageType === Constants.stickerType + active: repliedMessageContentType === Constants.messageContentType.stickerType anchors.top: lblReplyAuthor.bottom anchors.topMargin: nameMargin anchors.left: userImage.left @@ -154,7 +146,7 @@ Loader { imageHeight: 56 imageWidth: 56 stickerData: root.stickerData - contentType: repliedMessageType + contentType: repliedMessageContentType onLoaded: { scrollToBottom(true, root.container) } @@ -164,16 +156,16 @@ Loader { StyledTextEdit { id: lblReplyMessage - visible: repliedMessageType !== Constants.imageType && repliedMessageType !== Constants.stickerType + visible: repliedMessageContentType !== Constants.messageContentType.imageType && repliedMessageContentType !== Constants.messageContentType.stickerType Component.onCompleted: textFieldImplicitWidth = implicitWidth anchors.top: lblReplyAuthor.bottom anchors.topMargin: nameMargin text: { if (repliedMessageIsEdited){ let index = repliedMessageContent.length - 4 - return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent.slice(0, index) + Constants.editLabel + repliedMessageContent.slice(index)), Emoji.size.small), isCurrentUser, localAccountSensitiveSettings.useCompactMode) + return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent.slice(0, index) + Constants.editLabel + repliedMessageContent.slice(index)), Emoji.size.small), amISenderOfTheRepliedMessage, localAccountSensitiveSettings.useCompactMode) } else { - return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), Emoji.size.small), isCurrentUser, localAccountSensitiveSettings.useCompactMode) + return Utils.getReplyMessageStyle(Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), Emoji.size.small), amISenderOfTheRepliedMessage, localAccountSensitiveSettings.useCompactMode) } } textFormat: Text.RichText diff --git a/ui/imports/shared/panels/chat/ChatTimePanel.qml b/ui/imports/shared/panels/chat/ChatTimePanel.qml index a842cffe53..be8362bb55 100644 --- a/ui/imports/shared/panels/chat/ChatTimePanel.qml +++ b/ui/imports/shared/panels/chat/ChatTimePanel.qml @@ -8,14 +8,13 @@ import utils 1.0 StyledText { id: chatTime color: Style.current.secondaryText - //TODO uncomment when dynamic scoping is cleaned up - //property string timestamp - text: Utils.formatTime(timestamp) + property string timestamp + text: Utils.formatTime(chatTime.timestamp) font.pixelSize: Style.current.asideTextFontSize StatusQ.StatusToolTip { visible: hhandler.hovered - text: new Date(parseInt(timestamp, 10)).toLocaleString(Qt.locale(localAppSettings.locale)) + text: new Date(parseInt(chatTime.timestamp, 10)).toLocaleString(Qt.locale(localAppSettings.locale)) maxWidth: 350 } diff --git a/ui/imports/shared/panels/chat/EmojiReactionsPanel.qml b/ui/imports/shared/panels/chat/EmojiReactionsPanel.qml index 18556718f5..d2e17d1d6a 100644 --- a/ui/imports/shared/panels/chat/EmojiReactionsPanel.qml +++ b/ui/imports/shared/panels/chat/EmojiReactionsPanel.qml @@ -19,10 +19,9 @@ Item { signal toggleReaction(int emojiID) signal setMessageActive(string messageId, bool active) -// TODO bring those back and remove dynamic scoping -// property bool isCurrentUser -// property var emojiReactionsModel -// property bool isMessageActive + property bool isCurrentUser + property var emojiReactionsModel + property bool isMessageActive Row { spacing: root.imageMargin @@ -30,7 +29,7 @@ Item { Repeater { id: reactionRepeater width: childrenRect.width - model: emojiReactionsModel + model: root.emojiReactionsModel Rectangle { property bool isHovered: false @@ -55,9 +54,9 @@ Item { width: 10 height: 10 anchors.top: parent.top - anchors.left: !isCurrentUser || localAccountSensitiveSettings.useCompactMode ? parent.left : undefined + anchors.left: !root.isCurrentUser || localAccountSensitiveSettings.useCompactMode ? parent.left : undefined anchors.leftMargin: 0 - anchors.right: !isCurrentUser || localAccountSensitiveSettings.useCompactMode ? undefined : parent.right + anchors.right: !root.isCurrentUser || localAccountSensitiveSettings.useCompactMode ? undefined : parent.right anchors.rightMargin: 0 radius: 2 z: -1 @@ -84,9 +83,9 @@ Item { width: 10 height: 10 anchors.top: parent.top - anchors.left: !isCurrentUser || localAccountSensitiveSettings.useCompactMode ? parent.left : undefined + anchors.left: !root.isCurrentUser || localAccountSensitiveSettings.useCompactMode ? parent.left : undefined anchors.leftMargin: 0 - anchors.right: !isCurrentUser || localAccountSensitiveSettings.useCompactMode ? undefined : parent.right + anchors.right: !root.isCurrentUser || localAccountSensitiveSettings.useCompactMode ? undefined : parent.right anchors.rightMargin: 0 radius: 2 z: -1 @@ -176,7 +175,7 @@ Item { onEntered: addEmojiBtn.isHovered = true onExited: addEmojiBtn.isHovered = false onClicked: { - if (typeof isMessageActive !== "undefined") { + if (typeof root.isMessageActive !== "undefined") { setMessageActive(messageId, true); } root.addEmojiClicked(); diff --git a/ui/imports/shared/status/StatusChatInput.qml b/ui/imports/shared/status/StatusChatInput.qml index 5d1b1272c3..1ca4d4f83f 100644 --- a/ui/imports/shared/status/StatusChatInput.qml +++ b/ui/imports/shared/status/StatusChatInput.qml @@ -49,7 +49,7 @@ Rectangle { property string chatInputPlaceholder: qsTrId("type-a-message-") property alias textInput: messageInputField - property bool isStatusUpdateInput: chatType === Constants.chatTypeStatusUpdate + property bool isStatusUpdateInput: chatType === Constants.chatType.profile property var fileUrls: [] @@ -713,7 +713,7 @@ Rectangle { anchors.bottomMargin: 16 icon.name: "chat-commands" type: StatusQ.StatusFlatRoundButton.Type.Tertiary - visible: !isEdit && control.chatType === Constants.chatTypeOneToOne && !control.isStatusUpdateInput + visible: !isEdit && control.chatType === Constants.chatType.oneToOne && !control.isStatusUpdateInput enabled: !control.isContactBlocked onClicked: { chatCommandsPopup.opened ? @@ -732,7 +732,7 @@ Rectangle { anchors.bottomMargin: 16 icon.name: "image" type: StatusQ.StatusFlatRoundButton.Type.Tertiary - visible: !isEdit && control.chatType !== Constants.chatTypePublic && !control.isStatusUpdateInput + visible: !isEdit && control.chatType !== Constants.chatType.publicChat && !control.isStatusUpdateInput enabled: !control.isContactBlocked onClicked: { highlighted = true diff --git a/ui/imports/shared/status/StatusChatInputReplyArea.qml b/ui/imports/shared/status/StatusChatInputReplyArea.qml index a0c7835fea..742c1cc739 100644 --- a/ui/imports/shared/status/StatusChatInputReplyArea.qml +++ b/ui/imports/shared/status/StatusChatInputReplyArea.qml @@ -8,9 +8,9 @@ import shared.panels 1.0 Rectangle { id: root - height: (root.contentType === Constants.imageType) ? + height: (root.contentType === Constants.messageContentType.imageType) ? replyToUsername.height + imageThumbnail.height + Style.current.padding : - (root.contentType === Constants.stickerType) ? + (root.contentType === Constants.messageContentType.stickerType) ? replyToUsername.height + stickerThumbnail.height + Style.current.padding : 50 color: Style.current.replyBackground radius: 16 @@ -55,7 +55,7 @@ Rectangle { anchors.bottom: parent.bottom clip: true color: Style.current.transparent - visible: (root.contentType !== Constants.imageType) && (root.contentType !== Constants.stickerType) + visible: (root.contentType !== Constants.messageContentType.imageType) && (root.contentType !== Constants.messageContentType.stickerType) StyledText { id: replyText @@ -78,7 +78,7 @@ Rectangle { imageSource: root.image chatHorizontalPadding: 0 container: root.container - visible: root.contentType === Constants.imageType + visible: root.contentType === Constants.messageContentType.imageType } StatusSticker { diff --git a/ui/imports/shared/status/StatusNotification.qml b/ui/imports/shared/status/StatusNotification.qml index d0900cc373..3f87ff70c4 100644 --- a/ui/imports/shared/status/StatusNotification.qml +++ b/ui/imports/shared/status/StatusNotification.qml @@ -15,7 +15,7 @@ Rectangle { property string chatId: "" property string name: "channelName" property string message: "My latest message\n with a return" - property int chatType: Constants.chatTypePublic + property int chatType: Constants.chatType.publicChat property string identicon: "" color: "#F7F7F7" diff --git a/ui/imports/shared/status/StatusSticker.qml b/ui/imports/shared/status/StatusSticker.qml index 1bbeee90e3..c816f420e2 100644 --- a/ui/imports/shared/status/StatusSticker.qml +++ b/ui/imports/shared/status/StatusSticker.qml @@ -12,7 +12,7 @@ Loader { signal loaded() id: root - active: contentType === Constants.stickerType + active: contentType === Constants.messageContentType.stickerType sourceComponent: Component { ImageLoader { diff --git a/ui/imports/shared/views/chat/ChannelIdentifierView.qml b/ui/imports/shared/views/chat/ChannelIdentifierView.qml index 8efc23e08d..72b3b852d6 100644 --- a/ui/imports/shared/views/chat/ChannelIdentifierView.qml +++ b/ui/imports/shared/views/chat/ChannelIdentifierView.qml @@ -22,10 +22,10 @@ Column { width: 120 height: 120 radius: 120 - border.width: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne ? 2 : 0 + border.width: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne ? 2 : 0 border.color: Style.current.border color: { - if (root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) { + if (root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne) { return Style.current.transparent } if (root.store.chatsModelInst.channelView.activeChannel.color) { @@ -39,7 +39,7 @@ Column { } RoundedImage { - visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne + visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter width: 120 @@ -50,7 +50,7 @@ Column { } StyledText { - visible: root.store.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatTypeOneToOne + visible: root.store.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatType.oneToOne text: Utils.removeStatusEns((root.store.chatsModelInst.channelView.activeChannel.name.charAt(0) === "#" ? root.store.chatsModelInst.channelView.activeChannel.name.charAt(1) : root.store.chatsModelInst.channelView.activeChannel.name.charAt(0)).toUpperCase()) @@ -68,8 +68,8 @@ Column { wrapMode: Text.Wrap text: { switch(root.store.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypePublic: return "#" + root.store.chatsModelInst.channelView.activeChannel.name; - case Constants.chatTypeOneToOne: return Utils.removeStatusEns(root.store.chatsModelInst.userNameOrAlias(chatsModel.channelView.activeChannel.id)) + case Constants.chatType.publicChat: return "#" + root.store.chatsModelInst.channelView.activeChannel.name; + case Constants.chatType.oneToOne: return Utils.removeStatusEns(root.store.chatsModelInst.userNameOrAlias(chatsModel.channelView.activeChannel.id)) default: return root.store.chatsModelInst.channelView.activeChannel.name } } @@ -87,9 +87,9 @@ Column { text: { switch(root.store.chatsModelInst.channelView.activeChannel.chatType) { //% "Welcome to the beginning of the %2 group!" - case Constants.chatTypePrivateGroupChat: return qsTrId("welcome-to-the-beginning-of-the--span-style--color---1---2--span--group-").arg(Style.current.textColor).arg(root.store.chatsModelInst.channelView.activeChannel.name); + case Constants.chatType.privateGroupChat: return qsTrId("welcome-to-the-beginning-of-the--span-style--color---1---2--span--group-").arg(Style.current.textColor).arg(root.store.chatsModelInst.channelView.activeChannel.name); //% "Any messages you send here are encrypted and can only be read by you and %2" - case Constants.chatTypeOneToOne: return qsTrId("any-messages-you-send-here-are-encrypted-and-can-only-be-read-by-you-and--span-style--color---1---2--span-").arg(Style.current.textColor).arg(channelName.text) + case Constants.chatType.oneToOne: return qsTrId("any-messages-you-send-here-are-encrypted-and-can-only-be-read-by-you-and--span-style--color---1---2--span-").arg(Style.current.textColor).arg(channelName.text) default: return ""; } } @@ -100,7 +100,7 @@ Column { } Item { - visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypePrivateGroupChat + visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.privateGroupChat && root.store.chatsModelInst.channelView.activeChannel.isMemberButNotJoined anchors.horizontalCenter: parent.horizontalCenter width: visible ? joinChat.width : 0 diff --git a/ui/imports/shared/views/chat/ChatTextView.qml b/ui/imports/shared/views/chat/ChatTextView.qml index e171089358..7f091cacfe 100644 --- a/ui/imports/shared/views/chat/ChatTextView.qml +++ b/ui/imports/shared/views/chat/ChatTextView.qml @@ -10,11 +10,10 @@ Item { id: root property var store - //TODO remove when dynamic scoping is cleaned up - property var messageStore property bool longChatText: true - property bool veryLongChatText: !!root.store ? root.store.chatsModelInst.plainText(message).length > - (localAccountSensitiveSettings.useCompactMode ? Constants.limitLongChatTextCompactMode : Constants.limitLongChatText) : false + property bool veryLongChatText: false +// property bool veryLongChatText: !!root.store ? root.store.chatsModelInst.plainText(message).length > +// (localAccountSensitiveSettings.useCompactMode ? Constants.limitLongChatTextCompactMode : Constants.limitLongChatText) : false property bool readMore: false property alias textField: chatText @@ -53,7 +52,6 @@ Item { height: root.veryLongChatText && !root.readMore ? Math.min(implicitHeight, 200) : implicitHeight clip: height < implicitHeight onLinkActivated: { - root.linkActivated(link) if(link.startsWith("#")) { const channelName = link.substring(1); @@ -112,7 +110,7 @@ Item { } text: { - if(contentType === Constants.stickerType) return ""; + if(contentType === Constants.messageContentType.stickerType) return ""; let msg = Utils.linkifyAndXSS(message); if(isEmoji) { return Emoji.parse(msg, Emoji.size.middle); diff --git a/ui/imports/shared/views/chat/CompactMessageView.qml b/ui/imports/shared/views/chat/CompactMessageView.qml index f3a527f99c..9755f300ac 100644 --- a/ui/imports/shared/views/chat/CompactMessageView.qml +++ b/ui/imports/shared/views/chat/CompactMessageView.qml @@ -12,38 +12,35 @@ import StatusQ.Controls 0.1 as StatusQControls Item { id: root - property var store - property var messageStore + + property var messageContextMenu + property var container + + property int chatHorizontalPadding: Style.current.halfPadding property int chatVerticalPadding: 7 - property string linkUrls: root.messageStore.linkUrls - property int contentType: 2 - property var container - property bool isCurrentUser: false - property bool isExpired: false - property bool timeout: false - property bool isHovered: typeof root.messageStore.hoveredMessage !== "undefined" && root.messageStore.hoveredMessage === messageId - property bool isMessageActive: typeof root.messageStore.activeMessage !== "undefined" && root.messageStore.activeMessage === messageId - property bool headerRepeatCondition: (authorCurrentMsg !== authorPrevMsg || shouldRepeatHeader || dateGroupLbl.visible || chatReply.active) - property bool showMoreButton: { - if (!!root.store) { - switch (root.store.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypeOneToOne: return true - case Constants.chatTypePrivateGroupChat: return root.store.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) ? true : isCurrentUser - case Constants.chatTypePublic: return isCurrentUser - case Constants.chatTypeCommunity: return root.store.chatsModelInst.communities.activeCommunity.admin ? true : isCurrentUser - default: return false - } - } - else { - return false; - } - } - property string repliedMessageUserIdenticon - property string repliedMessageUserImage - property bool showEdit: true - property var messageContextMenu + property bool headerRepeatCondition: (authorCurrentMsg !== authorPrevMsg || + shouldRepeatHeader || dateGroupLbl.visible || chatReply.active) + property bool showMoreButton: { + // Not Refactored Yet + + return false +// if (!!rootStore) { +// switch (rootStore.chatsModelInst.channelView.activeChannel.chatType) { +// case Constants.chatType.oneToOne: return true +// case Constants.chatType.privateGroupChat: return rootStore.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) ? true : isCurrentUser +// case Constants.chatType.publicChat: return isCurrentUser +// case Constants.chatType.communityChat: return rootStore.chatsModelInst.communities.activeCommunity.admin ? true : isCurrentUser +// case Constants.chatType.profile: return false +// default: return false +// } +// } +// else { +// return false; +// } + } + signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker) width: parent.width @@ -68,10 +65,10 @@ Item { } ChatButtonsPanel { - contentType: root.contentType - parentIsHovered: !isEdit && root.isHovered + contentType: contentType + parentIsHovered: !isEdit && isHovered onHoverChanged: { - hovered && root.messageStore.setHovered(messageId, hovered) + hovered && setHovered(messageId, hovered) } anchors.right: parent.right anchors.rightMargin: 20 @@ -79,8 +76,8 @@ 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 messageContextMenu: root.messageContextMenu - showMoreButton: root.showMoreButton - fromAuthor: fromAuthor + showMoreButton: showMoreButton + fromAuthor: senderId editBtnActive: isText && !isEdit && isCurrentUser && showEdit onClickMessage: { parent.parent.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker); @@ -88,12 +85,12 @@ Item { } Loader { - active: typeof messageContextMenu !== "undefined" + active: typeof root.messageContextMenu !== "undefined" sourceComponent: Component { Connections { - enabled: root.isMessageActive - target: messageContextMenu - onClosed: root.messageStore.setMessageActive(messageId, false) + enabled: isMessageActive + target: root.messageContextMenu + onClosed: setMessageActive(messageId, false) } } } @@ -155,6 +152,7 @@ Item { + (pinnedRectangleLoader.active ? Style.current.smallPadding : 0) + (isEdit ? 25 : 0) width: parent.width + color: { if (isEdit) { return Style.current.backgroundHoverLight @@ -169,10 +167,10 @@ Item { } if (pinnedMessage) { - return root.isHovered || isMessageActive ? Style.current.pinnedMessageBackgroundHovered : Style.current.pinnedMessageBackground + return isHovered || isMessageActive ? Style.current.pinnedMessageBackgroundHovered : Style.current.pinnedMessageBackground } - return root.isHovered || isMessageActive ? (hasMention ? Style.current.mentionMessageHoverColor : Style.current.backgroundHoverLight) : + return isHovered || isMessageActive ? (hasMention ? Style.current.mentionMessageHoverColor : Style.current.backgroundHoverLight) : (hasMention ? Style.current.mentionMessageColor : Style.current.transparent) } @@ -209,7 +207,7 @@ Item { StyledText { //% "Pinned by %1" - text: qsTrId("pinned-by--1").arg(root.store.chatsModelInst.alias(pinnedBy)) + text: qsTrId("pinned-by--1").arg(rootStore.chatsModelInst.alias(pinnedBy)) anchors.left: pinImage.right anchors.verticalCenter: parent.verticalCenter font.pixelSize: 13 @@ -220,8 +218,8 @@ Item { Connections { - enabled: !!root.store - target: enabled ? root.store.chatsModelInst.messageView : null + enabled: !!rootStore + target: enabled ? rootStore.chatsModelInst.messageView : null onMessageEdited: { if(chatReply.item) chatReply.item.messageEdited(editedMessageId, editedMessageContent) @@ -238,24 +236,33 @@ Item { longReply: active && textFieldImplicitWidth > width container: root.container - chatHorizontalPadding: root.chatHorizontalPadding - stickerData: !!root.store ? root.store.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "sticker") : null - active: responseTo !== "" && replyMessageIndex > -1 && !activityCenterMessage -// To-Do move to store later? -// isCurrentUser: root.messageStore.isCurrentUser -// repliedMessageType: root.messageStore.repliedMessageType -// repliedMessageImage: root.messageStore.repliedMessageImage - repliedMessageUserIdenticon: root.repliedMessageUserIdenticon -// repliedMessageIsEdited: root.messageStore.repliedMessageIsEdited - repliedMessageUserImage: root.repliedMessageUserImage -// repliedMessageAuthor: root.messageStore.repliedMessageAuthor -// repliedMessageContent: root.messageStore.repliedMessageContent -// responseTo: root.messageStore.responseTo -// onScrollToBottom: { -// root.messageStore.scrollToBottom(isit, container); -// } + chatHorizontalPadding: chatHorizontalPadding + // Not Refactored Yet +// stickerData: !!rootStore ? rootStore.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "sticker") : null + active: responseTo !== "" && !activityCenterMessage + + Component.onCompleted: { + let obj = messageStore.getMessageByIdAsJson(messageId) + if(!obj) + return + + amISenderOfTheRepliedMessage = obj.amISender + repliedMessageContentType = obj.contentType + repliedMessageSenderIcon = obj.senderIcon + repliedMessageSenderIconIsIdenticon = obj.isSenderIconIdenticon + // TODO: not sure about is edited at the moment + repliedMessageIsEdited = false + repliedMessageSender = obj.senderDisplayName + repliedMessageContent = obj.messageText + repliedMessageImage = obj.messageImage + } + onScrollToBottom: { + // Not Refactored Yet +// messageStore.scrollToBottom(isit, root.container); + } onClickMessage: { - parent.parent.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); + // Not Refactored Yet +// parent.parent.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); } } @@ -268,11 +275,8 @@ Item { anchors.top: chatReply.active ? chatReply.bottom : pinnedRectangleLoader.active ? pinnedRectangleLoader.bottom : parent.top anchors.topMargin: chatReply.active || pinnedRectangleLoader.active ? 4 : Style.current.smallPadding -// messageContextMenu: root.messageStore.messageContextMenu -// isCurrentUser: root.messageStore.isCurrentUser -// profileImage: root.messageStore.profileImageSource -// isMessage: root.messageStore.isMessage -// identiconImageSource: root.messageStore.identicon + icon: senderIcon + isIdenticon: isSenderIconIdenticon onClickMessage: { parent.parent.parent.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); } @@ -281,14 +285,12 @@ Item { UsernameLabel { id: chatName visible: !isEdit && isMessage && headerRepeatCondition - anchors.leftMargin: root.chatHorizontalPadding + anchors.leftMargin: chatHorizontalPadding anchors.top: chatImage.top anchors.left: chatImage.right -// messageContextMenu: root.messageStore.messageContextMenu -// isCurrentUser: root.messageStore.isCurrentUser -// localName: root.messageStore.localName -// userName: root.messageStore.userName -// displayUserName: root.messageStore.displayUserName + displayName: senderDisplayName + localName: senderLocalName + amISender: amISender onClickMessage: { parent.parent.parent.parent.clickMessage(true, false, false, null, false, false, false); } @@ -309,9 +311,9 @@ Item { active: isEdit anchors.top: chatReply.active ? chatReply.bottom : parent.top anchors.left: chatImage.right - anchors.leftMargin: root.chatHorizontalPadding + anchors.leftMargin: chatHorizontalPadding anchors.right: parent.right - anchors.rightMargin: root.chatHorizontalPadding + anchors.rightMargin: chatHorizontalPadding height: (item !== null && typeof(item)!== 'undefined')? item.height: 0 property string sourceText @@ -374,7 +376,7 @@ Item { StatusChatInput { id: editTextInput chatInputPlaceholder: qsTrId("type-a-message-") - chatType: root.store.chatsModelInst.channelView.activeChannel.chatType + chatType: rootStore.chatsModelInst.channelView.activeChannel.chatType isEdit: true textInput.text: editMessageLoader.sourceText onSendMessage: { @@ -410,12 +412,13 @@ Item { text: qsTrId("save") enabled: editTextInput.textInput.text.trim().length > 0 onClicked: { - let msg = root.store.chatsModelInst.plainText(Emoji.deparse(editTextInput.textInput.text)) - if (msg.length > 0){ - msg = chatInput.interpretMessage(msg) - isEdit = false - root.store.chatsModelInst.messageView.editMessage(messageId, contentType == Constants.editType ? replaces : messageId, msg); - } + // Not Refactored Yet +// let msg = rootStore.chatsModelInst.plainText(Emoji.deparse(editTextInput.textInput.text)) +// if (msg.length > 0){ +// msg = chatInput.interpretMessage(msg) +// isEdit = false +// rootStore.chatsModelInst.messageView.editMessage(messageId, contentType == Constants.messageContentType.editType ? replaces : messageId, msg); +// } } } } @@ -427,19 +430,17 @@ Item { anchors.top: chatName.visible ? chatName.bottom : chatReply.active ? chatReply.bottom : pinnedRectangleLoader.active ? pinnedRectangleLoader.bottom : parent.top - // This entire component needs to be reworked and moved to StatusQ, hence providing a hardcoded fix for #4211. - anchors.left: parent.left - anchors.leftMargin: chatImage.imageWidth + Style.current.padding + root.chatHorizontalPadding + anchors.left: chatImage.right + anchors.leftMargin: chatHorizontalPadding anchors.right: parent.right - anchors.rightMargin: root.chatHorizontalPadding + anchors.rightMargin: chatHorizontalPadding visible: !isEdit ChatTextView { id: chatText - store: root.store - messageStore: root.messageStore - readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + root.chatHorizontalPadding + store: rootStore + readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + chatHorizontalPadding visible: { - const urls = root.linkUrls.split(" ") + const urls = linkUrls.split(" ") if (urls.length === 1 && Utils.hasImageExtension(urls[0]) && localAccountSensitiveSettings.displayChatImages) { return false } @@ -475,13 +476,13 @@ Item { imageWidth: 200 onClicked: { if (mouse.button === Qt.LeftButton) { - root.messageStore.imageClick(image) + messageStore.imageClick(image) } else if (mouse.button === Qt.RightButton) { // Set parent, X & Y positions for the messageContextMenu - messageContextMenu.parent = root - messageContextMenu.setXPosition = function() { return (mouse.x)} - messageContextMenu.setYPosition = function() { return (mouse.y)} + root.messageContextMenu.parent = root + root.messageContextMenu.setXPosition = function() { return (mouse.x)} + root.messageContextMenu.setYPosition = function() { return (mouse.y)} clickMessage(false, false, true, image, false, true, false, true, imageSource) } } @@ -492,29 +493,29 @@ Item { Loader { id: stickerLoader - active: contentType === Constants.stickerType + active: contentType === Constants.messageContentType.stickerType anchors.top: parent.top anchors.topMargin: active ? Style.current.halfPadding : 0 sourceComponent: Component { Rectangle { id: stickerContainer color: Style.current.transparent - border.color: root.isHovered ? Qt.darker(Style.current.border, 1.1) : Style.current.border + border.color: isHovered ? Qt.darker(Style.current.border, 1.1) : Style.current.border border.width: 1 radius: 16 - width: stickerId.width + 2 * root.chatVerticalPadding - height: stickerId.height + 2 * root.chatVerticalPadding + width: stickerId.width + 2 * chatVerticalPadding + height: stickerId.height + 2 * chatVerticalPadding StatusSticker { id: stickerId anchors.top: parent.top - anchors.topMargin: root.chatVerticalPadding + anchors.topMargin: chatVerticalPadding anchors.left: parent.left - anchors.leftMargin: root.chatVerticalPadding - contentType: root.contentType + anchors.leftMargin: chatVerticalPadding + contentType: contentType stickerData: sticker onLoaded: { - root.messageStore.scrollToBottom(true, root.container) + messageStore.scrollToBottom(true, root.container) } } } @@ -531,22 +532,22 @@ Item { parent.parent.parent.parent.parent.clickMessage(isProfileClick, isSticker, isImage); } onSetMessageActive: { - root.messageStore.setMessageActive(messageId, active); + setMessageActive(messageId, active); } } Loader { id: linksLoader - active: !!root.linkUrls + active: !!linkUrls anchors.top: chatText.bottom anchors.topMargin: active ? Style.current.halfPadding : 0 sourceComponent: Component { LinksMessageView { - store: root.store - linkUrls: root.linkUrls + store: rootStore + linkUrls: linkUrls container: root.container - isCurrentUser: root.isCurrentUser + isCurrentUser: isCurrentUser } } } @@ -564,28 +565,28 @@ Item { } } - Loader { - id: transactionBubbleLoader - active: contentType === Constants.transactionType - anchors.top: parent.top - anchors.topMargin: active ? (chatName.visible ? 4 : 6) : 0 - sourceComponent: Component { - TransactionBubbleView { - store: root.store - } - } - } +// Loader { +// id: transactionBubbleLoader +// active: contentType === Constants.messageContentType.transactionType +// anchors.top: parent.top +// anchors.topMargin: active ? (chatName.visible ? 4 : 6) : 0 +// sourceComponent: Component { +// TransactionBubbleView { +// store: rootStore +// } +// } +// } Loader { - active: contentType === Constants.communityInviteType + active: contentType === Constants.messageContentType.communityInviteType anchors.left: parent.left anchors.top: parent.top anchors.topMargin: active ? 8 : 0 sourceComponent: Component { id: invitationBubble InvitationBubbleView { - store: root.store - communityId: container.communityId + store: rootStore + communityId: root.container.communityId } } } @@ -599,11 +600,12 @@ Item { anchors.top: chatTime.visible ? chatTime.top : messageContent.bottom anchors.topMargin: chatTime.visible ? 0 : -4 anchors.bottom: chatTime.visible ? chatTime.bottom : undefined - isCurrentUser: root.isCurrentUser - isExpired: root.isExpired - timeout: root.timeout + isCurrentUser: isCurrentUser + isExpired: isExpired + timeout: timeout onClicked: { - root.store.chatsModelInst.messageView.resendMessage(chatId, messageId) + // Not Refactored Yet +// rootStore.chatsModelInst.messageView.resendMessage(chatId, messageId) } } } @@ -626,9 +628,10 @@ Item { HoverHandler { enabled: !activityCenterMessage && - (forceHoverHandler || (typeof messageContextMenu !== "undefined" && typeof profilePopupOpened !== "undefined" && !messageContextMenu.opened && !profilePopupOpened && !popupOpened)) + (forceHoverHandler || (typeof root.messageContextMenu !== "undefined" && typeof profilePopupOpened !== "undefined" && + !root.messageContextMenu.opened && !profilePopupOpened && !popupOpened)) onHoveredChanged: { - root.messageStore.setHovered(messageId, hovered); + setHovered(messageId, hovered); } } @@ -643,22 +646,24 @@ Item { sourceComponent: Component { EmojiReactionsPanel { id: emojiRect -// emojiReactionsModel: root.messageStore.emojiReactionsModel + emojiReactionsModel: emojiReactionsModel onHoverChanged: { - root.messageStore.setHovered(messageId, hovered) + setHovered(messageId, hovered) } -// isMessageActive: root.messageStore.isMessageActive + isMessageActive: isMessageActive + isCurrentUser: isCurrentUser onAddEmojiClicked: { root.addEmoji(false, false, false, null, true, false); // Set parent, X & Y positions for the messageContextMenu - messageContextMenu.parent = emojiReactionLoader - messageContextMenu.setXPosition = function() { return (messageContextMenu.parent.x + 4)} - messageContextMenu.setYPosition = function() { return (-messageContextMenu.height - 4)} + root.messageContextMenu.parent = emojiReactionLoader + root.messageContextMenu.setXPosition = function() { return (root.messageContextMenu.parent.x + 4)} + root.messageContextMenu.setYPosition = function() { return (-root.messageContextMenu.height - 4)} } - onToggleReaction: root.store.chatsModelInst.toggleReaction(messageId, emojiID) + // Not Refactored Yet +// onToggleReaction: rootStore.chatsModelInst.toggleReaction(messageId, emojiID) onSetMessageActive: { - root.messageStore.setMessageActive(messageId, active);; + setMessageActive(messageId, active);; } } } diff --git a/ui/imports/shared/views/chat/InvitationBubbleView.qml b/ui/imports/shared/views/chat/InvitationBubbleView.qml index 9ef4649845..83d439f88a 100644 --- a/ui/imports/shared/views/chat/InvitationBubbleView.qml +++ b/ui/imports/shared/views/chat/InvitationBubbleView.qml @@ -201,7 +201,7 @@ Item { StatusBaseText { id: invitedYou text: { - if (root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) { + if (root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne) { return isCurrentUser ? //% "You invited %1 to join a community" qsTrId("you-invited--1-to-join-a-community").arg(root.store.chatsModelInst.userNameOrAlias(root.store.chatsModelInst.channelView.activeChannel.id)) diff --git a/ui/imports/shared/views/chat/MessageContextMenuView.qml b/ui/imports/shared/views/chat/MessageContextMenuView.qml index 90523f6ddb..dff9e5bccc 100644 --- a/ui/imports/shared/views/chat/MessageContextMenuView.qml +++ b/ui/imports/shared/views/chat/MessageContextMenuView.qml @@ -324,10 +324,11 @@ StatusPopupMenu { return false switch (root.store.chatsModelInst.channelView.activeChannel.chatType) { - case Constants.chatTypePublic: return false - case Constants.chatTypeOneToOne: return true - case Constants.chatTypePrivateGroupChat: return root.store.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) - case Constants.chatTypeCommunity: return root.store.chatsModelInst.communities.activeCommunity.admin + case Constants.chatType.publicChat: return false + case Constants.chatType.profile: return false + case Constants.chatType.oneToOne: return true + case Constants.chatType.privateGroupChat: return root.store.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) + case Constants.chatType.communityChat: return root.store.chatsModelInst.communities.activeCommunity.admin } return false @@ -342,11 +343,11 @@ StatusPopupMenu { StatusMenuItem { id: deleteMessageAction enabled: isCurrentUser && !isProfile && !emojiOnly && !pinnedPopup && !isRightClickOnImage && - (contentType === Constants.messageType || - contentType === Constants.stickerType || - contentType === Constants.emojiType || - contentType === Constants.imageType || - contentType === Constants.audioType) + (contentType === Constants.messageContentType.messageType || + contentType === Constants.messageContentType.stickerType || + contentType === Constants.messageContentType.emojiType || + contentType === Constants.messageContentType.imageType || + contentType === Constants.messageContentType.audioType) //% "Delete message" text: qsTrId("delete-message") onTriggered: { diff --git a/ui/imports/shared/views/chat/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml index c9cd90527b..00efceb289 100644 --- a/ui/imports/shared/views/chat/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -18,34 +18,104 @@ Column { property var rootStore property var messageStore - property var chatsModel: !!root.rootStore ? root.rootStore.chatsModelInst : null + //property var chatsModel: !!root.rootStore ? root.rootStore.chatsModelInst : null + + property string messageId: "" + property string responseToMessageWithId: "" + property string senderId: "" + property string senderDisplayName: "" + property string senderLocalName: "" + property string senderIcon: "" + property bool isSenderIconIdenticon: true + property bool amISender: false + property string message: "" + property string messageImage: "" + property string messageTimestamp: "" + property string messageOutgoingStatus: "" + property int messageContentType: 1 + property bool pinnedMessage: false + + property int prevMessageIndex: -1 + property var prevMessageAsJsonObj + property int nextMessageIndex: -1 + property var nextMessageAsJsonObj + + property string hoveredMessage + property string activeMessage + property bool isHovered: typeof hoveredMessage !== "undefined" && hoveredMessage === messageId + property bool isMessageActive: typeof activeMessage !== "undefined" && activeMessage === messageId + + function setHovered(messageId, hovered) { + if (hovered) { + hoveredMessage = messageId; + } else if (hoveredMessage === messageId) { + hoveredMessage = ""; + } + } + + function setMessageActive(messageId, active) { + if (active) { + activeMessage = messageId; + } else if (activeMessage === messageId) { + activeMessage = ""; + } + } + + // Legacy + property string responseTo: responseToMessageWithId + property bool isCurrentUser: amISender + property int contentType: messageContentType + property string timestamp: messageTimestamp + property string displayUserName: senderDisplayName + property string outgoingStatus: messageOutgoingStatus + property string authorCurrentMsg: senderId + property string authorPrevMsg: { + if(!prevMessageAsJsonObj) + return "" + + return prevMessageAsJsonObj.senderId + } + property string prevMsgTimestamp: { + if(!prevMessageAsJsonObj) + return "" + + return prevMessageAsJsonObj.timestamp + } + property string nextMsgTimestamp: { + if(!nextMessageAsJsonObj) + return "" + + return nextMessageAsJsonObj.timestamp + } + + property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval ////////////////////////////////////// //TODO REMOVE - property string fromAuthor: "0x0011223344556677889910" - property string userName: "Jotaro Kujo" - property string alias: "" - property string localName: "" - property string message: "That's right. We're friends... Of justice, that is." +// property string fromAuthor: "0x0011223344556677889910" +// property string userName: "Jotaro Kujo" +// property string alias: "" +// property string localName: "" +// property string message: "That's right. We're friends... Of justice, that is." property string plainText: "That's right. We're friends... Of justice, that is." - property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg==" - property bool isCurrentUser: false - property string timestamp: "1234567" +// property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg==" +// property bool isCurrentUser: false +// property string timestamp: "1234567" property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v" - property int contentType: 1 // constants don't work in default props +// property int contentType: 1 // constants don't work in default props property string chatId: "chatId" - property string outgoingStatus: "" - property string responseTo: "" - property string messageId: "" +// property string outgoingStatus: "" +// property string responseTo: "" +// property string messageId: "" property string emojiReactions: "" - property int prevMessageIndex: -1 - property int nextMessageIndex: -1 +// property int prevMessageIndex: -1 +// property int nextMessageIndex: -1 property bool timeout: false property bool hasMention: false property string linkUrls: "" property bool placeholderMessage: false property bool activityCenterMessage: false - property bool pinnedMessage: false +// property bool pinnedMessage: false property bool read: true property string pinnedBy property bool forceHoverHandler: false // Used to force the HoverHandler to be active (useful for messages in popups) @@ -58,172 +128,179 @@ Column { property bool isEdited: false property bool showEdit: true property var messageContextMenu - property string displayUserName: { - if (isCurrentUser) { - //% "You" - return qsTrId("You") - } +// property string displayUserName: { +// if (isCurrentUser) { +// //% "You" +// return qsTrId("You") +// } - if (localName !== "") { - return localName - } +// if (localName !== "") { +// return localName +// } - if (userName !== "") { - return Utils.removeStatusEns(userName) - } - return Utils.removeStatusEns(alias) - } +// if (userName !== "") { +// return Utils.removeStatusEns(userName) +// } +// return Utils.removeStatusEns(alias) +// } - property string authorCurrentMsg: "authorCurrentMsg" - property string authorPrevMsg: "authorPrevMsg" +// property string authorCurrentMsg: "authorCurrentMsg" +// property string authorPrevMsg: "authorPrevMsg" - property string prevMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(prevMessageIndex, "timestamp") : "" - property string nextMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(nextMessageIndex, "timestamp"): "" +// property string prevMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(prevMessageIndex, "timestamp") : "" +// property string nextMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(nextMessageIndex, "timestamp"): "" - property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval +// property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval - property bool isEmoji: contentType === Constants.emojiType - property bool isImage: contentType === Constants.imageType - property bool isAudio: contentType === Constants.audioType - property bool isStatusMessage: contentType === Constants.systemMessagePrivateGroupType - property bool isSticker: contentType === Constants.stickerType - property bool isText: contentType === Constants.messageType || contentType === Constants.editType + property bool isEmoji: contentType === Constants.messageContentType.emojiType + property bool isImage: contentType === Constants.messageContentType.imageType + property bool isAudio: contentType === Constants.messageContentType.audioType + property bool isStatusMessage: contentType === Constants.messageContentType.systemMessagePrivateGroupType + property bool isSticker: contentType === Constants.messageContentType.stickerType + property bool isText: contentType === Constants.messageContentType.messageType || contentType === Constants.messageContentType.editType property bool isMessage: isEmoji || isImage || isSticker || isText || isAudio - || contentType === Constants.communityInviteType || contentType === Constants.transactionType + || contentType === Constants.messageContentType.communityInviteType || contentType === Constants.messageContentType.transactionType property bool isExpired: (outgoingStatus === "sending" && (Math.floor(timestamp) + 180000) < Date.now()) + property bool isStatusUpdate: false property int statusAgeEpoch: 0 - property int replyMessageIndex: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageIndex(responseTo) : -1 - property string repliedMessageAuthor: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName") : "" : ""; - property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "publicKey") : ""; - property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === userProfile.pubKey : ""; - property bool repliedMessageIsEdited: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "isEdited") === "true" : false : false; - property string repliedMessageContent: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message") : "" : ""; - property int repliedMessageType: replyMessageIndex > -1 ? !!root.chatsModel ? parseInt(root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "contentType")) : 0 : 0; - property string repliedMessageImage: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "image") : "" : ""; - property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon") : "" : ""; - property string repliedMessageUserImage: replyMessageIndex > -1 ? appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser , false) || "" : ""; + // TODO: we don't use replyMessageIndex any more, but messageId +// property int replyMessageIndex: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageIndex(responseTo) : -1 +// property string repliedMessageAuthor: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName") : "" : ""; +// property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "publicKey") : ""; +// property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === userProfile.pubKey : ""; +// property bool repliedMessageIsEdited: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "isEdited") === "true" : false : false; +// property string repliedMessageContent: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message") : "" : ""; +// property int repliedMessageType: replyMessageIndex > -1 ? !!root.chatsModel ? parseInt(root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "contentType")) : 0 : 0; +// property string repliedMessageImage: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "image") : "" : ""; +// property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon") : "" : ""; +// property string repliedMessageUserImage: replyMessageIndex > -1 ? appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser , false) || "" : ""; property var imageClick: function () {} property var scrollToBottom: function () {} - property string userPubKey: { - if (contentType === Constants.chatIdentifier) { - return chatId - } - return fromAuthor - } - property bool useLargeImage: contentType === Constants.chatIdentifier +// property string userPubKey: { +// if (contentType === Constants.messageContentType.chatIdentifier) { +// return chatId +// } +// return fromAuthor +// } +// property bool useLargeImage: contentType === Constants.messageContentType.chatIdentifier - property string profileImageSource: !placeholderMessage && appMain.getProfileImage(userPubKey, isCurrentUser, useLargeImage) || "" + // Not Refactored Yet - This will be determined on the backend +// property string profileImageSource: !placeholderMessage && appMain.getProfileImage(userPubKey, isCurrentUser, useLargeImage) || "" property var emojiReactionsModel: { - if (!emojiReactions) { - return [] - } + // Not Refactored Yet + return [] +// if (!emojiReactions) { +// return [] +// } - try { - // group by id - var allReactions = Object.values(JSON.parse(emojiReactions)) - var byEmoji = {} - allReactions.forEach(function (reaction) { - if (!byEmoji[reaction.emojiId]) { - byEmoji[reaction.emojiId] = { - emojiId: reaction.emojiId, - fromAccounts: [], - count: 0, - currentUserReacted: false - } - } - byEmoji[reaction.emojiId].count++; - byEmoji[reaction.emojiId].fromAccounts.push(root.chatsModel.userNameOrAlias(reaction.from)); - if (!byEmoji[reaction.emojiId].currentUserReacted && reaction.from === userProfile.pubKey) { - byEmoji[reaction.emojiId].currentUserReacted = true - } +// try { +// // group by id +// var allReactions = Object.values(JSON.parse(emojiReactions)) +// var byEmoji = {} +// allReactions.forEach(function (reaction) { +// if (!byEmoji[reaction.emojiId]) { +// byEmoji[reaction.emojiId] = { +// emojiId: reaction.emojiId, +// fromAccounts: [], +// count: 0, +// currentUserReacted: false +// } +// } +// byEmoji[reaction.emojiId].count++; +// byEmoji[reaction.emojiId].fromAccounts.push(root.chatsModel.userNameOrAlias(reaction.from)); +// if (!byEmoji[reaction.emojiId].currentUserReacted && reaction.from === userProfile.pubKey) { +// byEmoji[reaction.emojiId].currentUserReacted = true +// } - }) - return Object.values(byEmoji) - } catch (e) { - console.error('Error parsing emoji reactions', e) - return [] - } +// }) +// return Object.values(byEmoji) +// } catch (e) { +// console.error('Error parsing emoji reactions', e) +// return [] +// } } property var clickMessage: function(isProfileClick, isSticker = false, isImage = false, image = null, emojiOnly = false, hideEmojiPicker = false, isReply = false, isRightClickOnImage = false, imageSource = "") { - if (placeholderMessage || activityCenterMessage) { - return - } + // Not Refactored Yet +// if (placeholderMessage || activityCenterMessage) { +// return +// } - if (!isProfileClick) { - SelectedMessage.set(messageId, fromAuthor); - } +// if (!isProfileClick) { +// SelectedMessage.set(messageId, fromAuthor); +// } - messageContextMenu.messageId = root.messageId - messageContextMenu.contentType = root.contentType - messageContextMenu.linkUrls = root.linkUrls; - messageContextMenu.isProfile = !!isProfileClick; - messageContextMenu.isCurrentUser = root.isCurrentUser - messageContextMenu.isText = root.isText - messageContextMenu.isSticker = isSticker; - messageContextMenu.emojiOnly = emojiOnly; - messageContextMenu.hideEmojiPicker = hideEmojiPicker; - messageContextMenu.pinnedMessage = pinnedMessage; - messageContextMenu.isCurrentUser = isCurrentUser; - messageContextMenu.isRightClickOnImage = isRightClickOnImage - messageContextMenu.imageSource = imageSource - messageContextMenu.onClickEdit = function() {root.isEdit = true} +// messageContextMenu.messageId = root.messageId +// messageContextMenu.contentType = root.contentType +// messageContextMenu.linkUrls = root.linkUrls; +// messageContextMenu.isProfile = !!isProfileClick; +// messageContextMenu.isCurrentUser = root.isCurrentUser +// messageContextMenu.isText = root.isText +// messageContextMenu.isSticker = isSticker; +// messageContextMenu.emojiOnly = emojiOnly; +// messageContextMenu.hideEmojiPicker = hideEmojiPicker; +// messageContextMenu.pinnedMessage = pinnedMessage; +// messageContextMenu.isCurrentUser = isCurrentUser; +// messageContextMenu.isRightClickOnImage = isRightClickOnImage +// messageContextMenu.imageSource = imageSource +// messageContextMenu.onClickEdit = function() {root.isEdit = true} - if (isReply) { - let nickname = appMain.getUserNickname(repliedMessageAuthor) - messageContextMenu.show(repliedMessageAuthor, repliedMessageAuthorPubkey, repliedMessageUserImage || repliedMessageUserIdenticon, plainText, nickname, emojiReactionsModel); - } else { - let nickname = appMain.getUserNickname(fromAuthor) - messageContextMenu.show(userName, fromAuthor, root.profileImageSource || identicon, plainText, nickname, emojiReactionsModel); - } +// if (isReply) { +// let nickname = appMain.getUserNickname(repliedMessageAuthor) +// messageContextMenu.show(repliedMessageAuthor, repliedMessageAuthorPubkey, repliedMessageUserImage || repliedMessageUserIdenticon, plainText, nickname, emojiReactionsModel); +// } else { +// let nickname = appMain.getUserNickname(fromAuthor) +// messageContextMenu.show(userName, fromAuthor, root.profileImageSource || identicon, plainText, nickname, emojiReactionsModel); +// } - messageContextMenu.x = messageContextMenu.setXPosition() - messageContextMenu.y = messageContextMenu.setYPosition() +// messageContextMenu.x = messageContextMenu.setXPosition() +// messageContextMenu.y = messageContextMenu.setYPosition() } - function showReactionAuthors(fromAccounts, emojiId) { - return root.rootStore.showReactionAuthors(fromAccounts, emojiId) - } +// function showReactionAuthors(fromAccounts, emojiId) { +// return root.rootStore.showReactionAuthors(fromAccounts, emojiId) +// } - function startMessageFoundAnimation() { - messageLoader.item.startMessageFoundAnimation(); - } +// function startMessageFoundAnimation() { +// messageLoader.item.startMessageFoundAnimation(); +// } ///////////////////////////////////////////// - Connections { - enabled: (!placeholderMessage && !!root.rootStore) - target: !!root.rootStore ? root.rootStore.allContacts : null - onContactChanged: { - if (pubkey === fromAuthor) { - const img = appMain.getProfileImage(userPubKey, isCurrentUser, useLargeImage) - if (img) { - profileImageSource = img - } - } else if (replyMessageIndex > -1 && pubkey === repliedMessageAuthorPubkey) { - const imgReply = appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser, false) - if (imgReply) { - repliedMessageUserImage = imgReply - } - } - } - } + // Not Refactored Yet +// Connections { +// enabled: (!placeholderMessage && !!root.rootStore) +// target: !!root.rootStore ? root.rootStore.allContacts : null +// onContactChanged: { +// if (pubkey === fromAuthor) { +// const img = appMain.getProfileImage(userPubKey, isCurrentUser, useLargeImage) +// if (img) { +// profileImageSource = img +// } +// } else if (replyMessageIndex > -1 && pubkey === repliedMessageAuthorPubkey) { +// const imgReply = appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser, false) +// if (imgReply) { +// repliedMessageUserImage = imgReply +// } +// } +// } +// } - Connections { - enabled: !!root.rootStore - target: !!root.rootStore ? root.chatsModel.messageView : null - onHideMessage: { - // This hack is used because message_list deleteMessage sometimes does not remove the messages (there might be an issue with the delegate model) - if(mId === messageId){ - root.visible = 0; - root.height = 0; - } - } - } +// Connections { +// enabled: !!root.rootStore +// target: !!root.rootStore ? root.chatsModel.messageView : null +// onHideMessage: { +// // This hack is used because message_list deleteMessage sometimes does not remove the messages (there might be an issue with the delegate model) +// if(mId === messageId){ +// root.visible = 0; +// root.height = 0; +// } +// } +// } Loader { id: messageLoader @@ -231,16 +308,17 @@ Column { width: parent.width sourceComponent: { switch(contentType) { - case Constants.chatIdentifier: + case Constants.messageContentType.chatIdentifier: return channelIdentifierComponent - case Constants.fetchMoreMessagesButton: + case Constants.messageContentType.fetchMoreMessagesButton: return fetchMoreMessagesButtonComponent - case Constants.systemMessagePrivateGroupType: + case Constants.messageContentType.systemMessagePrivateGroupType: return privateGroupHeaderComponent - case Constants.gapType: + case Constants.messageContentType.gapType: return gapComponent default: - return localAccountSensitiveSettings.useCompactMode ? compactMessageComponent : messageComponent + return isStatusUpdate ? statusUpdateComponent : + (localAccountSensitiveSettings.useCompactMode ? compactMessageComponent : messageComponent) } } @@ -250,9 +328,10 @@ Column { id: gapComponent GapComponent { onClicked: { - root.chatsModel.messageView.fillGaps(messageStore.messageId); - root.visible = false; - root.height = 0; + // Not Refactored Yet +// root.chatsModel.messageView.fillGaps(messageStore.messageId); +// root.visible = false; +// root.height = 0; } } } @@ -260,19 +339,32 @@ Column { Component { id: fetchMoreMessagesButtonComponent FetchMoreMessagesButton { +// nextMessageIndex: root.messageStore.nextMessageIndex +// nextMsgTimestamp: root.messageStore.nextMsgTimestamp + onClicked: { + // Not Refactored Yet +// root.chatsModel.messageView.hideLoadingIndicator(); + } onTimerTriggered: { - root.chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours); + // Not Refactored Yet +// root.chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours); } } } Component { id: channelIdentifierComponent - ChannelIdentifierView { - store: root.rootStore - profileImage: profileImageSource - authorCurrentMsg: root.authorCurrentMsg + Rectangle { + color: "blue" + width: 100 + height: 100 } + // Not Refactored Yet +// ChannelIdentifierView { +// store: root.rootStore +// profileImage: profileImageSource +// authorCurrentMsg: root.authorCurrentMsg +// } } // Private group Messages @@ -309,32 +401,43 @@ Column { Component { id: messageComponent NormalMessageView { - linkUrls: root.linkUrls - isCurrentUser: root.isCurrentUser - isExpired: root.isExpired - timeout: root.timeout - contentType: root.contentType + container: root + } + } + + Component { + id: statusUpdateComponent + StatusUpdateView { + statusAgeEpoch: root.statusAgeEpoch container: root store: root.rootStore - messageStore: root.messageStore + messageContextMenu: root.messageContextMenu + onAddEmoji: { + root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker); + } + onChatImageClicked: { + messageStore.imageClick(image); + } + onUserNameClicked: { + root.parent.clickMessage(isProfileClick); + } + onEmojiBtnClicked: { + root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly); + } + onClickMessage: { + root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); + } + onSetMessageActive: { + root.messageStore.setMessageActive(messageId, active);; + } } } Component { id: compactMessageComponent CompactMessageView { - linkUrls: root.linkUrls - isCurrentUser: root.isCurrentUser - isExpired: root.isExpired - timeout: root.timeout - contentType: root.contentType - showEdit: root.showEdit - container: root messageContextMenu: root.messageContextMenu - store: root.rootStore - messageStore: root.messageStore - repliedMessageUserIdenticon: root.repliedMessageUserIdenticon - repliedMessageUserImage: root.repliedMessageUserImage + container: root onAddEmoji: { root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker); } diff --git a/ui/imports/shared/views/chat/NormalMessageView.qml b/ui/imports/shared/views/chat/NormalMessageView.qml index afbaea6554..58dcad2e2e 100644 --- a/ui/imports/shared/views/chat/NormalMessageView.qml +++ b/ui/imports/shared/views/chat/NormalMessageView.qml @@ -13,13 +13,7 @@ Item { height: childrenRect.height + this.anchors.topMargin + (dateGroupLbl.visible ? dateGroupLbl.height : 0) width: parent.width - property var store - property var messageStore - property string linkUrls: "" - property bool isCurrentUser: false - property bool isExpired: false - property bool timeout: false - property int contentType: 2 + property var container property bool headerRepeatCondition: (authorCurrentMsg !== authorPrevMsg || shouldRepeatHeader || dateGroupLbl.visible) @@ -34,15 +28,13 @@ Item { UserImage { id: chatImage - active: root.store.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && headerRepeatCondition && !root.isCurrentUser + //active: rootStore.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatType.oneToOne && isMessage && headerRepeatCondition && !root.isCurrentUser anchors.left: parent.left anchors.leftMargin: Style.current.padding anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top anchors.topMargin: 20 -// isCurrentUser: root.messageStore.isCurrentUser -// profileImage: root.messageStore.profileImageSource -// isMessage: root.messageStore.isMessage -// identiconImageSource: root.messageStore.identicon + icon: senderIcon + isIdenticon: isSenderIconIdenticon onClickMessage: { root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); } @@ -50,15 +42,14 @@ Item { UsernameLabel { id: chatName - visible: root.store.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatTypeOneToOne && isMessage && headerRepeatCondition && !root.isCurrentUser + //visible: rootStore.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatType.oneToOne && isMessage && headerRepeatCondition && !root.isCurrentUser anchors.leftMargin: 20 anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top anchors.topMargin: 0 anchors.left: chatImage.right -// isCurrentUser: root.messageStore.isCurrentUser -// userName: root.messageStore.userName -// localName: root.messageStore.localName -// displayUserName: root.messageStore.displayUserName + displayName: senderDisplayName + localName: senderLocalName + amISender: amISender onClickMessage: { root.parent.clickMessage(true, false, false, null, false, false, false); } @@ -72,9 +63,11 @@ Item { property int chatVerticalPadding: isImage ? 4 : 6 property int chatHorizontalPadding: isImage ? 0 : 12 property bool longReply: chatReply.active && repliedMessageContent.length > maxMessageChars - property bool longChatText: root.store.chatsModelInst.plainText(root.messageStore.message).split('\n').some(function (messagePart) { - return messagePart.length > maxMessageChars - }) + property bool longChatText: false + // Not Refactored Yet +// property bool longChatText: rootStore.chatsModelInst.plainText(messageStore.message).split('\n').some(function (messagePart) { +// return messagePart.length > maxMessageChars +// }) id: chatBox color: { @@ -91,10 +84,10 @@ Item { height: { let h = (3 * chatVerticalPadding) switch(contentType){ - case Constants.stickerType: + case Constants.messageContentType.stickerType: h += stickerId.height; break; - case Constants.audioType: + case Constants.messageContentType.audioType: h += audioPlayerLoader.height; break; default: @@ -110,9 +103,9 @@ Item { } width: { switch(contentType) { - case Constants.stickerType: + case Constants.messageContentType.stickerType: return stickerId.width + (2 * chatBox.chatHorizontalPadding); - case Constants.imageType: + case Constants.messageContentType.imageType: return chatImageContent.width default: if (longChatText || longReply) { @@ -134,13 +127,13 @@ Item { } radius: 16 - anchors.left: !root.isCurrentUser ? chatImage.right : undefined - anchors.leftMargin: !root.isCurrentUser ? 8 : 0 - anchors.right: !root.isCurrentUser ? undefined : parent.right - anchors.rightMargin: !root.isCurrentUser ? 0 : Style.current.padding - anchors.top: headerRepeatCondition && !root.isCurrentUser ? chatImage.top : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top) + anchors.left: !isCurrentUser ? chatImage.right : undefined + anchors.leftMargin: !isCurrentUser ? 8 : 0 + anchors.right: !isCurrentUser ? undefined : parent.right + anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding + anchors.top: headerRepeatCondition && !isCurrentUser ? chatImage.top : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top) anchors.topMargin: 0 - visible: isMessage && contentType !== Constants.transactionType + visible: isMessage && contentType !== Constants.messageContentType.transactionType ChatReplyPanel { id: chatReply @@ -153,34 +146,44 @@ Item { anchors.rightMargin: chatBox.chatHorizontalPadding container: root.container chatHorizontalPadding: chatBox.chatHorizontalPadding - stickerData: root.store.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "sticker") - active: responseTo !== "" && replyMessageIndex > -1 && !activityCenterMessage -// To-Do move to store later? -// isCurrentUser: root.messageStore.isCurrentUser -// repliedMessageType: root.messageStore.repliedMessageType -// repliedMessageImage: root.messageStore.repliedMessageImage -// repliedMessageUserIdenticon: root.messageStore.repliedMessageUserIdenticon -// repliedMessageIsEdited: root.messageStore.repliedMessageIsEdited -// repliedMessageUserImage: root.messageStore.repliedMessageUserImage -// repliedMessageAuthor: root.messageStore.repliedMessageAuthor -// repliedMessageContent: root.messageStore.repliedMessageContent -// responseTo: root.messageStore.responseTo -// onScrollToBottom: { -// root.messageStore.scrollToBottom(isit, container); -// } + // Not Refactored Yet + //stickerData: rootStore.chatsModelInst.messageView.messageList.getMessageData(replyMessageIndex, "sticker") + active: responseTo !== "" && !activityCenterMessage + + Component.onCompleted: { + let obj = messageStore.getMessageByIdAsJson(messageId) + if(!obj) + return + + amISenderOfTheRepliedMessage = obj.amISender + repliedMessageContentType = obj.contentType + repliedMessageSenderIcon = obj.senderIcon + repliedMessageSenderIconIsIdenticon = obj.isSenderIconIdenticon + // TODO: not sure about is edited at the moment + repliedMessageIsEdited = false + repliedMessageSender = obj.senderDisplayName + repliedMessageContent = obj.messageText + repliedMessageImage = obj.messageImage + } + + onScrollToBottom: { + // Not Refactored Yet +// messageStore.scrollToBottom(isit, root.container); + } onClickMessage: { - root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); + // Not Refactored Yet +// root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); } } - Connections { - target: root.store.chatsModelInst.messageView - onMessageEdited: { - if(chatReply.item) - chatReply.item.messageEdited(editedMessageId, editedMessageContent) - } - } +// Connections { +// target: rootStore.chatsModelInst.messageView +// onMessageEdited: { +// if(chatReply.item) +// chatReply.item.messageEdited(editedMessageId, editedMessageContent) +// } +// } ChatTextView { id: chatText @@ -191,9 +194,8 @@ Item { anchors.leftMargin: chatBox.chatHorizontalPadding anchors.right: chatBox.longChatText ? parent.right : undefined anchors.rightMargin: chatBox.longChatText ? chatBox.chatHorizontalPadding : 0 - store: root.store - messageStore: root.store.messageStore - textField.color: !root.isCurrentUser ? Style.current.textColor : Style.current.currentUserTextColor + store: rootStore + textField.color: !isCurrentUser ? Style.current.textColor : Style.current.currentUserTextColor Connections { target: localAccountSensitiveSettings.useCompactMode ? null : chatBox onLongChatTextChanged: { @@ -202,15 +204,16 @@ Item { } onLinkActivated: { - if (root.messageStore.activityCenterMessage) { - clickMessage(false, root.messageStore.isSticker, false) - } + // Not Refactored Yet +// if (activityCenterMessage) { +// clickMessage(false, isSticker, false) +// } } } Loader { id: chatImageContent - active: root.messageStore.isImage && !!image + active: isImage && !!image anchors.top: parent.top anchors.topMargin: Style.current.smallPadding anchors.left: parent.left @@ -226,7 +229,7 @@ Item { id: chatImageComponent imageSource: image imageWidth: 250 - isCurrentUser: root.isCurrentUser + isCurrentUser: isCurrentUser onClicked: imageClick(image) container: root.container } @@ -236,7 +239,7 @@ Item { Loader { id: audioPlayerLoader - active: root.messageStore.isAudio + active: isAudio sourceComponent: audioPlayer anchors.verticalCenter: parent.verticalCenter } @@ -255,42 +258,44 @@ Item { anchors.top: parent.top anchors.topMargin: chatBox.chatVerticalPadding color: Style.current.transparent - contentType: root.contentType - stickerData: root.messageStore.sticker + contentType: contentType + stickerData: sticker onLoaded: { - root.messageStore.scrollToBottom(true, root.container) + // Not Refactored Yet + //messageStore.scrollToBottom(true, root.container) } } MessageMouseArea { anchors.fill: parent enabled: !chatText.linkHovered - isActivityCenterMessage: root.messageStore.activityCenterMessage + isActivityCenterMessage: activityCenterMessage onClickMessage: { - root.parent.clickMessage(isProfileClick, root.messageStore.isSticker, root.messageStore.isImage) + // Not Refactored Yet + //root.parent.clickMessage(isProfileClick, isSticker, isImage) } onSetMessageActive: { - root.messageStore.setMessageActive(root.messageStore.messageId, active); + setMessageActive(messageId, active); } } RectangleCorner { // TODO find a way to show the corner for stickers since they have a border - visible: root.messageStore.isMessage - isCurrentUser: root.isCurrentUser + visible: isMessage + isCurrentUser: isCurrentUser } } Loader { id: transactionBubbleLoader - active: contentType === Constants.transactionType + active: contentType === Constants.messageContentType.transactionType anchors.left: !isCurrentUser ? chatImage.right : undefined anchors.leftMargin: isCurrentUser ? 0 : Style.current.halfPadding anchors.right: isCurrentUser ? parent.right : undefined anchors.rightMargin: Style.current.padding sourceComponent: Component { TransactionBubbleView { - store: root.store + store: rootStore } } } @@ -311,19 +316,18 @@ Item { ChatTimePanel { id: chatTime - visible: root.messageStore.isMessage && !emojiReactionLoader.active + visible: isMessage && !emojiReactionLoader.active anchors.top: isImage ? undefined : (linksLoader.active ? linksLoader.bottom : chatBox.bottom) anchors.topMargin: isImage ? 0 : 4 anchors.verticalCenter: isImage ? dateTimeBackground.verticalCenter : undefined anchors.right: isImage ? dateTimeBackground.right : (linksLoader.active ? linksLoader.right : chatBox.right) - anchors.rightMargin: isImage ? 6 : (root.isCurrentUser ? 5 : Style.current.padding) - //timestamp: root.messageStore.timestamp + anchors.rightMargin: isImage ? 6 : (isCurrentUser ? 5 : Style.current.padding) + timestamp: timestamp } SentMessage { id: sentMessage - visible: root.isCurrentUser && !root.messageStore.timeout && !root.messageStore.isExpired - && root.messageStore.isMessage && root.messageStore.outgoingStatus === "sent" + visible: isCurrentUser && !timeout && !isExpired && isMessage && outgoingStatus === "sent" anchors.verticalCenter: chatTime.verticalCenter anchors.right: chatTime.left anchors.rightMargin: 5 @@ -334,31 +338,32 @@ Item { anchors.verticalCenter: chatTime.verticalCenter anchors.right: chatTime.left anchors.rightMargin: 5 - isCurrentUser: root.isCurrentUser - isExpired: root.isExpired - timeout: root.timeout + isCurrentUser: isCurrentUser + isExpired: isExpired + timeout: timeout onClicked: { - root.store.chatsModelInst.messageView.resendMessage(chatId, messageId) + // Not Refactored Yet +// rootStore.chatsModelInst.messageView.resendMessage(chatId, messageId) } } Loader { id: linksLoader - active: !!root.linkUrls - anchors.left: !root.isCurrentUser ? chatImage.right : undefined - anchors.leftMargin: !root.isCurrentUser ? 8 : 0 - anchors.right: !root.isCurrentUser ? undefined : parent.right - anchors.rightMargin: !root.isCurrentUser ? 0 : Style.current.padding + active: !!linkUrls + anchors.left: !isCurrentUser ? chatImage.right : undefined + anchors.leftMargin: !isCurrentUser ? 8 : 0 + anchors.right: !isCurrentUser ? undefined : parent.right + anchors.rightMargin: !isCurrentUser ? 0 : Style.current.padding anchors.top: chatBox.bottom anchors.topMargin: Style.current.halfPadding anchors.bottomMargin: Style.current.halfPadding sourceComponent: Component { LinksMessageView { - store: root.store - linkUrls: root.linkUrls + store: rootStore + linkUrls: linkUrls container: root.container - isCurrentUser: root.isCurrentUser + isCurrentUser: isCurrentUser } } } @@ -367,9 +372,9 @@ Item { id: emojiReactionLoader active: emojiReactions !== "" sourceComponent: emojiReactionsComponent - anchors.left: root.isCurrentUser ? undefined : chatBox.left - anchors.right: root.isCurrentUser ? chatBox.right : undefined - anchors.leftMargin: root.isCurrentUser ? Style.current.halfPadding : 1 + anchors.left: isCurrentUser ? undefined : chatBox.left + anchors.right: isCurrentUser ? chatBox.right : undefined + anchors.leftMargin: isCurrentUser ? Style.current.halfPadding : 1 anchors.top: chatBox.bottom anchors.topMargin: 2 } @@ -377,12 +382,13 @@ Item { Component { id: emojiReactionsComponent EmojiReactionsPanel { -// isMessageActive: root.store.messageStore.isMessageActive -// emojiReactionsModel: root.store.messageStore.emojiReactionsModel + isMessageActive: isMessageActive + emojiReactionsModel: emojiReactionsModel onSetMessageActive: { - root.store.messageStore.setMessageActive(messageId, active);; + setMessageActive(messageId, active);; } - onToggleReaction: root.store.chatsModelInst.toggleReaction(messageId, emojiID) + // Not Refactored Yet + //onToggleReaction: rootStore.chatsModelInst.toggleReaction(messageId, emojiID) } } } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 19ab934f34..c6a1a600c1 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -47,16 +47,37 @@ QtObject { readonly property int idle: 3 } + readonly property QtObject chatType: QtObject{ + readonly property int unknown: 0 + readonly property int oneToOne: 1 + readonly property int publicChat: 2 + readonly property int privateGroupChat: 3 + readonly property int profile: 4 + readonly property int timeline: 5 + readonly property int communityChat: 6 + } + + readonly property QtObject messageContentType: QtObject { + readonly property int fetchMoreMessagesButton: -2 + readonly property int chatIdentifier: -1 + readonly property int unknownContentType: 0 + readonly property int messageType: 1 + readonly property int stickerType: 2 + readonly property int statusType: 3 + readonly property int emojiType: 4 + readonly property int transactionType: 5 + readonly property int systemMessagePrivateGroupType: 6 + readonly property int imageType: 7 + readonly property int audioType: 8 + readonly property int communityInviteType: 9 + readonly property int gapType: 10 + readonly property int editType: 11 + } + readonly property int communityImported: 0 readonly property int communityImportingInProgress: 1 readonly property int communityImportingError: 2 - readonly property int chatTypeOneToOne: 1 - readonly property int chatTypePublic: 2 - readonly property int chatTypePrivateGroupChat: 3 - readonly property int chatTypeStatusUpdate: 4 - readonly property int chatTypeCommunity: 6 - readonly property int communityChatPublicAccess: 1 readonly property int communityChatInvitationOnlyAccess: 2 readonly property int communityChatOnRequestAccess: 3 @@ -96,20 +117,6 @@ QtObject { readonly property int notificationPreviewAnonymous: 0 readonly property int notificationPreviewNameOnly: 1 readonly property int notificationPreviewNameAndMessage: 2 - readonly property int fetchMoreMessagesButton: -2 - readonly property int chatIdentifier: -1 - readonly property int unknownContentType: 0 - readonly property int messageType: 1 - readonly property int stickerType: 2 - readonly property int statusType: 3 - readonly property int emojiType: 4 - readonly property int transactionType: 5 - readonly property int systemMessagePrivateGroupType: 6 - readonly property int imageType: 7 - readonly property int audioType: 8 - readonly property int communityInviteType: 9 - readonly property int gapType: 10 - readonly property int editType: 11 readonly property string watchWalletType: "watch" readonly property string keyWalletType: "key" diff --git a/ui/main.qml b/ui/main.qml index 16225207bb..ef32f0ce1c 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -426,9 +426,9 @@ StatusWindow { (loader.item.appLayout.appView.currentIndex === Constants.appViewStackIndex.chat && ( // in a one-to-one chat - chatsModel.channelView.activeChannel.chatType === Constants.chatTypeOneToOne || + chatsModel.channelView.activeChannel.chatType === Constants.chatType.oneToOne || // in a private group chat - chatsModel.channelView.activeChannel.chatType === Constants.chatTypePrivateGroupChat + chatsModel.channelView.activeChannel.chatType === Constants.chatType.privateGroupChat ) ) || // in timeline view