feat: highlight the hovered hyperlink and link preview

This commit is contained in:
Alex Jbanca 2023-10-09 15:41:27 +03:00 committed by Alex Jbanca
parent fcd9567677
commit 331f27b52a
6 changed files with 46 additions and 7 deletions

View File

@ -65,6 +65,8 @@ Control {
property bool profileClickable: true property bool profileClickable: true
property bool hideMessage: false property bool hideMessage: false
property bool isInPinnedPopup property bool isInPinnedPopup
property string highlightedLink: ""
property string hoveredLink: ""
property StatusMessageDetails messageDetails: StatusMessageDetails {} property StatusMessageDetails messageDetails: StatusMessageDetails {}
property StatusMessageDetails replyDetails: StatusMessageDetails {} property StatusMessageDetails replyDetails: StatusMessageDetails {}
@ -273,9 +275,13 @@ Control {
isEdited: root.isEdited isEdited: root.isEdited
allowShowMore: !root.isInPinnedPopup allowShowMore: !root.isInPinnedPopup
textField.anchors.rightMargin: root.isInPinnedPopup ? /*Style.current.xlPadding*/ 32 : 0 // margin for the "Unpin" floating button textField.anchors.rightMargin: root.isInPinnedPopup ? /*Style.current.xlPadding*/ 32 : 0 // margin for the "Unpin" floating button
highlightedLink: root.highlightedLink
onLinkActivated: { onLinkActivated: {
root.linkActivated(link); root.linkActivated(link);
} }
textField.onHoveredLinkChanged: {
root.hoveredLink = hoveredLink;
}
} }
} }
Loader { Loader {
@ -295,6 +301,7 @@ Control {
messageDetails: root.messageDetails messageDetails: root.messageDetails
allowShowMore: !root.isInPinnedPopup allowShowMore: !root.isInPinnedPopup
textField.anchors.rightMargin: root.isInPinnedPopup ? /*Style.current.xlPadding*/ 32 : 0 // margin for the "Unpin" floating button textField.anchors.rightMargin: root.isInPinnedPopup ? /*Style.current.xlPadding*/ 32 : 0 // margin for the "Unpin" floating button
highlightedLink: root.highlightedLink
onLinkActivated: { onLinkActivated: {
root.linkActivated(link); root.linkActivated(link);
} }

View File

@ -9,6 +9,10 @@ import StatusQ.Core.Utils 0.1
Item { Item {
id: root id: root
readonly property alias hoveredLink: chatText.hoveredLink
property string highlightedLink: ""
property StatusMessageDetails messageDetails: StatusMessageDetails {} property StatusMessageDetails messageDetails: StatusMessageDetails {}
property bool isEdited: false property bool isEdited: false
property bool convertToSingleLine: false property bool convertToSingleLine: false
@ -24,6 +28,8 @@ Item {
QtObject { QtObject {
id: d id: d
property string hoveredLink: chatText.hoveredLink || root.highlightedLink
property bool readMore: false property bool readMore: false
property bool isQuote: false property bool isQuote: false
readonly property int showMoreHeight: showMoreButtonLoader.visible ? showMoreButtonLoader.height : 0 readonly property int showMoreHeight: showMoreButtonLoader.visible ? showMoreButtonLoader.height : 0
@ -44,7 +50,7 @@ Item {
const editedMessage = formattedMessage.slice(0, index) const editedMessage = formattedMessage.slice(0, index)
+ ` <span class="isEdited">` + qsTr("(edited)") + `</span>` + ` <span class="isEdited">` + qsTr("(edited)") + `</span>`
+ formattedMessage.slice(index); + formattedMessage.slice(index);
return Utils.getMessageWithStyle(Emoji.parse(editedMessage), chatText.hoveredLink) return Utils.getMessageWithStyle(Emoji.parse(editedMessage), d.hoveredLink)
} }
if (root.convertToSingleLine || isQuote) if (root.convertToSingleLine || isQuote)
@ -60,7 +66,7 @@ Item {
// short return not to add styling when no html // short return not to add styling when no html
return formattedMessage return formattedMessage
return Utils.getMessageWithStyle(formattedMessage, chatText.hoveredLink) return Utils.getMessageWithStyle(formattedMessage, d.hoveredLink)
} }
} }
@ -98,10 +104,6 @@ Item {
onLinkActivated: { onLinkActivated: {
root.linkActivated(link); root.linkActivated(link);
} }
onLinkHovered: {
// Strange thing. Without this empty stub the cursorShape
// is not changed to pointingHandCursor.
}
} }
// Horizontal crop mask // Horizontal crop mask

View File

@ -197,6 +197,7 @@ QtObject {
`padding: 0px 2px;` + `padding: 0px 2px;` +
`}` + `}` +
(hoveredLink !== "" ? `a.mention[href="${hoveredLink}"] { background-color: ${Theme.palette.mentionColor2}; }` : ``) + (hoveredLink !== "" ? `a.mention[href="${hoveredLink}"] { background-color: ${Theme.palette.mentionColor2}; }` : ``) +
(hoveredLink !== "" ? `a[href="${hoveredLink}"] { background-color: ${Theme.palette.primaryColor3}; }` : ``) +
`del {` + `del {` +
`text-decoration: line-through;` + `text-decoration: line-through;` +
`}` + `}` +

View File

@ -1,11 +1,13 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import shared.status 1.0 import shared.status 1.0
import utils 1.0
CalloutCard { CalloutCard {
id: root id: root
@ -14,6 +16,9 @@ CalloutCard {
required property string title required property string title
required property string description required property string description
required property string footer required property string footer
property bool highlight: false
property StatusAssetSettings logoSettings: StatusAssetSettings { property StatusAssetSettings logoSettings: StatusAssetSettings {
width: 28 width: 28
height: 28 height: 28
@ -27,11 +32,20 @@ CalloutCard {
borderWidth: 1 borderWidth: 1
implicitHeight: 290 implicitHeight: 290
implicitWidth: 305 implicitWidth: 305
hoverEnabled: true
borderColor: hovered || highlight ? Style.current.borderTertiary : Style.current.border
Behavior on borderColor {
ColorAnimation { duration: 200 }
}
contentItem: ColumnLayout { contentItem: ColumnLayout {
StatusImage { StatusImage {
id: bannerImage id: bannerImage
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: d.bannerImageMargins
Layout.rightMargin: d.bannerImageMargins
Layout.topMargin: d.bannerImageMargins
Layout.preferredHeight: 170 Layout.preferredHeight: 170
asynchronous: true asynchronous: true
source: root.bannerImageSource source: root.bannerImageSource
@ -98,4 +112,9 @@ CalloutCard {
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: root.clicked(mouse) onClicked: root.clicked(mouse)
} }
QtObject {
id: d
property real bannerImageMargins: 1 / Screen.devicePixelRatio // image size isn't pixel perfect..
}
} }

View File

@ -23,6 +23,9 @@ Flow {
required property bool isCurrentUser required property bool isCurrentUser
readonly property alias hoveredLink: linksRepeater.hoveredUrl
property string highlightLink: ""
signal imageClicked(var image, var mouse, var imageSource, string url) signal imageClicked(var image, var mouse, var imageSource, string url)
spacing: 12 spacing: 12
@ -80,8 +83,10 @@ Flow {
Repeater { Repeater {
id: linksRepeater id: linksRepeater
model: root.linkPreviewModel
property string hoveredUrl: ""
model: root.linkPreviewModel
delegate: Loader { delegate: Loader {
id: linkMessageLoader id: linkMessageLoader
@ -120,6 +125,8 @@ Flow {
break break
} }
} }
highlight: root.highlightLink === url
onHoveredChanged: linksRepeater.hoveredUrl = hovered ? url : ""
} }
} }
} }

View File

@ -755,14 +755,17 @@ Loader {
linksComponent: Component { linksComponent: Component {
LinksMessageView { LinksMessageView {
id: linksMessageView
linkPreviewModel: root.linkPreviewModel linkPreviewModel: root.linkPreviewModel
localUnfurlLinks: root.localUnfurlLinks localUnfurlLinks: root.localUnfurlLinks
messageStore: root.messageStore messageStore: root.messageStore
store: root.rootStore store: root.rootStore
isCurrentUser: root.amISender isCurrentUser: root.amISender
highlightLink: delegate.hoveredLink
onImageClicked: (image, mouse, imageSource, url) => { onImageClicked: (image, mouse, imageSource, url) => {
d.onImageClicked(image, mouse, imageSource, url) d.onImageClicked(image, mouse, imageSource, url)
} }
onHoveredLinkChanged: delegate.highlightedLink = linksMessageView.hoveredLink
} }
} }