mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-26 04:58:49 +03:00
Reimplement room context menus
This commit is contained in:
parent
c290b0747f
commit
e2765212fb
6 changed files with 232 additions and 34 deletions
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import "./dialogs"
|
||||
import Qt.labs.platform 1.1 as Platform
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
@ -31,6 +32,93 @@ Page {
|
|||
target: TimelineManager
|
||||
}
|
||||
|
||||
Platform.Menu {
|
||||
id: roomContextMenu
|
||||
|
||||
property string roomid
|
||||
property var tags
|
||||
|
||||
function show(roomid_, tags_) {
|
||||
roomid = roomid_;
|
||||
tags = tags_;
|
||||
roomContextMenu.clear();
|
||||
roomContextMenu.addItem(leaveOpt.createObject(roomContextMenu));
|
||||
roomContextMenu.addItem(separatorOpt.createObject(roomContextMenu));
|
||||
for (let tag of Rooms.tags()) {
|
||||
roomContextMenu.addItem(tagDelegate.createObject(roomContextMenu, {
|
||||
"t": tag
|
||||
}));
|
||||
}
|
||||
roomContextMenu.addItem(newTagOpt.createObject(roomContextMenu));
|
||||
open();
|
||||
}
|
||||
|
||||
InputDialog {
|
||||
id: newTag
|
||||
|
||||
title: qsTr("New tag")
|
||||
prompt: qsTr("Enter the tag you want to use:")
|
||||
onAccepted: function(text) {
|
||||
Rooms.toggleTag(roomContextMenu.roomid, "u." + text, true);
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: leaveOpt
|
||||
|
||||
Platform.MenuItem {
|
||||
text: qsTr("Leave room")
|
||||
onTriggered: Rooms.leave(roomContextMenu.roomid)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: separatorOpt
|
||||
|
||||
Platform.MenuSeparator {
|
||||
text: qsTr("Tag room as:")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: tagDelegate
|
||||
|
||||
Platform.MenuItem {
|
||||
property string t
|
||||
|
||||
text: {
|
||||
switch (t) {
|
||||
case "m.favourite":
|
||||
return qsTr("Favourite");
|
||||
case "m.lowpriority":
|
||||
return qsTr("Low priority");
|
||||
case "m.server_notice":
|
||||
return qsTr("Server notice");
|
||||
default:
|
||||
return t.substring(2);
|
||||
}
|
||||
}
|
||||
checkable: true
|
||||
checked: roomContextMenu.tags.includes(t)
|
||||
onTriggered: Rooms.toggleTag(roomContextMenu.roomid, t, checked)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: newTagOpt
|
||||
|
||||
Platform.MenuItem {
|
||||
text: qsTr("Create new tag...")
|
||||
onTriggered: newTag.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
id: roomItem
|
||||
|
||||
|
@ -75,6 +163,12 @@ Page {
|
|||
}
|
||||
]
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.RightButton
|
||||
onSingleTapped: roomContextMenu.show(model.roomId, model.tags)
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: hovered
|
||||
}
|
||||
|
@ -94,6 +188,7 @@ Page {
|
|||
|
||||
id: avatar
|
||||
|
||||
enabled: false
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
height: Math.ceil(fontMetrics.lineSpacing * 2.3)
|
||||
width: Math.ceil(fontMetrics.lineSpacing * 2.3)
|
||||
|
@ -279,43 +374,14 @@ Page {
|
|||
Layout.preferredHeight: userInfoGrid.implicitHeight + 2 * Nheko.paddingMedium
|
||||
Layout.minimumHeight: 40
|
||||
|
||||
ApplicationWindow {
|
||||
InputDialog {
|
||||
id: statusDialog
|
||||
|
||||
modality: Qt.NonModal
|
||||
flags: Qt.Dialog
|
||||
title: qsTr("Status Message")
|
||||
width: 350
|
||||
height: fontMetrics.lineSpacing * 7
|
||||
|
||||
ColumnLayout {
|
||||
anchors.margins: Nheko.paddingLarge
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
color: Nheko.colors.text
|
||||
text: qsTr("Enter your status message:")
|
||||
prompt: qsTr("Enter your status message:")
|
||||
onAccepted: function(text) {
|
||||
Nheko.setStatusMessage(text);
|
||||
}
|
||||
|
||||
MatrixTextField {
|
||||
id: statusInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
footer: DialogButtonBox {
|
||||
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
|
||||
onAccepted: {
|
||||
Nheko.setStatusMessage(statusInput.text);
|
||||
statusDialog.close();
|
||||
}
|
||||
onRejected: {
|
||||
statusDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Platform.Menu {
|
||||
|
|
|
@ -9,7 +9,7 @@ MatrixText {
|
|||
property string formatted: model.data.formattedBody
|
||||
property string copyText: selectedText ? getText(selectionStart, selectionEnd) : model.data.body
|
||||
|
||||
text: "<style type=\"text/css\">a { color:" + Nheko.colors.link + ";}\ncode { background-color: " + Nheko.colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + Nheko.colors.alternateBase + "'>")
|
||||
text: "<style type=\"text/css\">a { color:" + Nheko.colors.link + ";}\ncode { background-color: " + Nheko.colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + Nheko.colors.alternateBase + "'>").replace("<del>", "<s>").replace("</del>", "</s>").replace("<strike>", "<s>").replace("</strike>", "</s>")
|
||||
width: parent ? parent.width : undefined
|
||||
height: isReply ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : undefined
|
||||
clip: isReply
|
||||
|
|
53
resources/qml/dialogs/InputDialog.qml
Normal file
53
resources/qml/dialogs/InputDialog.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import ".."
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.3
|
||||
import im.nheko 1.0
|
||||
|
||||
ApplicationWindow {
|
||||
id: inputDialog
|
||||
|
||||
property alias prompt: promptLabel.text
|
||||
property var onAccepted: undefined
|
||||
|
||||
modality: Qt.NonModal
|
||||
flags: Qt.Dialog
|
||||
width: 350
|
||||
height: fontMetrics.lineSpacing * 7
|
||||
|
||||
ColumnLayout {
|
||||
anchors.margins: Nheko.paddingLarge
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
id: promptLabel
|
||||
|
||||
color: Nheko.colors.text
|
||||
}
|
||||
|
||||
MatrixTextField {
|
||||
id: statusInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
footer: DialogButtonBox {
|
||||
standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
|
||||
onAccepted: {
|
||||
if (inputDialog.onAccepted)
|
||||
inputDialog.onAccepted(statusInput.text);
|
||||
|
||||
inputDialog.close();
|
||||
}
|
||||
onRejected: {
|
||||
inputDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -168,6 +168,7 @@
|
|||
<file>qml/device-verification/NewVerificationRequest.qml</file>
|
||||
<file>qml/device-verification/Failed.qml</file>
|
||||
<file>qml/device-verification/Success.qml</file>
|
||||
<file>qml/dialogs/InputDialog.qml</file>
|
||||
<file>qml/ui/Ripple.qml</file>
|
||||
<file>qml/voip/ActiveCallBar.qml</file>
|
||||
<file>qml/voip/CallDevices.qml</file>
|
||||
|
|
|
@ -49,6 +49,7 @@ RoomlistModel::roleNames() const
|
|||
{NotificationCount, "notificationCount"},
|
||||
{IsInvite, "isInvite"},
|
||||
{IsSpace, "isSpace"},
|
||||
{Tags, "tags"},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,13 @@ RoomlistModel::data(const QModelIndex &index, int role) const
|
|||
case Roles::IsInvite:
|
||||
case Roles::IsSpace:
|
||||
return false;
|
||||
case Roles::Tags: {
|
||||
auto info = cache::singleRoomInfo(roomid.toStdString());
|
||||
QStringList list;
|
||||
for (const auto &t : info.tags)
|
||||
list.push_back(QString::fromStdString(t));
|
||||
return list;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
@ -111,6 +119,8 @@ RoomlistModel::data(const QModelIndex &index, int role) const
|
|||
return true;
|
||||
case Roles::IsSpace:
|
||||
return false;
|
||||
case Roles::Tags:
|
||||
return QStringList();
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
@ -364,6 +374,21 @@ RoomlistModel::declineInvite(QString roomid)
|
|||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
RoomlistModel::leave(QString roomid)
|
||||
{
|
||||
if (models.contains(roomid)) {
|
||||
auto idx = roomidToIndex(roomid);
|
||||
|
||||
if (idx != -1) {
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
roomids.erase(roomids.begin() + idx);
|
||||
models.remove(roomid);
|
||||
endRemoveRows();
|
||||
ChatPage::instance()->leaveRoom(roomid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum NotificationImportance : short
|
||||
|
@ -440,3 +465,50 @@ FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *pare
|
|||
|
||||
sort(0);
|
||||
}
|
||||
|
||||
QStringList
|
||||
FilteredRoomlistModel::tags()
|
||||
{
|
||||
std::set<std::string> ts;
|
||||
for (const auto &e : cache::roomInfo()) {
|
||||
for (const auto &t : e.tags) {
|
||||
if (t.find("u.") == 0) {
|
||||
ts.insert(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList ret{{
|
||||
"m.favourite",
|
||||
"m.lowpriority",
|
||||
}};
|
||||
|
||||
for (const auto &t : ts)
|
||||
ret.push_back(QString::fromStdString(t));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
FilteredRoomlistModel::toggleTag(QString roomid, QString tag, bool on)
|
||||
{
|
||||
if (on) {
|
||||
http::client()->put_tag(
|
||||
roomid.toStdString(), tag.toStdString(), {}, [tag](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::ui()->error("Failed to add tag: {}, {}",
|
||||
tag.toStdString(),
|
||||
err->matrix_error.error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
http::client()->delete_tag(
|
||||
roomid.toStdString(), tag.toStdString(), [tag](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
nhlog::ui()->error("Failed to delete tag: {}, {}",
|
||||
tag.toStdString(),
|
||||
err->matrix_error.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QSharedPointer>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QString>
|
||||
#include <set>
|
||||
|
||||
#include <mtx/responses/sync.hpp>
|
||||
|
||||
|
@ -33,6 +34,7 @@ public:
|
|||
NotificationCount,
|
||||
IsInvite,
|
||||
IsSpace,
|
||||
Tags,
|
||||
};
|
||||
|
||||
RoomlistModel(TimelineViewManager *parent = nullptr);
|
||||
|
@ -66,6 +68,7 @@ public slots:
|
|||
}
|
||||
void acceptInvite(QString roomid);
|
||||
void declineInvite(QString roomid);
|
||||
void leave(QString roomid);
|
||||
|
||||
private slots:
|
||||
void updateReadStatus(const std::map<QString, bool> roomReadStatus_);
|
||||
|
@ -100,6 +103,9 @@ public slots:
|
|||
}
|
||||
void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
|
||||
void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
|
||||
void leave(QString roomid) { roomlistmodel->leave(roomid); }
|
||||
QStringList tags();
|
||||
void toggleTag(QString roomid, QString tag, bool on);
|
||||
|
||||
private:
|
||||
short int calculateImportance(const QModelIndex &idx) const;
|
||||
|
|
Loading…
Reference in a new issue