status-desktop/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml

264 lines
10 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import QtGraphicalEffects 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
import StatusQ.Popups.Dialog 0.1
import utils 1.0
import shared.views.chat 1.0
import shared.stores 1.0 as SharedStores
import AppLayouts.Chat.stores 1.0
StatusDialog {
id: root
property SharedStores.RootStore sharedStore
property SharedStores.UtilsStore utilsStore
property RootStore store
property MessageStore messageStore
property var pinnedMessagesModel //this doesn't belong to the messageStore, it is a part of the ChatContentStore, but we didn't introduce it yet.
property string messageToPin
property string messageToUnpin
property string chatId
readonly property var contactDetails: store ? store.oneToOneChatContact : null
readonly property bool isPinActionAvaliable: contactDetails ? contactDetails.isContact : true
width: 800
height: 428
padding: 0
title: root.messageToPin ? qsTr("Pin limit reached") : qsTr("Pinned messages")
subtitle: root.messageToPin ? qsTr("Unpin a previous message first")
: qsTr("%n message(s)", "", pinnedMessageListView.count)
QtObject {
id: d
function jumpToMessage(messageId) {
root.close()
root.messageStore.messageModule.jumpToMessage(messageId)
}
}
contentItem: ColumnLayout {
id: column
StatusBaseText {
visible: pinnedMessageListView.count === 0
text: qsTr("Pinned messages will appear here.")
Layout.alignment: Qt.AlignCenter
verticalAlignment: Text.AlignVCenter
color: Theme.palette.secondaryText
}
ButtonGroup {
id: pinButtonGroup
}
StatusListView {
id: pinnedMessageListView
model: root.pinnedMessagesModel
Layout.fillWidth: true
Layout.fillHeight: count
delegate: Item {
id: messageDelegate
width: ListView.view.width
height: messageItem.height
MessageView {
id: messageItem
width: parent.width
sharedRootStore: root.sharedStore
utilsStore: root.utilsStore
rootStore: root.store
messageStore: root.messageStore
messageId: model.id
responseToMessageWithId: model.responseToMessageWithId
senderId: model.senderId
senderDisplayName: model.senderDisplayName
senderOptionalName: model.senderOptionalName
senderIsEnsVerified: model.senderEnsVerified
senderIsAdded: model.senderIsAdded
senderIcon: model.senderIcon
senderColorHash: model.senderColorHash
senderTrustStatus: model.senderTrustStatus
amISender: model.amISender
messageText: model.messageText
messageImage: model.messageImage
messageTimestamp: model.timestamp
messageOutgoingStatus: model.outgoingStatus
messageContentType: model.contentType
pinnedMessage: model.pinned
messagePinnedBy: model.pinnedBy
sticker: model.sticker
stickerPack: model.stickerPack
linkPreviewModel: model.linkPreviewModel
links: model.links
transactionParams: model.transactionParameters
quotedMessageText: model.quotedMessageParsedText
quotedMessageFrom: model.quotedMessageFrom
quotedMessageContentType: model.quotedMessageContentType
quotedMessageDeleted: model.quotedMessageDeleted
quotedMessageAuthorDetailsName: model.quotedMessageAuthorName
quotedMessageAuthorDetailsDisplayName: model.quotedMessageAuthorDisplayName
quotedMessageAuthorDetailsThumbnailImage: model.quotedMessageAuthorThumbnailImage
quotedMessageAuthorDetailsEnsVerified: model.quotedMessageAuthorEnsVerified
quotedMessageAuthorDetailsIsContact: model.quotedMessageAuthorIsContact
quotedMessageAuthorDetailsColorHash: model.quotedMessageAuthorColorHash
bridgeName: model.bridgeName
// This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once.
prevMessageIndex: index - 1
prevMessageAsJsonObj: root.messageStore ? root.messageStore.getMessageByIndexAsJson(index - 1) : {}
nextMessageIndex: index + 1
nextMessageAsJsonObj: root.messageStore ? root.messageStore.getMessageByIndexAsJson(index + 1) : {}
// Additional params
isInPinnedPopup: true
shouldRepeatHeader: true
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
z: 55
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
switch (mouse.button) {
case Qt.RightButton:
Global.openMenu(pinnedPopupMessageContextMenuComponent, this, {
messageId: messageItem.messageId,
})
break
case Qt.LeftButton:
if (!!root.messageToPin) {
if (!radio.checked)
radio.checked = true
} else {
d.jumpToMessage(model.id)
}
break
}
}
}
StatusFlatRoundButton {
id: unpinButton
anchors.top: parent.top
anchors.topMargin: Theme.bigPadding
anchors.right: parent.right
anchors.rightMargin: Theme.bigPadding
z: mouseArea.z + 1
width: 32
height: 32
visible: root.isPinActionAvaliable && !root.messageToPin && (hovered || mouseArea.containsMouse)
icon.name: "unpin"
tooltip.text: qsTr("Unpin")
color: hovered ? Theme.palette.primaryColor2 : Theme.palette.indirectColor1
onClicked: {
root.messageStore.unpinMessage(model.id)
}
}
StatusRadioButton {
id: radio
visible: root.messageToPin
anchors.right: parent.right
anchors.rightMargin: Theme.bigPadding
anchors.verticalCenter: parent.verticalCenter
ButtonGroup.group: pinButtonGroup
onCheckedChanged: { // NB this should be `onToggled` but MouseArea above handles the whole delegate
root.messageToUnpin = checked ? model.id : ""
}
}
Component {
id: pinnedPopupMessageContextMenuComponent
StatusMenu {
id: messageContextMenu
property string messageId
StatusAction {
text: qsTr("Unpin")
icon.name: "unpin"
onTriggered: {
root.messageStore.unpinMessage(messageContextMenu.messageId)
close()
}
}
StatusAction {
text: qsTr("Jump to")
icon.name: "arrow-up"
onTriggered: {
d.jumpToMessage(messageContextMenu.messageId)
close()
}
}
onOpened: {
messageItem.setMessageActive(model.id, true)
}
onClosed: {
messageItem.setMessageActive(model.id, false)
destroy()
}
}
}
}
}
layer.enabled: root.visible && !root.messageToPin
layer.effect: OpacityMask {
maskSource: Rectangle {
width: column.width
height: column.height
radius: background.radius
Rectangle {
width: parent.width
height: parent.radius
anchors.top: parent.top
}
}
}
}
footer: StatusDialogFooter {
id: footer
visible: !!root.messageToPin
rightButtons: ObjectModel {
StatusButton {
visible: footer.visible
enabled: !!root.messageToUnpin && pinButtonGroup.checkedButton
text: qsTr("Unpin selected message and pin new message")
onClicked: {
root.messageStore.unpinMessage(root.messageToUnpin)
root.messageToUnpin = ""
root.messageStore.pinMessage(root.messageToPin)
root.messageToPin = ""
root.close()
}
}
}
}
}