feat: redisgn compact mode part 1
redesigns the compact mode to have a nice hover, easier replying and adding reactions and more Missing parts are aligning chat command, images and unfurlings, redesigning mentions and the channel list and also trying to find a way to re-enable link hovers in the text
This commit is contained in:
parent
d1faf98f80
commit
b245d858aa
|
@ -31,15 +31,17 @@ ScrollView {
|
|||
|
||||
ListView {
|
||||
property string currentNotificationChatId
|
||||
property bool chatButtonsHovered: false
|
||||
|
||||
id: chatLogView
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: Style.current.bigPadding
|
||||
spacing: 4
|
||||
spacing: appSettings.compactMode ? 0 : 4
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
flickDeceleration: 10000
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalLayoutDirection: ListView.TopToBottom
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
import QtQuick 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import "../../../../../shared"
|
||||
import "../../../../../shared/status"
|
||||
import "../../../../../imports"
|
||||
|
||||
Rectangle {
|
||||
property bool parentIsHovered: false
|
||||
signal hoverChanged(bool hovered)
|
||||
property int containerMargin: 2
|
||||
|
||||
id: buttonsContainer
|
||||
visible: buttonsContainer.parentIsHovered || isMessageActive
|
||||
width: buttonRow.width + buttonsContainer.containerMargin * 2
|
||||
height: 36
|
||||
radius: Style.current.radius
|
||||
color: Style.current.background
|
||||
z: 52
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
width: buttonsContainer.width
|
||||
height: buttonsContainer.height
|
||||
x: buttonsContainer.x
|
||||
y: buttonsContainer.y + 10
|
||||
visible: buttonsContainer.visible
|
||||
source: buttonsContainer
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 2
|
||||
radius: 10
|
||||
samples: 15
|
||||
color: "#22000000"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: buttonsContainer
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
buttonsContainer.hoverChanged(true)
|
||||
chatLogView.chatButtonsHovered = true
|
||||
}
|
||||
onExited: {
|
||||
buttonsContainer.hoverChanged(false)
|
||||
chatLogView.chatButtonsHovered = false
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttonRow
|
||||
spacing: buttonsContainer.containerMargin
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: buttonsContainer.containerMargin
|
||||
anchors.verticalCenter: buttonsContainer.verticalCenter
|
||||
height: parent.height - 2 * buttonsContainer.containerMargin
|
||||
|
||||
StatusIconButton {
|
||||
id: emojiBtn
|
||||
icon.name: "emoji"
|
||||
width: 32
|
||||
height: 32
|
||||
onClicked: {
|
||||
isMessageActive = true
|
||||
clickMessage(false, false, false, null, true)
|
||||
}
|
||||
onHoveredChanged: {
|
||||
chatLogView.chatButtonsHovered = this.hovered
|
||||
buttonsContainer.hoverChanged(this.hovered)
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: emojiBtn.hovered
|
||||
text: qsTr("Add reaction")
|
||||
width: 115
|
||||
}
|
||||
}
|
||||
|
||||
StatusIconButton {
|
||||
id: replyBtn
|
||||
icon.name: "reply"
|
||||
width: 32
|
||||
height: 32
|
||||
onClicked: {
|
||||
SelectedMessage.set(messageId, fromAuthor);
|
||||
showReplyArea()
|
||||
}
|
||||
onHoveredChanged: {
|
||||
chatLogView.chatButtonsHovered = this.hovered
|
||||
buttonsContainer.hoverChanged(this.hovered)
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: replyBtn.hovered
|
||||
text: qsTr("Reply")
|
||||
width: 75
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,7 +105,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: mask
|
||||
anchors.fill: chatText
|
||||
|
|
|
@ -1,179 +1,240 @@
|
|||
import QtQuick 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import "../../../../../shared"
|
||||
import "../../../../../shared/status"
|
||||
import "../../../../../imports"
|
||||
|
||||
Item {
|
||||
property var clickMessage: function () {}
|
||||
property int chatHorizontalPadding: 12
|
||||
property int chatHorizontalPadding: 8
|
||||
property int chatVerticalPadding: 7
|
||||
property string linkUrls: ""
|
||||
property int contentType: 2
|
||||
property var container
|
||||
property bool isCurrentUser: false
|
||||
property bool isHovered: false
|
||||
property bool isMessageActive: false
|
||||
|
||||
id: root
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: authorCurrentMsg != authorPrevMsg ? Style.current.smallPadding : 0
|
||||
height: childrenRect.height + this.anchors.topMargin
|
||||
|
||||
width: parent.width
|
||||
height: messageContainer.height
|
||||
|
||||
// FIXME @jonathanr: Adding this breaks the first line. Need to fix the height somehow
|
||||
// DateGroup {
|
||||
// id: dateGroupLbl
|
||||
// }
|
||||
|
||||
UserImage {
|
||||
id: chatImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.padding
|
||||
// anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
|
||||
anchors.top: parent.top
|
||||
MouseArea {
|
||||
anchors.fill: messageContainer
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: messageMouseArea.clicked(mouse)
|
||||
}
|
||||
|
||||
UsernameLabel {
|
||||
id: chatName
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
// anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
|
||||
anchors.top: parent.top
|
||||
anchors.left: chatImage.right
|
||||
}
|
||||
|
||||
ChatReply {
|
||||
id: chatReply
|
||||
// anchors.top: chatName.visible ? chatName.bottom : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top)
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.topMargin: chatName.visible && this.visible ? root.chatVerticalPadding : 0
|
||||
anchors.left: chatImage.right
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
ChatButtons {
|
||||
parentIsHovered: root.isHovered
|
||||
onHoverChanged: root.isHovered = hovered
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.chatHorizontalPadding
|
||||
container: root.container
|
||||
chatHorizontalPadding: root.chatHorizontalPadding
|
||||
}
|
||||
|
||||
ChatText {
|
||||
id: chatText
|
||||
anchors.top: chatReply.bottom
|
||||
anchors.topMargin: chatName.visible && this.visible ? root.chatVerticalPadding : 0
|
||||
anchors.left: chatImage.right
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.chatHorizontalPadding
|
||||
anchors.rightMargin: 20
|
||||
anchors.top: parent.top
|
||||
// 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
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: chatImageContent
|
||||
active: isImage
|
||||
anchors.left: chatText.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: chatReply.bottom
|
||||
z: 51
|
||||
|
||||
active: typeof messageContextMenu !== "undefined"
|
||||
sourceComponent: Component {
|
||||
ChatImage {
|
||||
imageSource: image
|
||||
imageWidth: 200
|
||||
onClicked: root.clickMessage(false, false, true, image)
|
||||
container: root.container
|
||||
Connections {
|
||||
enabled: root.isMessageActive
|
||||
target: messageContextMenu
|
||||
onClosed: root.isMessageActive = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: stickerLoader
|
||||
active: contentType === Constants.stickerType
|
||||
anchors.left: chatText.left
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.topMargin: this.visible && chatName.visible ? root.chatVerticalPadding : 0
|
||||
Rectangle {
|
||||
property alias chatText: chatText
|
||||
|
||||
sourceComponent: Component {
|
||||
Rectangle {
|
||||
id: stickerContainer
|
||||
color: Style.current.transparent
|
||||
border.color: Style.current.grey
|
||||
border.width: 1
|
||||
radius: 16
|
||||
width: stickerId.width + 2 * root.chatVerticalPadding
|
||||
height: stickerId.height + 2 * root.chatVerticalPadding
|
||||
id: messageContainer
|
||||
height: childrenRect.height + (chatName.visible || emojiReactionLoader.active ? Style.current.smallPadding : 0)
|
||||
+ (emojiReactionLoader.active ? emojiReactionLoader.height + Style.current.halfPadding : 0)
|
||||
width: parent.width
|
||||
|
||||
Sticker {
|
||||
id: stickerId
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: root.chatVerticalPadding
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.chatVerticalPadding
|
||||
contentType: root.contentType
|
||||
color: root.isHovered || isMessageActive ? Style.current.backgroundHover : Style.current.transparent
|
||||
|
||||
// FIXME @jonathanr: Adding this breaks the first line. Need to fix the height somehow
|
||||
// DateGroup {
|
||||
// id: dateGroupLbl
|
||||
// }
|
||||
|
||||
UserImage {
|
||||
id: chatImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.padding
|
||||
// anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
}
|
||||
|
||||
UsernameLabel {
|
||||
id: chatName
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
// anchors.top: dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top
|
||||
anchors.top: chatImage.top
|
||||
anchors.left: chatImage.right
|
||||
}
|
||||
|
||||
ChatReply {
|
||||
id: chatReply
|
||||
// anchors.top: chatName.visible ? chatName.bottom : (dateGroupLbl.visible ? dateGroupLbl.bottom : parent.top)
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.topMargin: chatName.visible && this.visible ? root.chatVerticalPadding : 0
|
||||
anchors.left: chatImage.right
|
||||
anchors.leftMargin: root.chatHorizontalPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: root.chatHorizontalPadding
|
||||
container: root.container
|
||||
chatHorizontalPadding: root.chatHorizontalPadding
|
||||
}
|
||||
|
||||
ChatText {
|
||||
id: chatText
|
||||
anchors.top: chatReply.active ? chatReply.bottom : chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
// using a padding instead of a margin let's us select text more easily
|
||||
textField.leftPadding: chatImage.anchors.leftMargin + chatImage.width + root.chatHorizontalPadding
|
||||
textField.rightPadding: Style.current.bigPadding
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: chatImageContent
|
||||
active: isImage
|
||||
anchors.left: chatText.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: chatReply.bottom
|
||||
z: 51
|
||||
|
||||
sourceComponent: Component {
|
||||
ChatImage {
|
||||
imageSource: image
|
||||
imageWidth: 200
|
||||
onClicked: root.clickMessage(false, false, true, image)
|
||||
container: root.container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: stickerLoader
|
||||
active: contentType === Constants.stickerType
|
||||
anchors.left: chatText.left
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.topMargin: this.visible && chatName.visible ? root.chatVerticalPadding : 0
|
||||
|
||||
sourceComponent: Component {
|
||||
Rectangle {
|
||||
id: stickerContainer
|
||||
color: Style.current.transparent
|
||||
border.color: Style.current.grey
|
||||
border.width: 1
|
||||
radius: 16
|
||||
width: stickerId.width + 2 * root.chatVerticalPadding
|
||||
height: stickerId.height + 2 * root.chatVerticalPadding
|
||||
|
||||
Sticker {
|
||||
id: stickerId
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: root.chatVerticalPadding
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.chatVerticalPadding
|
||||
contentType: root.contentType
|
||||
container: root.container
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageMouseArea {
|
||||
id: messageMouseArea
|
||||
anchors.fill: stickerLoader.active ? stickerLoader : chatText
|
||||
}
|
||||
|
||||
ChatTime {
|
||||
id: chatTime
|
||||
visible: authorCurrentMsg != authorPrevMsg
|
||||
anchors.verticalCenter: chatName.verticalCenter
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: 4
|
||||
}
|
||||
|
||||
SentMessage {
|
||||
id: sentMessage
|
||||
visible: isCurrentUser && !timeout && !isExpired && isMessage && outgoingStatus !== "sent"
|
||||
anchors.verticalCenter: chatTime.verticalCenter
|
||||
anchors.left: chatTime.right
|
||||
anchors.leftMargin: Style.current.halfPadding
|
||||
}
|
||||
|
||||
Retry {
|
||||
id: retry
|
||||
anchors.right: chatTime.right
|
||||
anchors.rightMargin: 5
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: linksLoader
|
||||
active: !!root.linkUrls
|
||||
anchors.left: chatText.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: chatText.bottom
|
||||
|
||||
sourceComponent: Component {
|
||||
LinksMessage {
|
||||
linkUrls: root.linkUrls
|
||||
container: root.container
|
||||
isCurrentUser: root.isCurrentUser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: audioPlayerLoader
|
||||
active: isAudio
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.left: chatImage.right
|
||||
|
||||
sourceComponent: Component {
|
||||
AudioPlayer {
|
||||
audioSource: audio
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageMouseArea {
|
||||
anchors.fill: stickerLoader.active ? stickerLoader : chatText
|
||||
}
|
||||
|
||||
// TODO show date for not the first messsage (on hover maybe)
|
||||
ChatTime {
|
||||
id: chatTime
|
||||
visible: authorCurrentMsg != authorPrevMsg
|
||||
anchors.verticalCenter: chatName.verticalCenter
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
}
|
||||
|
||||
SentMessage {
|
||||
id: sentMessage
|
||||
visible: isCurrentUser && !timeout && !isExpired && isMessage && outgoingStatus !== "sent"
|
||||
anchors.verticalCenter: chatTime.verticalCenter
|
||||
anchors.left: chatTime.right
|
||||
anchors.leftMargin: 8
|
||||
}
|
||||
|
||||
Retry {
|
||||
id: retry
|
||||
anchors.right: chatTime.right
|
||||
anchors.rightMargin: 5
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: linksLoader
|
||||
active: !!root.linkUrls
|
||||
anchors.left: chatText.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.top: chatText.bottom
|
||||
|
||||
sourceComponent: Component {
|
||||
LinksMessage {
|
||||
linkUrls: root.linkUrls
|
||||
container: root.container
|
||||
isCurrentUser: root.isCurrentUser
|
||||
}
|
||||
// TODO find a way for this to not eat link hovers
|
||||
MouseArea {
|
||||
anchors.fill: root
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
root.isHovered = true
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: audioPlayerLoader
|
||||
active: isAudio
|
||||
anchors.top: chatName.visible ? chatName.bottom : parent.top
|
||||
anchors.left: chatImage.right
|
||||
|
||||
sourceComponent: Component {
|
||||
AudioPlayer {
|
||||
audioSource: audio
|
||||
onExited: {
|
||||
if (chatLogView.chatButtonsHovered) {
|
||||
return
|
||||
}
|
||||
root.isHovered = false
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: emojiReactionLoader
|
||||
active: emojiReactions !== ""
|
||||
anchors.top: chatText.bottom
|
||||
anchors.left: chatText.left
|
||||
anchors.topMargin: active ? 2 : 0
|
||||
anchors.bottom: messageContainer.bottom
|
||||
anchors.bottomMargin: Style.current.smallPadding
|
||||
anchors.left: messageContainer.left
|
||||
anchors.leftMargin: messageContainer.chatText.textField.leftPadding
|
||||
|
||||
sourceComponent: Component {
|
||||
EmojiReactions {}
|
||||
EmojiReactions {
|
||||
onHoverChanged: root.isHovered = hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import "../../../../../shared"
|
||||
import "../../../../../shared/status"
|
||||
import "../../../../../imports"
|
||||
|
||||
Item {
|
||||
property int imageMargin: 4
|
||||
signal hoverChanged(bool hovered)
|
||||
|
||||
id: root
|
||||
height: 20
|
||||
width: childrenRect.width
|
||||
|
@ -23,7 +27,7 @@ Item {
|
|||
if (fromAccounts.length > 3) {
|
||||
leftNode = fromAccounts.slice(0, 3);
|
||||
rightNode = fromAccounts.slice(3, fromAccounts.length);
|
||||
return (rightNode.length == 1) ?
|
||||
return (rightNode.length === 1) ?
|
||||
lastTwoItems([leftNode.join(", "), rightNode[0]]) :
|
||||
lastTwoItems([leftNode.join(", "), qsTr("%1 more reacted.").arg(rightNode.length)]);
|
||||
}
|
||||
|
@ -33,109 +37,198 @@ Item {
|
|||
return lastTwoItems([leftNode.join(", "), rightNode[0]]);
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: reactionepeater
|
||||
model: {
|
||||
if (!emojiReactions) {
|
||||
return []
|
||||
Row {
|
||||
spacing: root.imageMargin
|
||||
|
||||
Repeater {
|
||||
id: reactionRepeater
|
||||
width: childrenRect.width
|
||||
model: {
|
||||
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(chatsModel.userNameOrAlias(reaction.from));
|
||||
if (!byEmoji[reaction.emojiId].currentUserReacted && reaction.from === profileModel.profile.pubKey) {
|
||||
byEmoji[reaction.emojiId].currentUserReacted = true
|
||||
}
|
||||
|
||||
})
|
||||
return Object.values(byEmoji)
|
||||
} catch (e) {
|
||||
console.error('Error parsing emoji reactions', e)
|
||||
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
|
||||
Rectangle {
|
||||
property bool isHovered: false
|
||||
|
||||
id: emojiContainer
|
||||
width: emojiImage.width + emojiCount.width + (root.imageMargin * 2) + + 8
|
||||
height: 20
|
||||
radius: 10
|
||||
color: modelData.currentUserReacted ? Style.current.secondaryBackground :
|
||||
(isHovered ? Style.current.emojiReactionBackgroundHovered : Style.current.emojiReactionBackground)
|
||||
|
||||
ToolTip {
|
||||
visible: mouseArea.containsMouse
|
||||
text: showReactionAuthors(modelData.fromAccounts)
|
||||
}
|
||||
|
||||
// Rounded corner to cover one corner
|
||||
Rectangle {
|
||||
color: parent.color
|
||||
width: 8
|
||||
height: 8
|
||||
anchors.top: parent.top
|
||||
anchors.left: !isCurrentUser || appSettings.compactMode ? parent.left : undefined
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: !isCurrentUser || appSettings.compactMode ? undefined : parent.right
|
||||
anchors.rightMargin: 0
|
||||
radius: 2
|
||||
z: -1
|
||||
}
|
||||
|
||||
// This is a workaround to get a "border" around the rectangle including the weird rectangle
|
||||
Loader {
|
||||
active: modelData.currentUserReacted
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -1
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -1
|
||||
z: -2
|
||||
|
||||
sourceComponent: Component {
|
||||
Rectangle {
|
||||
width: emojiContainer.width + 2
|
||||
height: emojiContainer.height + 2
|
||||
radius: emojiContainer.radius
|
||||
color: Style.current.primary
|
||||
|
||||
Rectangle {
|
||||
color: parent.color
|
||||
width: 8
|
||||
height: 8
|
||||
anchors.top: parent.top
|
||||
anchors.left: !isCurrentUser || appSettings.compactMode ? parent.left : undefined
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: !isCurrentUser || appSettings.compactMode ? undefined : parent.right
|
||||
anchors.rightMargin: 0
|
||||
radius: 2
|
||||
z: -1
|
||||
}
|
||||
}
|
||||
}
|
||||
byEmoji[reaction.emojiId].count++;
|
||||
byEmoji[reaction.emojiId].fromAccounts.push(chatsModel.userNameOrAlias(reaction.from));
|
||||
if (!byEmoji[reaction.emojiId].currentUserReacted && reaction.from === profileModel.profile.pubKey) {
|
||||
byEmoji[reaction.emojiId].currentUserReacted = true
|
||||
}
|
||||
|
||||
SVGImage {
|
||||
id: emojiImage
|
||||
width: 15
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: {
|
||||
const basePath = "../../../../img/emojiReactions/"
|
||||
switch (modelData.emojiId) {
|
||||
case 1: return basePath + "heart.svg"
|
||||
case 2: return basePath + "thumbsUp.svg"
|
||||
case 3: return basePath + "thumbsDown.svg"
|
||||
case 4: return basePath + "laughing.svg"
|
||||
case 5: return basePath + "sad.svg"
|
||||
case 6: return basePath + "angry.svg"
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.imageMargin
|
||||
}
|
||||
|
||||
})
|
||||
return Object.values(byEmoji)
|
||||
} catch (e) {
|
||||
console.error('Error parsing emoji reactions', e)
|
||||
return []
|
||||
}
|
||||
StyledText {
|
||||
id: emojiCount
|
||||
text: modelData.count
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: emojiImage.right
|
||||
anchors.leftMargin: root.imageMargin
|
||||
font.pixelSize: 12
|
||||
color: modelData.currentUserReacted ? Style.current.textColorTertiary : Style.current.textColor
|
||||
}
|
||||
|
||||
}
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: {
|
||||
root.hoverChanged(true)
|
||||
emojiContainer.isHovered = true
|
||||
}
|
||||
onExited: {
|
||||
root.hoverChanged(false)
|
||||
emojiContainer.isHovered = false
|
||||
}
|
||||
onClicked: {
|
||||
chatsModel.toggleReaction(messageId, modelData.emojiId)
|
||||
|
||||
Rectangle {
|
||||
width: emojiImage.width + emojiCount.width + (root.imageMargin * 2) + + 8
|
||||
height: 20
|
||||
radius: 10
|
||||
anchors.left: (index === 0) ? parent.left: parent.children[index-1].right
|
||||
anchors.leftMargin: (index === 0) ? 0 : root.imageMargin
|
||||
color: modelData.currentUserReacted ? Style.current.primary : Style.current.inputBackground
|
||||
|
||||
ToolTip {
|
||||
visible: mouseArea.containsMouse
|
||||
text: showReactionAuthors(modelData.fromAccounts)
|
||||
}
|
||||
|
||||
// Rounded corner to cover one corner
|
||||
Rectangle {
|
||||
color: parent.color
|
||||
width: 8
|
||||
height: 8
|
||||
anchors.top: parent.top
|
||||
anchors.left: !isCurrentUser || appSettings.compactMode ? parent.left : undefined
|
||||
anchors.leftMargin: 0
|
||||
anchors.right: !isCurrentUser || appSettings.compactMode ? undefined : parent.right
|
||||
anchors.rightMargin: 0
|
||||
radius: 2
|
||||
z: -1
|
||||
}
|
||||
|
||||
SVGImage {
|
||||
id: emojiImage
|
||||
width: 15
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: {
|
||||
const basePath = "../../../../img/emojiReactions/"
|
||||
switch (modelData.emojiId) {
|
||||
case 1: return basePath + "heart.svg"
|
||||
case 2: return basePath + "thumbsUp.svg"
|
||||
case 3: return basePath + "thumbsDown.svg"
|
||||
case 4: return basePath + "laughing.svg"
|
||||
case 5: return basePath + "sad.svg"
|
||||
case 6: return basePath + "angry.svg"
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: addEmojiBtn.width + addEmojiBtn.anchors.leftMargin // there is more margin between the button and the emojis than between each emoji
|
||||
height: addEmojiBtn.height
|
||||
|
||||
SVGImage {
|
||||
property bool isHovered: false
|
||||
|
||||
id: addEmojiBtn
|
||||
source: "../../../../img/emoji.svg"
|
||||
width: 16.5
|
||||
height: 16.5
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.imageMargin
|
||||
anchors.leftMargin: 2.5
|
||||
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: emojiCount
|
||||
text: modelData.count
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: emojiImage.right
|
||||
anchors.leftMargin: root.imageMargin
|
||||
font.pixelSize: 12
|
||||
color: modelData.currentUserReacted ? Style.current.currentUserTextColor : Style.current.textColor
|
||||
ColorOverlay {
|
||||
anchors.fill: addEmojiBtn
|
||||
antialiasing: true
|
||||
source: addEmojiBtn
|
||||
color: addEmojiBtn.isHovered ? Style.current.primary : Style.current.secondaryText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
anchors.fill: addEmojiBtn
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: addEmojiBtn.isHovered = true
|
||||
onExited: addEmojiBtn.isHovered = false
|
||||
onClicked: {
|
||||
chatsModel.toggleReaction(messageId, modelData.emojiId)
|
||||
|
||||
isMessageActive = true
|
||||
clickMessage(false, false, false, null, true)
|
||||
}
|
||||
}
|
||||
|
||||
StatusToolTip {
|
||||
visible: addEmojiBtn.isHovered
|
||||
text: qsTr("Add reaction")
|
||||
width: 115
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import QtQuick 2.3
|
||||
import QtQuick 2.13
|
||||
import "../../../../../shared"
|
||||
import "../../../../../imports"
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import "../../../../../imports"
|
|||
|
||||
Item {
|
||||
id: root
|
||||
property bool isHovered: false
|
||||
height: childrenRect.height
|
||||
width: chatName.width + (ensOrAlias.visible ? ensOrAlias.width + ensOrAlias.anchors.leftMargin : 0)
|
||||
property alias label: chatName
|
||||
|
@ -28,6 +29,7 @@ Item {
|
|||
color: text.startsWith("@") || isCurrentUser || localName !== "" ? Style.current.blue : Style.current.secondaryText
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: Style.current.secondaryTextFontSize
|
||||
font.underline: root.isHovered
|
||||
readOnly: true
|
||||
wrapMode: Text.WordWrap
|
||||
selectByMouse: true
|
||||
|
@ -37,10 +39,10 @@ Item {
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
parent.font.underline = true
|
||||
root.isHovered = true
|
||||
}
|
||||
onExited: {
|
||||
parent.font.underline = false
|
||||
root.isHovered = false
|
||||
}
|
||||
onClicked: {
|
||||
clickMessage(true)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.2361 9.43053C10.9676 9.16205 10.5323 9.16205 10.2638 9.43053C9.99536 9.69902 9.99536 10.1343 10.2638 10.4028L11.9744 12.1134C12.2632 12.4021 12.0587 12.8958 11.6504 12.8958L7.99998 12.8958C4.83585 12.8958 2.27081 10.3308 2.27081 7.16667C2.27081 4.00254 4.83585 1.4375 7.99998 1.4375C8.37967 1.4375 8.68748 1.1297 8.68748 0.75C8.68748 0.370305 8.37967 0.0625 7.99998 0.0625C4.07646 0.0624998 0.895812 3.24315 0.895813 7.16667C0.895813 11.0902 4.07646 14.2708 7.99998 14.2708H11.6504C12.0587 14.2708 12.2632 14.7645 11.9744 15.0533L10.2638 16.7639C9.99536 17.0324 9.99536 17.4677 10.2638 17.7361C10.5323 18.0046 10.9676 18.0046 11.2361 17.7361L14.9028 14.0695C15.1713 13.801 15.1713 13.3657 14.9028 13.0972L11.2361 9.43053Z" fill="#939BA1"/>
|
||||
</svg>
|
After Width: | Height: | Size: 856 B |
|
@ -51,6 +51,8 @@ Theme {
|
|||
property color topBarChatInfoColor: evenDarkerGrey
|
||||
property color codeBackground: "#2E386B"
|
||||
property color primarySelectionColor: "#b4c8ff"
|
||||
property color emojiReactionBackground: "#2d2823"
|
||||
property color emojiReactionBackgroundHovered: "#3a3632"
|
||||
|
||||
property color buttonForegroundColor: blue
|
||||
property color buttonBackgroundColor: secondaryBackground
|
||||
|
|
|
@ -50,6 +50,8 @@ Theme {
|
|||
property color topBarChatInfoColor: grey
|
||||
property color codeBackground: "#2E386B"
|
||||
property color primarySelectionColor: "#b4c8ff"
|
||||
property color emojiReactionBackground: "#e2e6e9"
|
||||
property color emojiReactionBackgroundHovered: "#d7dadd"
|
||||
|
||||
property color buttonForegroundColor: blue
|
||||
property color buttonBackgroundColor: secondaryBackground
|
||||
|
|
|
@ -30,6 +30,7 @@ QtObject {
|
|||
property color orange: "#FE8F59"
|
||||
|
||||
property color background
|
||||
property color backgroundHover
|
||||
property color border
|
||||
property color textColor
|
||||
property color secondaryText
|
||||
|
@ -38,6 +39,8 @@ QtObject {
|
|||
property color modalBackground
|
||||
property color codeBackground
|
||||
property color primarySelectioncolor
|
||||
property color emojiReactionBackground
|
||||
property color emojiReactionBackgroundHovered
|
||||
|
||||
property color buttonForegroundColor
|
||||
property color buttonBackgroundColor
|
||||
|
|
|
@ -145,6 +145,7 @@ DISTFILES += \
|
|||
app/AppLayouts/Chat/ChatColumn/ChatComponents/SignTransactionModal.qml \
|
||||
app/AppLayouts/Chat/ChatColumn/CompactMessage.qml \
|
||||
app/AppLayouts/Chat/ChatColumn/MessageComponents/ChannelIdentifier.qml \
|
||||
app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatButtons.qml \
|
||||
app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatImage.qml \
|
||||
app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply \
|
||||
app/AppLayouts/Chat/ChatColumn/MessageComponents/ChatReply.qml \
|
||||
|
|
|
@ -36,7 +36,7 @@ ToolTip {
|
|||
color: Style.current.tooltipForegroundColor
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.DemiBold
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue