378 lines
13 KiB
QML
378 lines
13 KiB
QML
import QtQuick 2.13
|
|
import QtGraphicalEffects 1.13
|
|
import QtQuick.Layouts 1.13
|
|
|
|
import utils 1.0
|
|
import "../../../../shared"
|
|
import "../../../../shared/panels"
|
|
import "../../../../shared/status"
|
|
|
|
import "../controls"
|
|
import "../panels"
|
|
|
|
Column {
|
|
id: root
|
|
property string linkUrls: ""
|
|
property var container
|
|
property bool isCurrentUser: false
|
|
property bool isImageLink: false
|
|
readonly property string uuid: Utils.uuid()
|
|
spacing: Style.current.halfPadding
|
|
|
|
ListModel {
|
|
id: linksModel
|
|
Component.onCompleted: {
|
|
if (!root.linkUrls) {
|
|
return
|
|
}
|
|
root.linkUrls.split(" ").forEach(link => {
|
|
linksModel.append({link})
|
|
})
|
|
}
|
|
}
|
|
|
|
Repeater {
|
|
id: linksRepeater
|
|
model: linksModel // doesn't work with a JSON object model!
|
|
|
|
delegate: Loader {
|
|
id: linkMessageLoader
|
|
property bool fetched: false
|
|
property var linkData
|
|
property int linkWidth: linksRepeater.width
|
|
|
|
active: true
|
|
|
|
Connections {
|
|
target: appSettings
|
|
onWhitelistedUnfurlingSitesChanged: {
|
|
fetched = false
|
|
linkMessageLoader.sourceComponent = undefined
|
|
linkMessageLoader.sourceComponent = linkMessageLoader.getSourceComponent()
|
|
}
|
|
onNeverAskAboutUnfurlingAgainChanged: {
|
|
linkMessageLoader.sourceComponent = undefined
|
|
linkMessageLoader.sourceComponent = linkMessageLoader.getSourceComponent()
|
|
}
|
|
onDisplayChatImagesChanged: {
|
|
linkMessageLoader.sourceComponent = undefined
|
|
linkMessageLoader.sourceComponent = linkMessageLoader.getSourceComponent()
|
|
}
|
|
}
|
|
Connections {
|
|
id: linkFetchConnections
|
|
enabled: false
|
|
target: chatsModel
|
|
onLinkPreviewDataWasReceived: {
|
|
let response
|
|
try {
|
|
response = JSON.parse(previewData)
|
|
|
|
} catch (e) {
|
|
console.error(previewData, e)
|
|
return
|
|
}
|
|
|
|
|
|
if (response.uuid !== root.uuid) return
|
|
|
|
linkFetchConnections.enabled = false
|
|
|
|
if (!response.success) {
|
|
console.error(response.result.error)
|
|
return undefined
|
|
}
|
|
|
|
linkData = response.result
|
|
|
|
if (linkData.contentType.startsWith("image/")) {
|
|
return linkMessageLoader.sourceComponent = unfurledImageComponent
|
|
}
|
|
if (linkData.site && linkData.title) {
|
|
linkData.address = link
|
|
return linkMessageLoader.sourceComponent = unfurledLinkComponent
|
|
}
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
id: linkCommunityFetchConnections
|
|
enabled: false
|
|
target: chatsModel.communities
|
|
onCommunityAdded: {
|
|
if (communityId !== linkData.communityId) {
|
|
return
|
|
}
|
|
linkCommunityFetchConnections.enabled = false
|
|
const data = Utils.getLinkDataForStatusLinks(link)
|
|
if (data) {
|
|
linkData = data
|
|
if (!data.fetching && data.communityId) {
|
|
return linkMessageLoader.sourceComponent = invitationBubble
|
|
}
|
|
|
|
return linkMessageLoader.sourceComponent = unfurledLinkComponent
|
|
}
|
|
}
|
|
}
|
|
|
|
function getSourceComponent() {
|
|
// Reset the height in case we set it to 0 below. See note below
|
|
// for more information
|
|
this.height = undefined
|
|
if (Utils.hasImageExtension(link)) {
|
|
if (appSettings.displayChatImages) {
|
|
linkData = {
|
|
thumbnailUrl: link
|
|
}
|
|
return unfurledImageComponent
|
|
} else {
|
|
if (isImageLink && index > 0) {
|
|
return
|
|
}
|
|
|
|
isImageLink = true
|
|
return enableLinkComponent
|
|
}
|
|
}
|
|
|
|
let linkWhiteListed = false
|
|
const linkHostname = Utils.getHostname(link)
|
|
const linkExists = Object.keys(appSettings.whitelistedUnfurlingSites).some(function(whitelistedHostname) {
|
|
const exists = linkHostname.endsWith(whitelistedHostname)
|
|
if (exists) {
|
|
linkWhiteListed = appSettings.whitelistedUnfurlingSites[whitelistedHostname] === true
|
|
}
|
|
return exists
|
|
})
|
|
if (!linkWhiteListed && linkExists && !appSettings.neverAskAboutUnfurlingAgain) {
|
|
return enableLinkComponent
|
|
}
|
|
if (linkWhiteListed) {
|
|
if (fetched) {
|
|
return
|
|
}
|
|
fetched = true
|
|
|
|
const data = Utils.getLinkDataForStatusLinks(link)
|
|
if (data) {
|
|
linkData = data
|
|
if (data.fetching && data.communityId) {
|
|
linkCommunityFetchConnections.enabled = true
|
|
return
|
|
}
|
|
if (data.communityId) {
|
|
return invitationBubble
|
|
}
|
|
|
|
return unfurledLinkComponent
|
|
}
|
|
|
|
linkFetchConnections.enabled = true
|
|
return chatsModel.getLinkPreviewData(link, root.uuid)
|
|
}
|
|
// setting the height to 0 allows the "enable link" dialog to
|
|
// disappear correctly when appSettings.neverAskAboutUnfurlingAgain
|
|
// is true. The height is reset at the top of this method.
|
|
this.height = 0
|
|
return undefined
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
// putting this is onCompleted prevents automatic binding, where
|
|
// QML warns of a binding loop detected
|
|
this.sourceComponent = getSourceComponent()
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: unfurledImageComponent
|
|
|
|
MessageBorder {
|
|
width: linkImage.width
|
|
height: linkImage.height
|
|
isCurrentUser: root.isCurrentUser
|
|
StatusChatImageLoader {
|
|
id: linkImage
|
|
anchors.centerIn: parent
|
|
container: root.container
|
|
source: linkData.thumbnailUrl
|
|
imageWidth: 300
|
|
isCurrentUser: root.isCurrentUser
|
|
onClicked: imageClick(linkImage.imageAlias)
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: invitationBubble
|
|
InvitationBubblePanel {
|
|
communityId: linkData.communityId
|
|
isLink: true
|
|
anchors.left: parent.left
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: unfurledLinkComponent
|
|
MessageBorder {
|
|
width: linkImage.width + 2
|
|
height: linkImage.height + (Style.current.smallPadding * 2) + linkTitle.height + 2 + linkSite.height
|
|
isCurrentUser: root.isCurrentUser
|
|
|
|
StatusChatImageLoader {
|
|
id: linkImage
|
|
container: root.container
|
|
source: linkData.thumbnailUrl
|
|
imageWidth: 300
|
|
isCurrentUser: root.isCurrentUser
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 1
|
|
}
|
|
StyledText {
|
|
id: linkTitle
|
|
text: linkData.title
|
|
font.pixelSize: 13
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: linkImage.bottom
|
|
anchors.rightMargin: Style.current.smallPadding
|
|
anchors.leftMargin: Style.current.smallPadding
|
|
anchors.topMargin: Style.current.smallPadding
|
|
}
|
|
|
|
StyledText {
|
|
id: linkSite
|
|
text: linkData.site
|
|
font.pixelSize: 12
|
|
font.weight: Font.Thin
|
|
color: Style.current.secondaryText
|
|
anchors.top: linkTitle.bottom
|
|
anchors.topMargin: 2
|
|
anchors.left: linkTitle.left
|
|
anchors.bottomMargin: Style.current.smallPadding
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.top: linkImage.top
|
|
anchors.left: linkImage.left
|
|
anchors.right: linkImage.right
|
|
anchors.bottom: linkSite.bottom
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: {
|
|
if (!!linkData.callback) {
|
|
return linkData.callback()
|
|
}
|
|
|
|
appMain.openLink(linkData.address)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: enableLinkComponent
|
|
Rectangle {
|
|
id: enableLinkRoot
|
|
width: 300
|
|
height: childrenRect.height + Style.current.smallPadding
|
|
radius: 16
|
|
border.width: 1
|
|
border.color: Style.current.border
|
|
color:Style.current.background
|
|
|
|
StatusIconButton {
|
|
icon.name: "close"
|
|
icon.width: 20
|
|
icon.height: 20
|
|
anchors.top: parent.top
|
|
anchors.topMargin: Style.current.smallPadding
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: Style.current.smallPadding
|
|
onClicked: {
|
|
enableLinkRoot.height = 0
|
|
enableLinkRoot.visible = false
|
|
}
|
|
}
|
|
|
|
Image {
|
|
id: unfurlingImage
|
|
source: Style.png("unfurling-image")
|
|
width: 132
|
|
height: 94
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.top: parent.top
|
|
anchors.topMargin: Style.current.smallPadding
|
|
}
|
|
|
|
StyledText {
|
|
id: enableText
|
|
//% "Enable automatic image unfurling"
|
|
text: isImageLink ? qsTrId("enable-automatic-image-unfurling") :
|
|
//% "Enable link previews in chat?"
|
|
qsTrId("enable-link-previews")
|
|
horizontalAlignment: Text.AlignHCenter
|
|
width: parent.width
|
|
wrapMode: Text.WordWrap
|
|
anchors.top: unfurlingImage.bottom
|
|
anchors.topMargin: Style.current.halfPadding
|
|
font.pixelSize: 15
|
|
}
|
|
|
|
StyledText {
|
|
id: infoText
|
|
//% "Once enabled, links posted in the chat may share your metadata with their owners"
|
|
text: qsTrId("once-enabled--links-posted-in-the-chat-may-share-your-metadata-with-their-owners")
|
|
horizontalAlignment: Text.AlignHCenter
|
|
width: parent.width
|
|
wrapMode: Text.WordWrap
|
|
anchors.top: enableText.bottom
|
|
font.pixelSize: 13
|
|
color: Style.current.secondaryText
|
|
}
|
|
|
|
Separator {
|
|
id: sep1
|
|
anchors.top: infoText.bottom
|
|
anchors.topMargin: Style.current.smallPadding
|
|
}
|
|
|
|
StatusButton {
|
|
id: enableBtn
|
|
//% "Enable in Settings"
|
|
text: qsTrId("enable-in-settings")
|
|
type: "secondary"
|
|
onClicked: {
|
|
appMain.changeAppSection(Constants.profile)
|
|
// TODO: replace with shared store constant
|
|
// Profile/RootStore.privacy_and_security_id
|
|
profileLayoutContainer.changeProfileSection(3)
|
|
}
|
|
width: parent.width
|
|
anchors.top: sep1.bottom
|
|
}
|
|
|
|
Separator {
|
|
id: sep2
|
|
anchors.top: enableBtn.bottom
|
|
anchors.topMargin: 0
|
|
}
|
|
|
|
StatusButton {
|
|
//% "Don't ask me again"
|
|
text: qsTrId("dont-ask")
|
|
type: "secondary"
|
|
onClicked: {
|
|
appSettings.neverAskAboutUnfurlingAgain = true
|
|
}
|
|
width: parent.width
|
|
anchors.top: sep2.bottom
|
|
}
|
|
}
|
|
}
|
|
}
|