Allow accepting knocks in the timeline

As well as selecting more join rules.
This commit is contained in:
Nicolas Werner 2021-08-17 23:31:25 +02:00
parent 56b24f8d93
commit 5b460861b1
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
8 changed files with 135 additions and 13 deletions

View File

@ -49,7 +49,7 @@ Rectangle {
smooth: true smooth: true
sourceSize.width: avatar.width sourceSize.width: avatar.width
sourceSize.height: avatar.height sourceSize.height: avatar.height
source: avatar.url ? (avatar.url + "?radius=" + (Settings.avatarCircles ? 100.0 : 25.0) + ((avatar.crop) ? "" : "&scale")) : "" source: avatar.url ? (avatar.url + "?radius=" + (Settings.avatarCircles ? 100 : 25) + ((avatar.crop) ? "" : "&scale")) : ""
MouseArea { MouseArea {
id: mouseArea id: mouseArea

View File

@ -16,12 +16,13 @@ Page {
property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3) property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3)
property bool collapsed: false property bool collapsed: false
Component { Component {
id: roomDirectoryComponent id: roomDirectoryComponent
RoomDirectory { RoomDirectory {
} }
}
}
ListView { ListView {
id: roomlist id: roomlist
@ -570,10 +571,10 @@ Component {
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.text: qsTr("Room directory") ToolTip.text: qsTr("Room directory")
Layout.margins: Nheko.paddingMedium Layout.margins: Nheko.paddingMedium
onClicked: { onClicked: {
var win = roomDirectoryComponent.createObject(timelineRoot); var win = roomDirectoryComponent.createObject(timelineRoot);
win.show(); win.show();
} }
} }
ImageButton { ImageButton {

View File

@ -186,7 +186,16 @@ ApplicationWindow {
ComboBox { ComboBox {
enabled: roomSettings.canChangeJoinRules enabled: roomSettings.canChangeJoinRules
model: [qsTr("Anyone and guests"), qsTr("Anyone"), qsTr("Invited users")] model: {
let opts = [qsTr("Anyone and guests"), qsTr("Anyone"), qsTr("Invited users")];
if (roomSettings.supportsKnocking)
opts.push(qsTr("By knocking"));
if (roomSettings.supportsRestricted)
opts.push(qsTr("Restricted by membership in other rooms"));
return opts;
}
currentIndex: roomSettings.accessJoinRules currentIndex: roomSettings.accessJoinRules
onActivated: { onActivated: {
roomSettings.changeAccessRules(index); roomSettings.changeAccessRules(index);

View File

@ -3,6 +3,8 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.6 import QtQuick 2.6
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import im.nheko 1.0 import im.nheko 1.0
Item { Item {
@ -357,11 +359,23 @@ Item {
DelegateChoice { DelegateChoice {
roleValue: MtxEvent.Member roleValue: MtxEvent.Member
NoticeMessage { ColumnLayout {
body: formatted width: parent ? parent.width : undefined
isOnlyEmoji: false
isReply: d.isReply NoticeMessage {
formatted: d.relatedEventCacheBuster, room.formatMemberEvent(d.eventId) body: formatted
isOnlyEmoji: false
isReply: d.isReply
formatted: d.relatedEventCacheBuster, room.formatMemberEvent(d.eventId)
}
Button {
visible: d.relatedEventCacheBuster, room.showAcceptKnockButton(d.eventId)
palette: Nheko.colors
text: qsTr("Allow them in")
onClicked: room.acceptKnock(eventId)
}
} }
} }

View File

@ -1689,6 +1689,19 @@ TimelineModel::formatJoinRuleEvent(QString id)
return tr("%1 opened the room to the public.").arg(name); return tr("%1 opened the room to the public.").arg(name);
case mtx::events::state::JoinRule::Invite: case mtx::events::state::JoinRule::Invite:
return tr("%1 made this room require and invitation to join.").arg(name); return tr("%1 made this room require and invitation to join.").arg(name);
case mtx::events::state::JoinRule::Knock:
return tr("%1 allowed to join this room by knocking.").arg(name);
case mtx::events::state::JoinRule::Restricted: {
QStringList rooms;
for (const auto &r : event->content.allow) {
if (r.type == mtx::events::state::JoinAllowanceType::RoomMembership)
rooms.push_back(QString::fromStdString(r.room_id));
}
return tr("%1 allowed members of the following rooms to automatically join this "
"room: %2")
.arg(name)
.arg(rooms.join(", "));
}
default: default:
// Currently, knock and private are reserved keywords and not implemented in Matrix. // Currently, knock and private are reserved keywords and not implemented in Matrix.
return ""; return "";
@ -1771,6 +1784,51 @@ TimelineModel::formatPowerLevelEvent(QString id)
return tr("%1 has changed the room's permissions.").arg(name); return tr("%1 has changed the room's permissions.").arg(name);
} }
void
TimelineModel::acceptKnock(QString id)
{
mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
if (!e)
return;
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
if (!event)
return;
if (!permissions_.canInvite())
return;
if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
return;
using namespace mtx::events::state;
if (event->content.membership != Membership::Knock)
return;
ChatPage::instance()->inviteUser(QString::fromStdString(event->state_key), "");
}
bool
TimelineModel::showAcceptKnockButton(QString id)
{
mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
if (!e)
return false;
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
if (!event)
return false;
if (!permissions_.canInvite())
return false;
if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
return false;
using namespace mtx::events::state;
return event->content.membership == Membership::Knock;
}
QString QString
TimelineModel::formatMemberEvent(QString id) TimelineModel::formatMemberEvent(QString id)
{ {
@ -1826,7 +1884,13 @@ TimelineModel::formatMemberEvent(QString id)
// the case of nothing changed but join follows join shouldn't happen, so // the case of nothing changed but join follows join shouldn't happen, so
// just show it as join // just show it as join
} else { } else {
rendered = tr("%1 joined.").arg(name); if (event->content.join_authorised_via_users_server.empty())
rendered = tr("%1 joined.").arg(name);
else
rendered = tr("%1 joined via authorisation from %2's server.")
.arg(name)
.arg(QString::fromStdString(
event->content.join_authorised_via_users_server));
} }
break; break;
case Membership::Leave: case Membership::Leave:

View File

@ -238,6 +238,8 @@ public:
Q_INVOKABLE QString avatarUrl(QString id) const; Q_INVOKABLE QString avatarUrl(QString id) const;
Q_INVOKABLE QString formatDateSeparator(QDate date) const; Q_INVOKABLE QString formatDateSeparator(QDate date) const;
Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg); Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg);
Q_INVOKABLE bool showAcceptKnockButton(QString id);
Q_INVOKABLE void acceptKnock(QString id);
Q_INVOKABLE QString formatMemberEvent(QString id); Q_INVOKABLE QString formatMemberEvent(QString id);
Q_INVOKABLE QString formatJoinRuleEvent(QString id); Q_INVOKABLE QString formatJoinRuleEvent(QString id);
Q_INVOKABLE QString formatHistoryVisibilityEvent(QString id); Q_INVOKABLE QString formatHistoryVisibilityEvent(QString id);

View File

@ -218,8 +218,12 @@ RoomSettings::RoomSettings(QString roomid, QObject *parent)
} else { } else {
accessRules_ = 1; accessRules_ = 1;
} }
} else { } else if (info_.join_rule == state::JoinRule::Invite) {
accessRules_ = 2; accessRules_ = 2;
} else if (info_.join_rule == state::JoinRule::Knock) {
accessRules_ = 3;
} else if (info_.join_rule == state::JoinRule::Restricted) {
accessRules_ = 4;
} }
emit accessJoinRulesChanged(); emit accessJoinRulesChanged();
} }
@ -368,6 +372,21 @@ RoomSettings::isEncryptionEnabled() const
return usesEncryption_; return usesEncryption_;
} }
bool
RoomSettings::supportsKnocking() const
{
return info_.version != "" && info_.version != "1" && info_.version != "2" &&
info_.version != "3" && info_.version != "4" && info_.version != "5" &&
info_.version != "6";
}
bool
RoomSettings::supportsRestricted() const
{
return info_.version != "" && info_.version != "1" && info_.version != "2" &&
info_.version != "3" && info_.version != "4" && info_.version != "5" &&
info_.version != "6" && info_.version != "7";
}
void void
RoomSettings::openEditModal() RoomSettings::openEditModal()
{ {
@ -464,6 +483,15 @@ RoomSettings::changeAccessRules(int index)
case 1: case 1:
event.join_rule = state::JoinRule::Public; event.join_rule = state::JoinRule::Public;
break; break;
case 2:
event.join_rule = state::JoinRule::Invite;
break;
case 3:
event.join_rule = state::JoinRule::Knock;
break;
case 4:
event.join_rule = state::JoinRule::Restricted;
break;
default: default:
event.join_rule = state::JoinRule::Invite; event.join_rule = state::JoinRule::Invite;
} }

View File

@ -78,6 +78,8 @@ class RoomSettings : public QObject
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT) Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT) Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged) Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
public: public:
RoomSettings(QString roomid, QObject *parent = nullptr); RoomSettings(QString roomid, QObject *parent = nullptr);
@ -98,6 +100,8 @@ public:
//! Whether the user has enough power level to send m.room.avatar event. //! Whether the user has enough power level to send m.room.avatar event.
bool canChangeAvatar() const; bool canChangeAvatar() const;
bool isEncryptionEnabled() const; bool isEncryptionEnabled() const;
bool supportsKnocking() const;
bool supportsRestricted() const;
Q_INVOKABLE void enableEncryption(); Q_INVOKABLE void enableEncryption();
Q_INVOKABLE void updateAvatar(); Q_INVOKABLE void updateAvatar();