154 lines
5.6 KiB
QML
154 lines
5.6 KiB
QML
|
import QtQuick 2.15
|
||
|
import QtQuick.Controls 2.15
|
||
|
import QtGraphicalEffects 1.15
|
||
|
import QtQuick.Layouts 1.15
|
||
|
|
||
|
import StatusQ.Core 0.1
|
||
|
|
||
|
import shared.status 1.0
|
||
|
import shared.controls.chat 1.0
|
||
|
|
||
|
import SortFilterProxyModel 0.2
|
||
|
|
||
|
Control {
|
||
|
id: root
|
||
|
|
||
|
required property var imagePreviewModel
|
||
|
required property var linkPreviewModel
|
||
|
|
||
|
readonly property alias hoveredUrl: d.hoveredUrl
|
||
|
readonly property int contentItemsCount: imagePreviewModel.length + d.filteredModel.count
|
||
|
|
||
|
signal imageRemoved(int index)
|
||
|
signal imageClicked(var chatImage)
|
||
|
signal linkReload(string link)
|
||
|
signal linkClicked(string link)
|
||
|
signal linkRemoved(string link)
|
||
|
|
||
|
horizontalPadding: 12
|
||
|
topPadding: 12
|
||
|
|
||
|
contentItem: Item {
|
||
|
id: opacityMaskWrapper
|
||
|
|
||
|
anchors.fill: parent
|
||
|
|
||
|
implicitWidth: flickable.implicitWidth
|
||
|
implicitHeight: flickable.implicitHeight
|
||
|
|
||
|
opacity: 0
|
||
|
|
||
|
Flickable {
|
||
|
id: flickable
|
||
|
|
||
|
anchors.fill: parent
|
||
|
anchors.leftMargin: root.leftPadding
|
||
|
anchors.rightMargin: root.rightPadding
|
||
|
anchors.bottomMargin: root.bottomPadding
|
||
|
anchors.topMargin: root.topPadding
|
||
|
|
||
|
implicitHeight: contentHeight
|
||
|
implicitWidth: contentWidth
|
||
|
|
||
|
contentWidth: layout.width
|
||
|
contentHeight: layout.height
|
||
|
|
||
|
RowLayout {
|
||
|
id: layout
|
||
|
spacing: 8
|
||
|
StatusChatInputImageArea {
|
||
|
id: imageArea
|
||
|
Layout.preferredHeight: 64
|
||
|
spacing: layout.spacing
|
||
|
imageSource: imagePreviewModel
|
||
|
onImageClicked: root.imageClicked(chatImage)
|
||
|
onImageRemoved: root.imageRemoved(index)
|
||
|
visible: !!imagePreviewModel && imagePreviewModel.length > 0
|
||
|
}
|
||
|
Repeater {
|
||
|
model: d.filteredModel
|
||
|
delegate: LinkPreviewMiniCard {
|
||
|
// Model properties
|
||
|
required property string title
|
||
|
required property string url
|
||
|
required property bool unfurled
|
||
|
required property bool immutable
|
||
|
required property string hostname
|
||
|
required property string description
|
||
|
required property int linkType
|
||
|
required property int thumbnailWidth
|
||
|
required property int thumbnailHeight
|
||
|
required property string thumbnailUrl
|
||
|
required property string thumbnailDataUri
|
||
|
|
||
|
required property int index
|
||
|
|
||
|
Layout.preferredHeight: 64
|
||
|
|
||
|
titleStr: title
|
||
|
domain: hostname //TODO: use domain when available
|
||
|
favIconUrl: thumbnailImageUrl //TODO: use favicon when available
|
||
|
communityName: "" //TODO: add community info when available
|
||
|
channelName: "" //TODO: add community info when available
|
||
|
|
||
|
thumbnailImageUrl: thumbnailDataUri.length > 0 ? thumbnailDataUri : thumbnailUrl
|
||
|
type: linkType === 0 ? LinkPreviewMiniCard.Type.Link : LinkPreviewMiniCard.Type.Image
|
||
|
previewState: unfurled && hostname != "" ? LinkPreviewMiniCard.State.Loaded :
|
||
|
unfurled && hostname === "" ? LinkPreviewMiniCard.State.LoadingFailed :
|
||
|
!unfurled ? LinkPreviewMiniCard.State.Loading : LinkPreviewMiniCard.State.Invalid
|
||
|
|
||
|
onClose: root.linkRemoved(url)
|
||
|
onRetry: root.linkReload(url)
|
||
|
onClicked: root.linkClicked(url)
|
||
|
onContainsMouseChanged: {
|
||
|
if (containsMouse) {
|
||
|
d.hoveredUrl = url
|
||
|
} else if (d.hoveredUrl === url) {
|
||
|
d.hoveredUrl = ""
|
||
|
}
|
||
|
}
|
||
|
Component.onDestruction: {
|
||
|
if(d.hoveredUrl === url) {
|
||
|
d.hoveredUrl = ""
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LinearGradient {
|
||
|
id: horizontalClipMask
|
||
|
anchors.fill: opacityMaskWrapper
|
||
|
visible: false
|
||
|
start: Qt.point(0 , 0)
|
||
|
end: Qt.point(horizontalClipMask.width, 0)
|
||
|
gradient: Gradient {
|
||
|
GradientStop { position: 0.0; color: "transparent" }
|
||
|
GradientStop { position: root.horizontalPadding / horizontalClipMask.width; color: "white" }
|
||
|
GradientStop { position: 1 - root.horizontalPadding / horizontalClipMask.width; color: "white" }
|
||
|
GradientStop { position: 1; color: "transparent" }
|
||
|
}
|
||
|
}
|
||
|
OpacityMask {
|
||
|
anchors.fill: opacityMaskWrapper
|
||
|
source: opacityMaskWrapper
|
||
|
maskSource: horizontalClipMask
|
||
|
}
|
||
|
|
||
|
QtObject {
|
||
|
id: d
|
||
|
property string hoveredUrl: ""
|
||
|
property SortFilterProxyModel filteredModel: SortFilterProxyModel {
|
||
|
id: filteredModel
|
||
|
sourceModel: root.linkPreviewModel
|
||
|
filters: [
|
||
|
ExpressionFilter {
|
||
|
expression: { return !model.immutable || model.unfurled } // Filter out immutable links that haven't been unfurled yet
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
}
|
||
|
}
|