2023-09-26 14:12:33 +00:00
|
|
|
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 StatusQ.Controls 0.1
|
|
|
|
|
|
|
|
import shared 1.0
|
|
|
|
import utils 1.0
|
|
|
|
|
2023-10-25 15:20:02 +00:00
|
|
|
import "./private" 1.0
|
|
|
|
|
2023-09-26 14:12:33 +00:00
|
|
|
CalloutCard {
|
|
|
|
id: root
|
|
|
|
|
|
|
|
enum State {
|
|
|
|
Invalid,
|
|
|
|
Loading,
|
|
|
|
LoadingFailed,
|
|
|
|
Loaded
|
|
|
|
}
|
|
|
|
|
2023-10-25 15:20:02 +00:00
|
|
|
readonly property LinkData linkData: LinkData { }
|
|
|
|
readonly property UserData userData: UserData { }
|
|
|
|
readonly property CommunityData communityData: CommunityData { }
|
|
|
|
readonly property ChannelData channelData: ChannelData { }
|
2023-10-13 13:36:07 +00:00
|
|
|
|
2023-09-26 14:12:33 +00:00
|
|
|
required property int previewState
|
|
|
|
required property int type
|
|
|
|
|
|
|
|
readonly property bool containsMouse: mouseArea.hovered || reloadButton.hovered || closeButton.hovered
|
|
|
|
|
|
|
|
signal close()
|
|
|
|
signal retry()
|
|
|
|
signal clicked(var eventPoint)
|
2023-10-09 08:45:16 +00:00
|
|
|
signal rightClicked(var eventPoint)
|
2023-09-26 14:12:33 +00:00
|
|
|
|
|
|
|
implicitWidth: 260
|
|
|
|
implicitHeight: 64
|
|
|
|
verticalPadding: 15
|
|
|
|
horizontalPadding: 12
|
|
|
|
borderColor: Theme.palette.directColor7
|
2023-11-15 08:00:25 +00:00
|
|
|
backgroundColor: root.containsMouse ? Theme.palette.directColor7 : Style.current.background
|
2023-09-26 14:12:33 +00:00
|
|
|
|
|
|
|
// behavior
|
|
|
|
states: [
|
|
|
|
State {
|
|
|
|
name: "invalid"
|
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Invalid
|
|
|
|
PropertyChanges {
|
|
|
|
target: root
|
|
|
|
visible: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loading"
|
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loading
|
|
|
|
PropertyChanges { target: root; visible: true; dashedBorder: true; }
|
|
|
|
PropertyChanges { target: loadingAnimation; visible: true; }
|
|
|
|
PropertyChanges { target: titleText; text: qsTr("Generating preview..."); color: Theme.palette.baseColor1 }
|
|
|
|
PropertyChanges { target: subtitleText; visible: false; }
|
|
|
|
PropertyChanges { target: reloadButton; visible: false; }
|
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loadingFailed"
|
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.LoadingFailed
|
|
|
|
PropertyChanges { target: root; visible: true; dashedBorder: true; }
|
|
|
|
PropertyChanges { target: loadingAnimation; visible: false; }
|
|
|
|
PropertyChanges { target: titleText; text: qsTr("Failed to generate preview"); color: Theme.palette.directColor1 }
|
|
|
|
PropertyChanges { target: subtitleText; visible: false; }
|
|
|
|
PropertyChanges { target: reloadButton; visible: true; }
|
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loaded"
|
2023-10-25 15:20:02 +00:00
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loaded &&
|
|
|
|
root.type === Constants.LinkPreviewType.Standard &&
|
|
|
|
root.linkData.type === Constants.StandardLinkPreviewType.Link
|
2023-09-26 14:12:33 +00:00
|
|
|
PropertyChanges {
|
|
|
|
target: root; visible: true; dashedBorder: false; borderWidth: 0;
|
|
|
|
borderColor: backgroundColor;
|
|
|
|
}
|
|
|
|
PropertyChanges { target: loadingAnimation; visible: false; }
|
2023-10-25 15:20:02 +00:00
|
|
|
PropertyChanges { target: titleText; text: root.linkData.title; color: Theme.palette.directColor1 }
|
|
|
|
PropertyChanges { target: subtitleText; visible: true; text: root.linkData.domain; }
|
2023-09-26 14:12:33 +00:00
|
|
|
PropertyChanges { target: reloadButton; visible: false; }
|
2023-10-25 15:20:02 +00:00
|
|
|
PropertyChanges {
|
|
|
|
target: favIcon
|
|
|
|
visible: true
|
|
|
|
name: root.linkData.title
|
|
|
|
asset.isLetterIdenticon: !root.linkData.image
|
|
|
|
asset.color: Theme.palette.baseColor2
|
|
|
|
}
|
2023-09-26 14:12:33 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loadedImage"
|
2023-10-25 15:20:02 +00:00
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loaded &&
|
|
|
|
root.type === Constants.LinkPreviewType.Standard &&
|
|
|
|
root.linkData.type === Constants.StandardLinkPreviewType.Image
|
2023-09-26 14:12:33 +00:00
|
|
|
extend: "loaded"
|
2023-10-25 15:20:02 +00:00
|
|
|
PropertyChanges { target: thumbnailImage; visible: root.linkData.thumbnail != ""; image.source: root.linkData.thumbnail; }
|
|
|
|
PropertyChanges { target: favIcon; visible: true; name: root.linkData.domain; asset.isLetterIdenticon: true; asset.color: Theme.palette.baseColor2; }
|
|
|
|
PropertyChanges { target: subtitleText; visible: true; text: root.linkData.domain; }
|
2023-09-26 14:12:33 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loadedCommunity"
|
2023-10-25 15:20:02 +00:00
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loaded && root.type === Constants.LinkPreviewType.StatusCommunity
|
2023-09-26 14:12:33 +00:00
|
|
|
extend: "loaded"
|
2023-10-25 15:20:02 +00:00
|
|
|
PropertyChanges { target: titleText; text: root.communityData.name; }
|
|
|
|
PropertyChanges { target: subtitleText; visible: true; text: Constants.externalStatusLink; }
|
|
|
|
PropertyChanges {
|
|
|
|
target: favIcon
|
|
|
|
visible: true
|
|
|
|
name: root.communityData.name
|
|
|
|
asset.isLetterIdenticon: root.communityData.image.length === 0
|
|
|
|
asset.color: root.communityData.color
|
|
|
|
asset.name: root.communityData.image
|
|
|
|
}
|
2023-09-26 14:12:33 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loadedChannel"
|
2023-10-25 15:20:02 +00:00
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loaded && root.type === Constants.LinkPreviewType.StatusCommunityChannel
|
|
|
|
extend: "loadedCommunity"
|
|
|
|
PropertyChanges { target: titleText; text: root.channelData.communityData.name; Layout.fillWidth: false; Layout.maximumWidth: Math.min(92, implicitWidth); }
|
|
|
|
PropertyChanges { target: secondTitleText; text: "#" + root.channelData.name; visible: true; }
|
|
|
|
PropertyChanges {
|
|
|
|
target: favIcon
|
|
|
|
visible: true
|
|
|
|
name: root.channelData.communityData.name
|
|
|
|
asset.isLetterIdenticon: root.channelData.communityData.image.length === 0
|
|
|
|
asset.color: root.channelData.communityData.color
|
|
|
|
asset.name: root.channelData.communityData.image
|
|
|
|
}
|
2023-09-26 14:12:33 +00:00
|
|
|
},
|
|
|
|
State {
|
|
|
|
name: "loadedUser"
|
2023-10-25 15:20:02 +00:00
|
|
|
when: root.previewState === LinkPreviewMiniCard.State.Loaded && root.type === Constants.LinkPreviewType.StatusContact
|
2023-09-26 14:12:33 +00:00
|
|
|
extend: "loaded"
|
2023-10-25 15:20:02 +00:00
|
|
|
PropertyChanges { target: titleText; text: root.userData.name; Layout.fillWidth: false; Layout.maximumWidth: Math.min(92, implicitWidth); }
|
|
|
|
PropertyChanges { target: subtitleText; visible: true; text: Constants.externalStatusLink; }
|
2023-09-26 14:20:59 +00:00
|
|
|
PropertyChanges {
|
|
|
|
target: favIcon
|
|
|
|
visible: true
|
2023-10-25 15:20:02 +00:00
|
|
|
name: root.userData.name
|
|
|
|
asset.name: root.userData.image
|
|
|
|
asset.isLetterIdenticon: root.userData.image.length === 0
|
2023-09-26 14:20:59 +00:00
|
|
|
asset.charactersLen: 2
|
|
|
|
asset.color: Theme.palette.miscColor9
|
|
|
|
}
|
2023-09-26 14:12:33 +00:00
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
contentItem: Item {
|
2023-09-26 14:20:59 +00:00
|
|
|
implicitHeight: layout.implicitHeight
|
|
|
|
implicitWidth: layout.implicitWidth
|
|
|
|
|
2023-09-26 14:12:33 +00:00
|
|
|
RowLayout {
|
2023-09-26 14:20:59 +00:00
|
|
|
id: layout
|
2023-09-26 14:12:33 +00:00
|
|
|
anchors.fill: parent
|
|
|
|
spacing: 0
|
|
|
|
LoadingAnimation {
|
|
|
|
id: loadingAnimation
|
|
|
|
Layout.alignment: Qt.AlignVCenter
|
|
|
|
Layout.margins: 4
|
|
|
|
visible: false
|
|
|
|
}
|
|
|
|
StatusSmartIdenticon {
|
|
|
|
id: favIcon
|
|
|
|
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
|
|
|
Layout.topMargin: 1
|
|
|
|
Layout.preferredWidth: 16
|
|
|
|
Layout.preferredHeight: 16
|
|
|
|
visible: false
|
|
|
|
asset.letterSize: asset.charactersLen == 1 ? 10 : 7
|
|
|
|
}
|
|
|
|
ColumnLayout {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
Layout.leftMargin: 8
|
|
|
|
spacing: 0
|
|
|
|
RowLayout {
|
|
|
|
id: titleRow
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
spacing: 0
|
|
|
|
StatusBaseText {
|
|
|
|
id: titleText
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
font.pixelSize: Style.current.additionalTextSize
|
|
|
|
font.weight: Font.Medium
|
|
|
|
wrapMode: Text.Wrap
|
|
|
|
elide: Text.ElideRight
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
maximumLineCount: 1
|
|
|
|
}
|
|
|
|
StatusIcon {
|
|
|
|
id: secondTitleIcon
|
|
|
|
width: 16
|
|
|
|
height: 16
|
|
|
|
icon: "tiny/chevron-right"
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
visible: secondTitleText.visible
|
|
|
|
}
|
|
|
|
StatusBaseText {
|
|
|
|
id: secondTitleText
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
font.pixelSize: Style.current.additionalTextSize
|
|
|
|
font.weight: Font.Medium
|
|
|
|
wrapMode: Text.Wrap
|
|
|
|
elide: Text.ElideRight
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
maximumLineCount: 1
|
|
|
|
visible: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StatusBaseText {
|
|
|
|
id: subtitleText
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
font.pixelSize: Style.current.tertiaryTextFontSize
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
wrapMode: Text.WordWrap
|
|
|
|
elide: Text.ElideRight
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StatusRoundedImage {
|
|
|
|
id: thumbnailImage
|
|
|
|
Layout.alignment: Qt.AlignRight
|
|
|
|
Layout.rightMargin: 4
|
|
|
|
implicitWidth: 34
|
|
|
|
implicitHeight: 34
|
|
|
|
radius: 4
|
|
|
|
visible: false
|
|
|
|
}
|
|
|
|
StatusFlatButton {
|
|
|
|
id: reloadButton
|
|
|
|
icon.name: "refresh"
|
|
|
|
size: StatusBaseButton.Size.Small
|
|
|
|
hoverColor: Theme.palette.directColor8
|
|
|
|
textColor: Theme.palette.directColor1
|
|
|
|
onClicked: root.retry()
|
|
|
|
}
|
|
|
|
StatusFlatButton {
|
|
|
|
id: closeButton
|
|
|
|
icon.name: "close"
|
|
|
|
size: StatusBaseButton.Size.Small
|
|
|
|
hoverColor: Theme.palette.directColor8
|
|
|
|
textColor: Theme.palette.directColor1
|
|
|
|
onClicked: root.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HoverHandler {
|
|
|
|
id: mouseArea
|
|
|
|
target: background
|
|
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
}
|
|
|
|
TapHandler {
|
|
|
|
id: tapHandler
|
|
|
|
target: background
|
|
|
|
onTapped: root.clicked(eventPoint)
|
|
|
|
}
|
2023-10-09 08:45:16 +00:00
|
|
|
TapHandler {
|
|
|
|
acceptedButtons: Qt.RightButton
|
|
|
|
onTapped: root.rightClicked(eventPoint)
|
|
|
|
}
|
2023-09-26 14:12:33 +00:00
|
|
|
}
|