Skip to content
Snippets Groups Projects
ImageMessage.qml 5.47 KiB
Newer Older
// SPDX-FileCopyrightText: Nheko Contributors
Nicolas Werner's avatar
Nicolas Werner committed
// SPDX-License-Identifier: GPL-3.0-or-later

import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import im.nheko
Malte E's avatar
Malte E committed
AbstractButton {
    required property int type
    required property int originalWidth
    required property int originalHeight
    required property double proportionalHeight
    required property string url
    required property string blurhash
    required property string body
    required property string filename
    required property bool isReply
Nicolas Werner's avatar
Nicolas Werner committed
    required property string eventId
    required property int containerHeight
    property double divisor: isReply ? 5 : 3
    //Layout.maximumWidth: originalWidth
    Layout.maximumHeight: Math.min(originalHeight, containerHeight / divisor)
    implicitWidth: height/proportionalHeight
    implicitHeight: Math.min(Layout.maximumHeight, width*proportionalHeight)
Malte E's avatar
Malte E committed
    hoverEnabled: true
    state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
            name: "BlurhashVisible"

            PropertyChanges {
                target: blurhash_
                opacity: (img.status != Image.Ready) || (timeline.privacyScreen.active && blurhash) ? 1 : 0
                visible: (img.status != Image.Ready) || (timeline.privacyScreen.active && blurhash)
            }

            PropertyChanges {
                target: img
                opacity: 0
            }

            PropertyChanges {
                target: mxcimage
                opacity: 0
            }
        },
        State {
            name: "ImageVisible"

            PropertyChanges {
                target: blurhash_
                opacity: 0
                visible: false
            }

            PropertyChanges {
                target: img
                opacity: 1
            }

            PropertyChanges {
                target: mxcimage
                opacity: 1
            }
        }
    ]
    transitions: [
        Transition {
            from: "ImageVisible"
            to: "BlurhashVisible"
            reversible: true

            SequentialAnimation {
                PropertyAction {
                    target: blurhash_
                    property: "visible"
                }

                ParallelAnimation {
                    NumberAnimation {
                        target: blurhash_
                        property: "opacity"
                        duration: 300
                        easing.type: Easing.Linear
                    }

                    NumberAnimation {
                        target: img
                        property: "opacity"
                        duration: 300
                        easing.type: Easing.Linear
                    }

                    NumberAnimation {
                        target: mxcimage
                        property: "opacity"
                        duration: 300
                        easing.type: Easing.Linear
                    }
                }
            }
        }
    ]

    property int metadataWidth
    property bool fitsMetadata: parent != null ? (parent.width - width) > metadataWidth+4 : false
    Image {
        id: img

Nicolas Werner's avatar
Nicolas Werner committed
        visible: !mxcimage.loaded
        anchors.fill: parent
        source: url != "" ? (url.replace("mxc://", "image://MxcImage/") + "?scale") : ""
        asynchronous: true
        fillMode: Image.PreserveAspectFit
        horizontalAlignment: Image.AlignLeft
        smooth: true
        mipmap: true
        sourceSize.width: Math.min(Screen.desktopAvailableWidth, originalWidth < 1 ? Screen.desktopAvailableWidth : originalWidth) * Screen.devicePixelRatio
        sourceSize.height: Math.min(Screen.desktopAvailableHeight, (originalWidth < 1 ? Screen.desktopAvailableHeight : originalWidth*proportionalHeight)) * Screen.devicePixelRatio
Nicolas Werner's avatar
Nicolas Werner committed
    MxcAnimatedImage {
        id: mxcimage
Nicolas Werner's avatar
Nicolas Werner committed
        visible: loaded
        roomm: room
Malte E's avatar
Malte E committed
        play: !Settings.animateImagesOnHover || parent.hovered
Nicolas Werner's avatar
Nicolas Werner committed
        eventId: parent.eventId
        width: parent.implicitWidth
        height: parent.implicitHeight
        source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + palette.buttonText)
        asynchronous: true
        fillMode: Image.PreserveAspectFit
        sourceSize.width: parent.implicitWidth * Screen.devicePixelRatio
        sourceSize.height: parent.implicitHeight * Screen.devicePixelRatio
        width: parent.implicitWidth
        height: parent.implicitHeight
    }

    onClicked: Settings.openImageExternal ? room.openMedia(eventId) : TimelineManager.openImageOverlay(room, url, eventId, originalWidth, proportionalHeight);
Nicolas Werner's avatar
Nicolas Werner committed
    Item {
        id: overlay
        width: parent.implicitWidth
        height: parent.implicitHeight
Malte E's avatar
Malte E committed
        visible: parent.hovered
Nicolas Werner's avatar
Nicolas Werner committed
        Rectangle {
            id: container

            width: parent.width
            implicitHeight: imgcaption.implicitHeight
            anchors.bottom: overlay.bottom
            color: palette.window
Nicolas Werner's avatar
Nicolas Werner committed
            opacity: 0.75
        }

        Text {
            id: imgcaption
Nicolas Werner's avatar
Nicolas Werner committed
            anchors.fill: container
            elide: Text.ElideMiddle
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
            // See this MSC: https://github.com/matrix-org/matrix-doc/pull/2530
            text: filename ? filename : body
            color: palette.text