diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index d80d274d..c3957fec 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -49,7 +49,7 @@ ScrollView { property var attachedPos: chat.contentY, attached ? chat.mapFromItem(attached, attached ? attached.width - width : 0, -height) : null readonly property int padding: 4 - visible: Settings.buttonsInTimeline && !!attached && (attached.hovered || messageActionHover.hovered) + visible: !Settings.mobileMode && (Settings.buttonsInTimeline && !!attached && (attached.hovered || messageActionHover.hovered)) x: attached ? attachedPos.x : 0 y: attached ? attachedPos.y : 0 z: 10 @@ -134,6 +134,13 @@ ScrollView { } + MobileMessageContextPopup { + id: mobileContextPopup + + visible: false + anchors.fill: parent + } + ScrollHelper { flickable: parent anchors.fill: parent @@ -477,7 +484,6 @@ ScrollView { } } } - } Connections { @@ -544,6 +550,9 @@ ScrollView { open(); } + // make sure that we close the popup when this menu is closed + onAboutToHide: if (mobileContextPopup.visible) mobileContextPopup.hide() + Platform.MenuItem { visible: messageContextMenu.text enabled: visible diff --git a/resources/qml/MobileMessageContextPopup.qml b/resources/qml/MobileMessageContextPopup.qml new file mode 100644 index 00000000..f65be5d5 --- /dev/null +++ b/resources/qml/MobileMessageContextPopup.qml @@ -0,0 +1,161 @@ +import QtQuick 2.12 +import QtGraphicalEffects 1.0 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import im.nheko 1.0 +import "./emoji" +import "./delegates" + +Item { + id: popupRoot + + // TODO: make this use permissions etc. like the desktop menu + function show(attachment, messageModel) { + attached = attachment + model = messageModel + visible = true + popup.state = "shown" + } + + function hide() { + popup.state = "hidden" + visible = false + attached = undefined + model = undefined + } + + property Item attached: null + property alias model: row.model + + Rectangle { + id: popup + + radius: 20 + z: 20 + anchors.bottom: parent.bottom + height: 75 + width: parent.width + color: colors.window + + RowLayout { + id: row + + property var model + + spacing: 5 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + Layout.margins: 10 + anchors.fill: parent + + // without this, the buttons tend to hug the sides + anchors.leftMargin: 10 + anchors.rightMargin: anchors.leftMargin + + ImageButton { + id: editButton + + visible: !!row.model && row.model.isEditable + buttonTextColor: colors.buttonText + Layout.minimumWidth: 20 + Layout.preferredWidth: 35 + Layout.preferredHeight: Layout.preferredWidth + Layout.minimumHeight: Layout.minimumWidth + height: width + Layout.alignment: Qt.AlignHCenter + hoverEnabled: true + image: ":/icons/icons/ui/edit.png" + ToolTip.visible: hovered + ToolTip.text: row.model && row.model.isEditable ? qsTr("Edit") : qsTr("Edited") + onClicked: { + if (row.model.isEditable) + TimelineManager.timeline.editAction(row.model.id); + popupRoot.hide() + } + } + + EmojiButton { + id: reactButton + + Layout.minimumWidth: 20 + Layout.preferredWidth: 35 + Layout.preferredHeight: Layout.preferredWidth + Layout.minimumHeight: Layout.minimumWidth + height: width + Layout.alignment: Qt.AlignHCenter + hoverEnabled: true + ToolTip.visible: hovered + ToolTip.text: qsTr("React") + emojiPicker: emojiPopup + event_id: row.model ? row.model.id : "" + } + + ImageButton { + id: replyButton + + Layout.minimumWidth: 20 + Layout.preferredWidth: 35 + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: Layout.preferredWidth + Layout.minimumHeight: Layout.minimumWidth + height: width + hoverEnabled: true + image: ":/icons/icons/ui/mail-reply.png" + ToolTip.visible: hovered + ToolTip.text: qsTr("Reply") + onClicked: { + TimelineManager.timeline.replyAction(row.model.id) + popupRoot.hide() + } + } + + ImageButton { + id: optionsButton + + Layout.minimumWidth: 20 + Layout.preferredWidth: 35 + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: Layout.preferredWidth + Layout.minimumHeight: Layout.minimumWidth + height: width + hoverEnabled: true + image: ":/icons/icons/ui/vertical-ellipsis.png" + ToolTip.visible: hovered + ToolTip.text: qsTr("Options") + onClicked: messageContextMenu.show(row.model.id, row.model.type, row.model.isEncrypted, row.model.isEditable, optionsButton) + } + } + + Rectangle { + id: popupBottomBar + + z: popup.z - 1 + anchors.bottom: popup.bottom + height: popup.radius + width: popup.width + color: popup.color + } + } + + Rectangle { + id: overlay + anchors.fill: parent + z: popupBottomBar.z - 1 + + color: "gray" + opacity: 0.5 + + TapHandler { + onTapped: popupRoot.hide() + } + } + + // TODO: this needs some love + FastBlur { + z: overlay.z - 1 + anchors.fill: parent + source: timelineRoot + radius: 50 + } +} diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml index c612479a..70ebf91d 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml @@ -65,7 +65,13 @@ Item { } TapHandler { - onLongPressed: messageContextMenu.show(eventId, type, isSender, isEncrypted, isEditable, contentItem.child.hoveredLink, contentItem.child.copyText) + onLongPressed: { + if (Settings.mobileMode) + mobileContextPopup.show(r, model); + else + messageContextMenu.show(eventId, type, isSender, isEncrypted, isEditable, contentItem.child.hoveredLink, contentItem.child.copyText) + + } onDoubleTapped: chat.model.reply = eventId gesturePolicy: TapHandler.ReleaseWithinBounds } diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 91bbca5b..ad3f9518 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -273,3 +273,4 @@ Item { } } +} diff --git a/resources/res.qrc b/resources/res.qrc index 3514ebca..b9e324c0 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -183,6 +183,7 @@ qml/InviteDialog.qml qml/ReadReceipts.qml qml/RawMessageDialog.qml + qml/MobileMessageContextPopup.qml media/ring.ogg