refactor(@desktop/chat-communities): qml part handles messages from refactored backend

- `chatType` added to `Constants` to group chat type related values
- `messageContentType` added to `Constants` to group message content type related
values
- `MessageStore` maintained per message list now
- added new `ChatContentView` component used to display chat/channel content
- components updated to display messages from the new backend
- `StatusChatToolBar` appropriately updated
- mute/unmute feature added to chat/channel list as well as to `StatusChatToolBar`
This commit is contained in:
Sale Djenic 2021-12-09 13:53:40 +01:00
parent bd2efb4a1e
commit e5a414a927
40 changed files with 1801 additions and 1477 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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) {

View File

@ -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: {

View File

@ -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;
// }
}
}
}
}
}

View File

@ -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();
// }
}
}
}

View File

@ -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: {

View File

@ -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);

View File

@ -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
openHandler: function (id) {
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)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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;
// }
}
}

View File

@ -330,7 +330,6 @@ Item {
width: parent.width
anchors.right: parent.right
store: root.store
messageStore: root.messageStore
}
RectangleCorner {}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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();

View File

@ -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

View File

@ -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 {

View File

@ -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"

View File

@ -12,7 +12,7 @@ Loader {
signal loaded()
id: root
active: contentType === Constants.stickerType
active: contentType === Constants.messageContentType.stickerType
sourceComponent: Component {
ImageLoader {

View File

@ -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 <span style='color: %1'>%2</span> 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 <span style='color: %1'>%2</span>"
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

View File

@ -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);

View File

@ -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);;
}
}
}

View File

@ -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))

View File

@ -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: {

View File

@ -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);
}

View File

@ -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)
}
}
}

View File

@ -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"

View File

@ -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