diff --git a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml index 235a349f835..29fb1ab6256 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusMessage.qml @@ -40,6 +40,7 @@ Control { property string messageAttachments: "" property var reactionIcons: [] property var linkPreviewModel + property var localUnfurlLinks property string messageId: "" property bool editMode: false @@ -349,7 +350,9 @@ Control { Loader { id: linksLoader Layout.fillWidth: true - active: !root.editMode && root.linkPreviewModel && root.linkPreviewModel.count > 0 + active: !root.editMode && + ((!!root.linkPreviewModel && root.linkPreviewModel.count > 0) + || (!!root.localUnfurlLinks && root.localUnfurlLinks.length > 0)) visible: active } Loader { diff --git a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml index 2c4f4289b3e..6fa88dd603b 100644 --- a/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/PinnedMessagesPopup.qml @@ -99,6 +99,7 @@ StatusDialog { sticker: model.sticker stickerPack: model.stickerPack linkPreviewModel: model.linkPreviewModel + links: model.links transactionParams: model.transactionParameters quotedMessageText: model.quotedMessageParsedText quotedMessageFrom: model.quotedMessageFrom diff --git a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml index eeb1f908b0b..908de7d7026 100644 --- a/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatMessagesView.qml @@ -297,6 +297,7 @@ Item { onEditModeOnChanged: root.editModeChanged(editModeOn) isEdited: model.isEdited linkPreviewModel: model.linkPreviewModel + links: model.links messageAttachments: model.messageAttachments transactionParams: model.transactionParameters hasMention: model.mentioned diff --git a/ui/imports/shared/views/chat/LinksMessageView.qml b/ui/imports/shared/views/chat/LinksMessageView.qml index 73f7cb42930..b867e808de0 100644 --- a/ui/imports/shared/views/chat/LinksMessageView.qml +++ b/ui/imports/shared/views/chat/LinksMessageView.qml @@ -18,7 +18,9 @@ ColumnLayout { property var store property var messageStore + property var linkPreviewModel + property var localUnfurlLinks property bool isCurrentUser: false @@ -42,6 +44,7 @@ ColumnLayout { required property int thumbnailHeight required property string thumbnailUrl required property string thumbnailDataUri + property bool animated: false asynchronous: true @@ -93,7 +96,7 @@ ColumnLayout { playing: globalAnimationEnabled && localAnimationEnabled isOnline: root.store.mainModuleInst.isOnline asynchronous: true - isAnimated: false // FIXME: GIFs are not supported with new unfurling yet + isAnimated: animated // FIXME: GIFs are not supported with new unfurling yet onClicked: { if (isAnimated && !playing) localAnimationEnabled = true @@ -231,4 +234,226 @@ ColumnLayout { } } } + + + // Code below can be dropped when New unfurling flow suppports GIFs. + + QtObject { + id: d + + readonly property string uuid: Utils.uuid() + readonly property string whiteListedImgExtensions: Constants.acceptedImageExtensions.toString() + readonly property string whiteListedUrls: JSON.stringify(localAccountSensitiveSettings.whitelistedUnfurlingSites) + readonly property string getLinkPreviewDataId: { + if (root.localUnfurlLinks === "") + return "" + return root.messageStore.messageModule.getLinkPreviewData(root.localUnfurlLinks, + d.uuid, + whiteListedUrls, + whiteListedImgExtensions, + localAccountSensitiveSettings.displayChatImages) + } + + + onGetLinkPreviewDataIdChanged: { + + linkFetchConnections.enabled = root.localUnfurlLinks !== "" + } + } + + Connections { + id: linkFetchConnections + enabled: false + target: root.messageStore.messageModule + + function onLinkPreviewDataWasReceived(previewData, uuid) { + if (d.uuid !== uuid) + return + linkFetchConnections.enabled = false + try { + linksModel.rawData = JSON.parse(previewData) + } + catch(e) { + console.warn("error parsing link preview data", previewData) + } + } + } + + ListModel { + id: linksModel + + property var rawData + + onRawDataChanged: { + linksModel.clear() + rawData.links.forEach((link) => { + linksModel.append(link) + }) + } + } + + Repeater { + id: tempRepeater + visible: !RootStore.neverAskAboutUnfurlingAgain + model: linksModel + + delegate: Loader { + id: tempLoader + + required property var result + required property string link + required property int index + required property bool unfurl + required property bool success + required property bool isStatusDeepLink + readonly property bool isImage: result.contentType ? result.contentType.startsWith("image/") : false + + readonly property string thumbnailUrl: result && result.thumbnailUrl ? result.thumbnailUrl : "" + readonly property string title: result && result.title ? result.title : "" + readonly property string hostname: result && result.site ? result.site : "" + readonly property bool animated: true + + StateGroup { + //Using StateGroup as a warkardound for https://bugreports.qt.io/browse/QTBUG-47796 + id: linkPreviewLoaderState + states: [ + State { + name: "askToEnableUnfurling" + when: !tempLoader.unfurl + PropertyChanges { target: tempLoader; sourceComponent: enableLinkComponent } + }, + State { + name: "loadImage" + when: tempLoader.unfurl && tempLoader.isImage + PropertyChanges { target: tempLoader; sourceComponent: unfurledImageComponent } + } +// State { +// name: "loadLinkPreview" +// when: unfurl && !isImage && !isStatusDeepLink +// PropertyChanges { target: tempLoader; sourceComponent: unfurledLinkComponent } +// }, +// State { +// name: "statusInvitation" +// when: unfurl && isStatusDeepLink +// PropertyChanges { target: tempLoader; sourceComponent: invitationBubble } +// } + ] + } + } + } + + 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 + + StatusFlatRoundButton { + anchors.top: parent.top + anchors.topMargin: Style.current.smallPadding + anchors.right: parent.right + anchors.rightMargin: Style.current.smallPadding + icon.width: 20 + icon.height: 20 + icon.name: "close-circle" + onClicked: linksModel.remove(index) + } + + 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 + } + + StatusBaseText { + id: enableText + text: isImage ? qsTr("Enable automatic image unfurling") : + qsTr("Enable link previews in chat?") + horizontalAlignment: Text.AlignHCenter + width: parent.width + wrapMode: Text.WordWrap + anchors.top: unfurlingImage.bottom + anchors.topMargin: Style.current.halfPadding + color: Theme.palette.directColor1 + } + + StatusBaseText { + id: infoText + text: qsTr("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: Theme.palette.baseColor1 + } + + Separator { + id: sep1 + anchors.top: infoText.bottom + anchors.topMargin: Style.current.smallPadding + } + + StatusFlatButton { + id: enableBtn + objectName: "LinksMessageView_enableBtn" + text: qsTr("Enable in Settings") + onClicked: { + Global.changeAppSectionBySectionType(Constants.appSection.profile, Constants.settingsSubsection.messaging); + } + width: parent.width + anchors.top: sep1.bottom + Component.onCompleted: { + background.radius = 0; + } + } + + Separator { + id: sep2 + anchors.top: enableBtn.bottom + anchors.topMargin: 0 + } + + Item { + width: parent.width + height: 44 + anchors.top: sep2.bottom + clip: true + + StatusFlatButton { + id: dontAskBtn + width: parent.width + height: (parent.height+Style.current.padding) + anchors.top: parent.top + anchors.topMargin: -Style.current.padding + contentItem: Item { + StatusBaseText { + anchors.centerIn: parent + anchors.verticalCenterOffset: Style.current.halfPadding + font: dontAskBtn.font + color: dontAskBtn.enabled ? dontAskBtn.textColor : dontAskBtn.disabledTextColor + text: qsTr("Don't ask me again") + } + } + onClicked: RootStore.setNeverAskAboutUnfurlingAgain(true) + Component.onCompleted: { + background.radius = Style.current.padding; + } + } + } + } + } + + + } diff --git a/ui/imports/shared/views/chat/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml index 977864d6420..f5a9aaf8836 100644 --- a/ui/imports/shared/views/chat/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -64,6 +64,19 @@ Loader { property string messageAttachments: "" property var transactionParams + // These 2 properties can be dropped when the new unfurling flow supports GIFs + property var links + readonly property var localUnfurlLinks: { + if (!links) + return [] + const separator = " " + const arr = links.split(separator) + const filtered = arr.filter(v => v.toLowerCase().endsWith('.gif')) + const out = filtered.join(separator) + console.log(`<<<${arr}->${out}`) + return out + } + property string responseToMessageWithId: "" property string quotedMessageText: "" property string quotedMessageFrom: "" @@ -518,6 +531,7 @@ Loader { resendError: root.resendError reactionsModel: root.reactionsModel linkPreviewModel: root.linkPreviewModel + localUnfurlLinks: root.localUnfurlLinks showHeader: root.shouldRepeatHeader || dateGroupLabel.visible || isAReply || root.prevMessageContentType === Constants.messageContentType.systemMessagePrivateGroupType || @@ -744,6 +758,7 @@ Loader { LinksMessageView { id: linksMessageView linkPreviewModel: root.linkPreviewModel + localUnfurlLinks: root.localUnfurlLinks messageStore: root.messageStore store: root.rootStore isCurrentUser: root.amISender