diff --git a/src/models/messageeventmodel.cpp b/src/models/messageeventmodel.cpp index 2efbc58e8..d9ddbb01f 100644 --- a/src/models/messageeventmodel.cpp +++ b/src/models/messageeventmodel.cpp @@ -525,6 +525,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const return DelegateType::Sticker; } if (evt.isStateEvent()) { + if (evt.matrixType() == "org.matrix.msc3672.beacon_info"_ls) { + return DelegateType::LiveLocation; + } return DelegateType::State; } if (is(evt)) { @@ -635,6 +638,11 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const return EventStatus::Hidden; } + // hide ending live location beacons + if (evt.isStateEvent() && evt.matrixType() == "org.matrix.msc3672.beacon_info"_ls && !evt.contentJson()["live"_ls].toBool()) { + return EventStatus::Hidden; + } + return EventStatus::Normal; } diff --git a/src/models/messageeventmodel.h b/src/models/messageeventmodel.h index 801d898b2..66d86842d 100644 --- a/src/models/messageeventmodel.h +++ b/src/models/messageeventmodel.h @@ -53,6 +53,7 @@ public: ReadMarker, /**< The local user read marker. */ Poll, /**< The initial event for a poll. */ Location, /**< A location event. */ + LiveLocation, /**< The initial event of a shared live location (i.e., the place where this is supposed to be shown in the timeline). */ Other, /**< Anything that cannot be classified as another type. */ }; Q_ENUM(DelegateType); diff --git a/src/qml/Component/Timeline/EventDelegate.qml b/src/qml/Component/Timeline/EventDelegate.qml index 0a15e22d9..17872bb40 100644 --- a/src/qml/Component/Timeline/EventDelegate.qml +++ b/src/qml/Component/Timeline/EventDelegate.qml @@ -11,7 +11,9 @@ import org.kde.kirigami 2.15 as Kirigami import org.kde.neochat 1.0 DelegateChooser { + id: root role: "delegateType" + property var room DelegateChoice { roleValue: MessageEventModel.State @@ -77,6 +79,12 @@ DelegateChooser { roleValue: MessageEventModel.Location delegate: LocationDelegate {} } + DelegateChoice { + roleValue: MessageEventModel.LiveLocation + delegate: LiveLocationDelegate { + room: root.room + } + } DelegateChoice { roleValue: MessageEventModel.Other diff --git a/src/qml/Component/Timeline/LiveLocationDelegate.qml b/src/qml/Component/Timeline/LiveLocationDelegate.qml new file mode 100644 index 000000000..8d4a1715c --- /dev/null +++ b/src/qml/Component/Timeline/LiveLocationDelegate.qml @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: 2021 Tobias Fella +// SPDX-FileCopyrightText: 2023 Volker Krause +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtLocation 5.15 +import QtPositioning 5.15 + +import org.kde.kirigami 2.15 as Kirigami + +import org.kde.neochat 1.0 + +/** + * @brief A timeline delegate for a location message. + * + * @inherit TimelineContainer + */ +TimelineContainer { + id: root + + property alias room: liveLocationModel.room + + ColumnLayout { + Layout.maximumWidth: root.contentMaxWidth + Layout.preferredWidth: root.contentMaxWidth + LiveLocationsModel { + id: liveLocationModel + eventId: root.eventId + } + Map { + id: map + Layout.fillWidth: true + Layout.preferredHeight: root.contentMaxWidth / 16 * 9 + + // center: QtPositioning.coordinate(root.latitude, root.longitude) + // zoomLevel: 15 + + plugin: OsmLocationPlugin.plugin + onCopyrightLinkActivated: Qt.openUrlExternally(link) + + MapItemView { + model: liveLocationModel + delegate: MapQuickItem { + anchorPoint.x: sourceItem.width / 2 + anchorPoint.y: sourceItem.height + coordinate: QtPositioning.coordinate(model.latitude, model.longitude) + autoFadeIn: false + sourceItem: Kirigami.Icon { + width: height + height: Kirigami.Units.iconSizes.huge + source: "gps" + isMask: true + color: model.isLive ? Kirigami.Theme.highlightColor : Kirigami.Theme.disabledTextColor + + Kirigami.Icon { + anchors.centerIn: parent + anchors.verticalCenterOffset: -parent.height / 8 + visible: model.asset === "m.pin" + width: height + height: parent.height / 3 + 1 + source: "pin" + isMask: true + color: parent.color + } + Kirigami.Avatar { + anchors.centerIn: parent + anchors.verticalCenterOffset: -parent.height / 8 + visible: model.asset === "m.self" + width: height + height: parent.height / 3 + 1 + name: model.author.displayName + source: model.author.avatarSource + color: model.author.color + } + } + } + } + + TapHandler { + acceptedButtons: Qt.LeftButton + onLongPressed: openMessageContext("") + } + TapHandler { + acceptedButtons: Qt.RightButton + onTapped: openMessageContext("") + } + } + } +} diff --git a/src/qml/Component/TimelineView.qml b/src/qml/Component/TimelineView.qml index 9d6fbcd40..5b1b665ff 100644 --- a/src/qml/Component/TimelineView.qml +++ b/src/qml/Component/TimelineView.qml @@ -173,6 +173,7 @@ QQC2.ScrollView { } delegate: EventDelegate { + room: root.currentRoom } QQC2.RoundButton { diff --git a/src/res.qrc b/src/res.qrc index 578b30961..8da329c03 100644 --- a/src/res.qrc +++ b/src/res.qrc @@ -127,5 +127,6 @@ qml/Component/AvatarTabButton.qml qml/Page/RoomList/SpaceDrawer.qml qml/Component/Timeline/OsmLocationPlugin.qml + qml/Component/Timeline/LiveLocationDelegate.qml