feat: Implement the new Link Preview cards
Implementing the new design for the following preview types: - Community and channel - General link previews (Youtube, github etc) - Image link preview The storybook implementation has all these links available for testing. Missing features in the app: - Logo (favicon) - Community card - Image preview details (title, domain name)
This commit is contained in:
parent
2ac484dd57
commit
7b6281a6c6
|
@ -0,0 +1,204 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import shared.controls.chat 1.0
|
||||
import utils 1.0
|
||||
|
||||
SplitView {
|
||||
id: root
|
||||
|
||||
property alias logoSettings: previewCard.logoSettings
|
||||
property string ytBannerQuality: "hqdefault"
|
||||
|
||||
Pane {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
LinkPreviewCard {
|
||||
id: previewCard
|
||||
bannerImageSource: "https://img.youtube.com/vi/yHN1M7vcPKU/%1.jpg".arg(root.ytBannerQuality)
|
||||
title: titleInput.text
|
||||
description: descriptionInput.text
|
||||
footer: footerInput.text
|
||||
logoSettings.name: Style.png("tokens/SOCKS")
|
||||
logoSettings.isImage: true
|
||||
logoSettings.isLetterIdenticon: false
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
SplitView.preferredWidth: 500
|
||||
SplitView.fillHeight: true
|
||||
ColumnLayout {
|
||||
spacing: 24
|
||||
ColumnLayout {
|
||||
Label {
|
||||
text: "Title"
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: titleInput
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
text: "What Is Web3? A Decentralized Internet Via Blockchain Technology That Will Revolutionise All Sectors- Decrypt (@decryptmedia) August 31 2021"
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Description"
|
||||
}
|
||||
RowLayout {
|
||||
TextField {
|
||||
id: descriptionInput
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
text: "Link description goes here. If blank it will enable multi line title."
|
||||
}
|
||||
Button {
|
||||
text: "clear"
|
||||
onClicked: descriptionInput.text = ""
|
||||
}
|
||||
Button {
|
||||
text: "Set"
|
||||
onClicked: descriptionInput.text = "Link description goes here. If blank it will enable multi line title."
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Footer"
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: footerInput
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
text: footerTypeCommunity.footerRichText
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Logo"
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
text: qsTr("No logo")
|
||||
checked: root.logoSettings.name === "" && root.logoSettings.emoji === ""
|
||||
onToggled: {
|
||||
root.logoSettings.name = ""
|
||||
root.logoSettings.emoji = ""
|
||||
root.logoSettings.isImage = false
|
||||
root.logoSettings.isLetterIdenticon = false
|
||||
}
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
readonly property string rawImageData: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAcCAYAAACdz7SqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAM2SURBVHgBtVbNbtNAEJ7ZpBQ4pRGF9kQqWqkBRNwnwLlxI9y4NX2CiiOntE9QeINw49a8QdwT3NhKQCKaSj4WUVXmABRqe5hxE+PGTuyk5ZOSXe/ftzs/3y5CBiw/NEzw/cdAaCJAifgXdCA4QGAjggbEvbMf0LJt7aSth6lkHjW4akIG8GI2/1k5H7e7XW2PGRdHqWQU8jdoNytZIrnC7YNPupnUnxtuWF01SjhD77hqwPQosNlrxdt34OTb172xpELoKvrA1QW4EqCZRJyLEnpI7ZBQggThlGvXYVLI3HAeE88vfj85Pno/6FaDiqeoEUZlMA9bvc/7cxyxVa6/SeM5j2Tcdn/hnHsNly520s7KAyN0V17+7pWNGhHVhxYJTNLraosLi8e0kMBxT0FH00IW830oeT/ButBertjRQ5BPO1xUQ1IE2oQUHHZ0K6mdI1RzoSEdpqRg76O2lPgSElKDdz919JYMoxA95QDow7qUykWoxTo5z2YIXsGUsLV2CPD1cDu7MODiQKKnsVmI1jhFyQJvFrb6URxFQWJAYYIZSEF6tKZATitFQpehEm1PkCraWYCE+8Nt5ENBwX8EAd2NNaKQxu0ukVuCqwATQHwnjhphShMuiSAVKZ527E6bzYt78Q3SulxvcAm44K8ntXMqagmkJDUpzNwMZGsqBDqLuDXcLvkvqajcWWgm+ZUI6svlym5fsbITlh9tsgi0Ezs5//vkMtBocqSJOZw84ZrHPiXFJ6UwECx5A/FbqNXX2hAiefkzqCNRha1Wi8yJgddeCk4qHzkK1aMgdypfshYRbkTGm3z0Rs6LW0REgDXVEMuMI0TE5kDlgkv8+PjIKRYXfzPxEyH2EYzDzv7L4q1FHsvpg8Gkt186OlGp5uYXZMjzkYS8txwfQnj63//APmzDIF1yWJVrCDJgeZVfjTjCj0KicC3qlny0053FZ/k/PFnyy6P2yv1Kk1T/1eCGF/pEYCncGI6DCzIo/uGnRvg8CfzE5MEPoQGT4Pz5Uj3oxp+hMe0V4oOOrssOMfmWyMJo5X1cG2WZkYIvO2Tn85sGXwg5B5Q9kiKMas5DntPr6Oq4+/gvs8hkkbAzoC8AAAAASUVORK5CYII="
|
||||
text: qsTr("Raw image")
|
||||
checked: root.logoSettings.name === rawImageData
|
||||
onToggled: {
|
||||
root.logoSettings.name = rawImageData
|
||||
root.logoSettings.isImage = true
|
||||
root.logoSettings.isLetterIdenticon = false
|
||||
}
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
text: qsTr("QRC asset: SOCKS")
|
||||
checked: root.logoSettings.name = Style.png("tokens/SOCKS")
|
||||
onToggled:{
|
||||
root.logoSettings.name = Style.png("tokens/SOCKS")
|
||||
root.logoSettings.isImage = true
|
||||
root.logoSettings.isLetterIdenticon = false
|
||||
}
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Letter identicon")
|
||||
checked: root.logoSettings.name = "github.com"
|
||||
onToggled: {
|
||||
root.logoSettings.name = "github.com"
|
||||
root.logoSettings.emoji = ""
|
||||
root.logoSettings.isLetterIdenticon = true
|
||||
root.logoSettings.color = "blue"
|
||||
}
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Emoji")
|
||||
checked: root.logoSettings.emoji === "👋"
|
||||
onToggled: {
|
||||
root.logoSettings.emoji = "👋"
|
||||
root.logoSettings.isLetterIdenticon = true
|
||||
root.logoSettings.color = "orchid"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Banner size"
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Low (120x90)")
|
||||
checked: ytBannerQuality === "default"
|
||||
onToggled: ytBannerQuality = "default"
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Medium(320x180)")
|
||||
checked: ytBannerQuality === "mqdefault"
|
||||
onToggled: ytBannerQuality = "mqdefault"
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("High(480x360)")
|
||||
checked: ytBannerQuality === "hqdefault"
|
||||
onToggled: ytBannerQuality = "hqdefault"
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Footer type"
|
||||
}
|
||||
RadioButton {
|
||||
id: footerTypeCommunity
|
||||
property string footerRichText: `<img src="%1" width="16" height="16" style="vertical-align: top" ></img><font color="%2"> 629.2K </font> <img src="%3" width="16" height="16" style="vertical-align: top" ><font color="%2">112.1K</font>`.arg(Style.svg("group")).arg(Theme.palette.directColor1).arg(Style.svg("active-members"))
|
||||
text: qsTr("Community")
|
||||
checked: footerInput.text === footerRichText
|
||||
onToggled: footerInput.text = footerRichText
|
||||
}
|
||||
RadioButton {
|
||||
property string footerRichText: `%1 <img src="%2" width="16" height="16" style="vertical-align: top" ><font color="%2"> %3</font>`.arg(qsTr("Channel in")).arg(Style.png("tokens/SOCKS")).arg(qsTr("Doodles"))
|
||||
text: qsTr("Channel")
|
||||
checked: footerInput.text === footerRichText
|
||||
onToggled: footerInput.text = footerRichText
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Link domain")
|
||||
property string footerText: "X"
|
||||
checked: footerInput.text === footerText
|
||||
onToggled: footerInput.text = footerText
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: "Tail position"
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Left")
|
||||
checked: previewCard.leftTail === true
|
||||
onToggled: previewCard.leftTail = true
|
||||
}
|
||||
RadioButton {
|
||||
text: qsTr("Right")
|
||||
checked: previewCard.leftTail === false
|
||||
onToggled: previewCard.leftTail = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import shared.views.chat 1.0
|
||||
|
||||
SplitView {
|
||||
Pane {
|
||||
id: messageViewWrapper
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
LinksMessageView {
|
||||
id: linksMessageView
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
store: {}
|
||||
messageStore: {}
|
||||
linkPreviewModel: ListModel {
|
||||
id: linkPreviewModel
|
||||
ListElement {
|
||||
url: "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||
unfurled: true
|
||||
hostname: "www.youtube.com"
|
||||
title: "PSY - GANGNAM STYLE(강남스타일) M/V"
|
||||
description: "PSY - ‘I LUV IT’ M/V @ https://youtu.be/Xvjnoagk6GU PSY - ‘New Face’ M/V @https://youtu.be/OwJPPaEyqhI PSY - 8TH ALBUM '4X2=8' on iTunes @ https://smarturl.it/PSY_8thAlbum PSY - GANGNAM STYLE(강남스타일) on iTunes @ http://smarturl.it/PsyGangnam #PSY #싸이 #GANGNAMSTYLE #강남스타일 More about PSY@ http://www.psyp..."
|
||||
linkType: 0 // 0 = link, 1 = image
|
||||
thumbnailWidth: 480
|
||||
thumbnailHeight: 360
|
||||
thumbnailUrl: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
thumbnailDataUri: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
}
|
||||
ListElement {
|
||||
url: "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||
unfurled: true
|
||||
hostname: "www.youtube.com"
|
||||
title: "PSY - GANGNAM STYLE(강남스타일) M/V"
|
||||
description: "PSY - ‘I LUV IT’ M/V @ https://youtu.be/Xvjnoagk6GU PSY - ‘New Face’ M/V @https://youtu.be/OwJPPaEyqhI PSY - 8TH ALBUM '4X2=8' on iTunes @ https://smarturl.it/PSY_8thAlbum PSY - GANGNAM STYLE(강남스타일) on iTunes @ http://smarturl.it/PsyGangnam #PSY #싸이 #GANGNAMSTYLE #강남스타일 More about PSY@ http://www.psyp..."
|
||||
linkType: 0 // 0 = link, 1 = image
|
||||
thumbnailWidth: 480
|
||||
thumbnailHeight: 360
|
||||
thumbnailUrl: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
thumbnailDataUri: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
}
|
||||
ListElement {
|
||||
url: "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||
unfurled: true
|
||||
hostname: "www.youtube.com"
|
||||
title: "PSY - GANGNAM STYLE(강남스타일) M/V"
|
||||
description: "PSY - ‘I LUV IT’ M/V @ https://youtu.be/Xvjnoagk6GU PSY - ‘New Face’ M/V @https://youtu.be/OwJPPaEyqhI PSY - 8TH ALBUM '4X2=8' on iTunes @ https://smarturl.it/PSY_8thAlbum PSY - GANGNAM STYLE(강남스타일) on iTunes @ http://smarturl.it/PsyGangnam #PSY #싸이 #GANGNAMSTYLE #강남스타일 More about PSY@ http://www.psyp..."
|
||||
linkType: 0 // 0 = link, 1 = image
|
||||
thumbnailWidth: 480
|
||||
thumbnailHeight: 360
|
||||
thumbnailUrl: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
thumbnailDataUri: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
}
|
||||
ListElement {
|
||||
url: "https://www.youtube.com/watch?v=9bZkp7q19f0"
|
||||
unfurled: true
|
||||
hostname: "www.youtube.com"
|
||||
title: "PSY - GANGNAM STYLE(강남스타일) M/V"
|
||||
description: "PSY - ‘I LUV IT’ M/V @ https://youtu.be/Xvjnoagk6GU PSY - ‘New Face’ M/V @https://youtu.be/OwJPPaEyqhI PSY - 8TH ALBUM '4X2=8' on iTunes @ https://smarturl.it/PSY_8thAlbum PSY - GANGNAM STYLE(강남스타일) on iTunes @ http://smarturl.it/PsyGangnam #PSY #싸이 #GANGNAMSTYLE #강남스타일 More about PSY@ http://www.psyp..."
|
||||
linkType: 0 // 0 = link, 1 = image
|
||||
thumbnailWidth: 480
|
||||
thumbnailHeight: 360
|
||||
thumbnailUrl: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
thumbnailDataUri: "https://i.ytimg.com/vi/9bZkp7q19f0/hqdefault.jpg"
|
||||
}
|
||||
}
|
||||
localUnfurlLinks: {}
|
||||
isCurrentUser: true
|
||||
|
||||
onImageClicked: {
|
||||
console.log("image clicked")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
SplitView.minimumWidth: 300
|
||||
SplitView.preferredWidth: 300
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 25
|
||||
ColumnLayout {
|
||||
Label {
|
||||
text: qsTr("Sender")
|
||||
}
|
||||
CheckBox {
|
||||
text: qsTr("Current user")
|
||||
checked: linksMessageView.isCurrentUser
|
||||
onToggled: linksMessageView.isCurrentUser = !linksMessageView.isCurrentUser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.46069 13.6656C6.42831 13.957 6.78989 14.1174 6.98417 13.8977L12.6016 7.54762C12.8588 7.25683 12.6524 6.79857 12.2641 6.79857H9.09442C8.91541 6.79857 8.77613 6.64297 8.7959 6.46505L9.25486 2.33445C9.28724 2.04302 8.92565 1.88265 8.73137 2.10227L3.11397 8.45238C2.85673 8.74317 3.06318 9.20143 3.45142 9.20143H6.28554C6.64358 9.20143 6.92212 9.51264 6.88258 9.86848L6.46069 13.6656Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 552 B |
|
@ -0,0 +1,34 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
import utils 1.0
|
||||
import shared 1.0
|
||||
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property bool leftTail: true
|
||||
property real borderWidth: 1
|
||||
|
||||
readonly property Component clippingEffect: CalloutOpacityMask {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
leftTail: root.leftTail
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: Style.current.border
|
||||
layer.enabled: true
|
||||
layer.effect: root.clippingEffect
|
||||
|
||||
Rectangle {
|
||||
id: clipping
|
||||
anchors.fill: parent
|
||||
anchors.margins: root.borderWidth
|
||||
color: Style.current.background
|
||||
layer.enabled: true
|
||||
layer.effect: root.clippingEffect
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import QtQuick 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import utils 1.0
|
||||
|
||||
OpacityMask {
|
||||
id: root
|
||||
property bool leftTail: true
|
||||
readonly property int smallCorner: Style.current.radius / 2
|
||||
readonly property int bigCorner: Style.current.radius * 2
|
||||
readonly property int fakeCornerSize: bigCorner * 2
|
||||
|
||||
cached: true
|
||||
maskSource: Item {
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
radius: root.bigCorner
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: root.leftTail
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: !root.leftTail
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import shared.status 1.0
|
||||
|
||||
CalloutCard {
|
||||
id: root
|
||||
|
||||
/// The title of the callout card
|
||||
required property string title
|
||||
required property string description
|
||||
required property string footer
|
||||
property StatusAssetSettings logoSettings: StatusAssetSettings {
|
||||
width: 28
|
||||
height: 28
|
||||
bgRadius: bgWidth / 2
|
||||
}
|
||||
|
||||
property string bannerImageSource: ""
|
||||
|
||||
signal clicked()
|
||||
|
||||
borderWidth: 1
|
||||
padding: borderWidth
|
||||
implicitHeight: 290
|
||||
implicitWidth: 305
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
StatusImage {
|
||||
id: bannerImage
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 170
|
||||
asynchronous: true
|
||||
source: root.bannerImageSource
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
layer.enabled: true
|
||||
layer.effect: root.clippingEffect
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: 12
|
||||
Layout.bottomMargin: 12
|
||||
Layout.leftMargin: 12
|
||||
Layout.rightMargin: 12
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.maximumHeight: root.description.length ? 28 : 72
|
||||
StatusSmartIdenticon {
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.preferredWidth: 28
|
||||
Layout.preferredHeight: 28
|
||||
asset: root.logoSettings
|
||||
name: root.logoSettings.name
|
||||
visible: !!root.logoSettings.name.length || !!root.logoSettings.emoji.length
|
||||
}
|
||||
StatusBaseText {
|
||||
text: root.title
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
text: root.description
|
||||
font.pixelSize: 12
|
||||
wrapMode: Text.Wrap
|
||||
elide: Text.ElideRight
|
||||
color: Theme.palette.baseColor1
|
||||
visible: root.description.length
|
||||
}
|
||||
StatusBaseText {
|
||||
id: linkSite
|
||||
Layout.fillWidth: true
|
||||
text: root.footer
|
||||
font.pixelSize: 12
|
||||
lineHeight: 16
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: Theme.palette.baseColor1
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignBottom
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: root
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.clicked()
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
import QtQuick 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import utils 1.0
|
||||
import shared 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property bool isCurrentUser: false
|
||||
readonly property int smallCorner: Style.current.radius / 2
|
||||
readonly property int bigCorner: Style.current.radius * 2
|
||||
readonly property int fakeCornerSize: bigCorner * 2
|
||||
|
||||
Rectangle {
|
||||
width: parent.width + 2
|
||||
height: parent.height + 2
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.topMargin: -1
|
||||
anchors.leftMargin: -1
|
||||
radius: root.bigCorner
|
||||
border.width: 2
|
||||
border.color: Style.current.border
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.bottomMargin: -1
|
||||
anchors.leftMargin: -1
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: !root.isCurrentUser
|
||||
border.width: 2
|
||||
border.color: Style.current.border
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: -1
|
||||
anchors.rightMargin: -1
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: root.isCurrentUser
|
||||
border.width: 2
|
||||
border.color: Style.current.border
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Style.current.background
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
Rectangle {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
radius: root.bigCorner
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: !root.isCurrentUser
|
||||
}
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
width: root.fakeCornerSize
|
||||
height: root.fakeCornerSize
|
||||
radius: root.smallCorner
|
||||
visible: root.isCurrentUser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
CalloutCard 1.0 CalloutCard.qml
|
||||
FetchMoreMessagesButton 1.0 FetchMoreMessagesButton.qml
|
||||
GapComponent 1.0 GapComponent.qml
|
||||
LinkPreviewCard 1.0 LinkPreviewCard.qml
|
||||
UsernameLabel 1.0 UsernameLabel.qml
|
||||
DateGroup 1.0 DateGroup.qml
|
||||
UserImage 1.0 UserImage.qml
|
||||
|
@ -10,7 +12,6 @@ Retry 1.0 Retry.qml
|
|||
SendTransactionButton 1.0 SendTransactionButton.qml
|
||||
StateBubble 1.0 StateBubble.qml
|
||||
GasSelectorButton 1.0 GasSelectorButton.qml
|
||||
MessageBorder 1.0 MessageBorder.qml
|
||||
EmojiReaction 1.0 EmojiReaction.qml
|
||||
ProfileHeader 1.0 ProfileHeader.qml
|
||||
VerificationLabel 1.0 VerificationLabel.qml
|
||||
|
|
|
@ -16,13 +16,13 @@ import shared.controls.chat 1.0
|
|||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var messageStore
|
||||
required property var store
|
||||
required property var messageStore
|
||||
|
||||
property var linkPreviewModel
|
||||
property var localUnfurlLinks
|
||||
required property var linkPreviewModel
|
||||
required property var localUnfurlLinks
|
||||
|
||||
property bool isCurrentUser: false
|
||||
required property bool isCurrentUser
|
||||
|
||||
signal imageClicked(var image, var mouse, var imageSource, string url)
|
||||
|
||||
|
@ -47,40 +47,31 @@ ColumnLayout {
|
|||
property bool animated: false
|
||||
|
||||
asynchronous: true
|
||||
active: unfurled && hostname != ""
|
||||
|
||||
StateGroup {
|
||||
//Using StateGroup as a warkardound for https://bugreports.qt.io/browse/QTBUG-47796
|
||||
states: [
|
||||
State {
|
||||
name: "loadLinkPreview"
|
||||
when: linkMessageLoader.linkType === Constants.LinkPreviewType.Link
|
||||
PropertyChanges { target: linkMessageLoader; sourceComponent: unfurledLinkComponent }
|
||||
},
|
||||
State {
|
||||
name: "loadImage"
|
||||
when: linkMessageLoader.linkType === Constants.LinkPreviewType.Image
|
||||
PropertyChanges { target: linkMessageLoader; sourceComponent: unfurledImageComponent }
|
||||
sourceComponent: LinkPreviewCard {
|
||||
id: unfurledLink
|
||||
leftTail: !root.isCurrentUser
|
||||
|
||||
bannerImageSource: thumbnailUrl
|
||||
title: parent.title
|
||||
description: parent.description
|
||||
footer: hostname
|
||||
onClicked: {
|
||||
Global.openLink(url)
|
||||
}
|
||||
// NOTE: New unfurling not yet suppport status links.
|
||||
// Uncomment code below when implemented:
|
||||
// - https://github.com/status-im/status-go/issues/3762
|
||||
// State {
|
||||
// name: "statusInvitation"
|
||||
// when: linkMessageLoader.isStatusDeepLink
|
||||
// PropertyChanges { target: linkMessageLoader; sourceComponent: invitationBubble }
|
||||
// }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Remove this once we have gif support in new unfurling flow
|
||||
Component {
|
||||
id: unfurledImageComponent
|
||||
|
||||
MessageBorder {
|
||||
CalloutCard {
|
||||
implicitWidth: linkImage.width
|
||||
implicitHeight: linkImage.height
|
||||
isCurrentUser: root.isCurrentUser
|
||||
leftTail: !root.isCurrentUser
|
||||
|
||||
StatusChatImageLoader {
|
||||
id: linkImage
|
||||
|
@ -138,6 +129,8 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
// Code below can be dropped when New unfurling flow suppports GIFs.
|
||||
|
||||
Component {
|
||||
id: invitationBubble
|
||||
|
||||
|
@ -166,78 +159,6 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: unfurledLinkComponent
|
||||
|
||||
MessageBorder {
|
||||
id: unfurledLink
|
||||
implicitWidth: linkImage.visible ? linkImage.width + 2 : 300
|
||||
implicitHeight: {
|
||||
if (linkImage.visible) {
|
||||
return linkImage.height + (Style.current.smallPadding * 2) + (linkTitle.height + 2 + linkSite.height)
|
||||
}
|
||||
return (Style.current.smallPadding * 2) + linkTitle.height + 2 + linkSite.height
|
||||
}
|
||||
isCurrentUser: root.isCurrentUser
|
||||
|
||||
StatusChatImageLoader {
|
||||
id: linkImage
|
||||
objectName: "LinksMessageView_unfurledLinkComponent_linkImage"
|
||||
source: thumbnailUrl
|
||||
visible: thumbnailUrl.length
|
||||
imageWidth: Math.min(300, thumbnailWidth > 0 ? thumbnailWidth : 300)
|
||||
isCurrentUser: root.isCurrentUser
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
isOnline: root.store.mainModuleInst.isOnline
|
||||
asynchronous: true
|
||||
onClicked: {
|
||||
Global.openLink(url)
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: linkTitle
|
||||
text: title
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
wrapMode: Text.Wrap
|
||||
anchors.top: linkImage.visible ? linkImage.bottom : parent.top
|
||||
anchors.topMargin: Style.current.smallPadding
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
anchors.rightMargin: Style.current.smallPadding
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: linkSite
|
||||
text: hostname
|
||||
font.pixelSize: 12
|
||||
font.weight: Font.Thin
|
||||
color: Theme.palette.baseColor1
|
||||
anchors.top: linkTitle.bottom
|
||||
anchors.topMargin: 2
|
||||
anchors.left: linkTitle.left
|
||||
anchors.bottomMargin: Style.current.halfPadding
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.top: linkImage.visible ? linkImage.top : linkTitle.top
|
||||
anchors.left: linkImage.visible ? linkImage.left : linkTitle.left
|
||||
anchors.right: linkImage.visible ? linkImage.right : linkTitle.right
|
||||
anchors.bottom: linkSite.bottom
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
Global.openLink(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Code below can be dropped when New unfurling flow suppports GIFs.
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -454,6 +375,4 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue