Skip to content
Snippets Groups Projects
Commit 7401bd13 authored by Jedi18's avatar Jedi18
Browse files

added notifications and encryption for the new roomsettings

parent b70f3719
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@ import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.2
import QtQuick.Window 2.3
import QtQuick.Dialogs 1.2
import im.nheko 1.0
ApplicationWindow {
......@@ -17,7 +18,8 @@ ApplicationWindow {
palette: colors
color: colors.window
title: roomSettings.roomName
modality: Qt.Modal
modality: Qt.WindowModal
flags: Qt.WindowStaysOnTopHint
Shortcut {
sequence: StandardKey.Cancel
......@@ -75,6 +77,10 @@ ApplicationWindow {
ComboBox {
model: [ "Muted", "Mentions only", "All messages" ]
currentIndex: roomSettings.notifications
onActivated: {
roomSettings.changeNotifications(index)
}
}
}
......@@ -85,7 +91,12 @@ ApplicationWindow {
ComboBox {
Layout.fillWidth: true
enabled: roomSettings.canChangeJoinRules
model: [ "Anyone and guests", "Anyone", "Invited users" ]
currentIndex: roomSettings.accessJoinRules
onActivated: {
roomSettings.changeAccessRules(index)
}
}
}
......@@ -99,10 +110,46 @@ ApplicationWindow {
}
Switch {
id: encryptionSwitch
checked: roomSettings.isEncryptionEnabled
onToggled: {
if(roomSettings.isEncryptionEnabled) {
checked=true;
return;
}
confirmEncryptionDialog.open();
}
}
MessageDialog {
id: confirmEncryptionDialog
title: qsTr("End-to-End Encryption")
text: qsTr("Encryption is currently experimental and things might break unexpectedly. <br>
Please take note that it can't be disabled afterwards.")
modality: Qt.WindowModal
icon: StandardIcon.Question
onAccepted: {
if(roomSettings.isEncryptionEnabled) {
return;
}
roomSettings.enableEncryption();
}
onRejected: {
encryptionSwitch.checked = false
}
standardButtons: Dialog.Ok | Dialog.Cancel
}
}
RowLayout {
visible: roomSettings.isEncryptionEnabled
MatrixText {
text: "Respond to key requests"
}
......@@ -112,6 +159,15 @@ ApplicationWindow {
}
Switch {
ToolTip.text: qsTr("Whether or not the client should respond automatically with the session keys
upon request. Use with caution, this is a temporary measure to test the
E2E implementation until device verification is completed.")
checked: roomSettings.respondsToKeyRequests
onToggled: {
roomSettings.changeKeyRequestsPreference(checked)
}
}
}
......
......@@ -178,7 +178,7 @@ Page {
target: TimelineManager
onOpenRoomSettingsDialog: {
var roomSettings = roomSettingsComponent.createObject(timelineRoot, {
"roomSettings": roomSettings
"roomSettings": settings
});
roomSettings.show();
}
......
......@@ -126,6 +126,12 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
0,
"UserProfileModel",
"UserProfile needs to be instantiated on the C++ side");
qmlRegisterUncreatableType<RoomSettings>(
"im.nheko",
1,
0,
"RoomSettingsModel",
"Room Settings needs to be instantiated on the C++ side");
static auto self = this;
qmlRegisterSingletonType<MainWindow>(
......@@ -394,8 +400,8 @@ TimelineViewManager::openRoomSettings()
{
MainWindow::instance()->openRoomSettings(timeline_->roomId());
RoomSettings *roomSettings = new RoomSettings(timeline_->roomId(), this);
emit openRoomSettingsDialog(roomSettings);
RoomSettings *settings = new RoomSettings(timeline_->roomId(), this);
emit openRoomSettingsDialog(settings);
}
void
......
......@@ -89,7 +89,7 @@ signals:
void showRoomList();
void narrowViewChanged();
void focusChanged();
void openRoomSettingsDialog(RoomSettings *roomSettings);
void openRoomSettingsDialog(RoomSettings *settings);
public slots:
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
......
......@@ -5,12 +5,65 @@
#include "Cache.h"
#include "Logging.h"
#include "MatrixClient.h"
#include "Utils.h"
using namespace mtx::events;
RoomSettings::RoomSettings(QString roomid, QObject *parent)
: roomid_{std::move(roomid)}
, QObject(parent)
{
retrieveRoomInfo();
// get room setting notifications
http::client()->get_pushrules(
"global",
"override",
roomid_.toStdString(),
[this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) {
if (err) {
if (err->status_code == boost::beast::http::status::not_found)
http::client()->get_pushrules(
"global",
"room",
roomid_.toStdString(),
[this](const mtx::pushrules::PushRule &rule,
mtx::http::RequestErr &err) {
if (err) {
notifications_ = 2; // all messages
emit notificationsChanged();
return;
}
if (rule.enabled) {
notifications_ = 1; // mentions only
emit notificationsChanged();
}
});
return;
}
if (rule.enabled) {
notifications_ = 0; // muted
emit notificationsChanged();
} else {
notifications_ = 2; // all messages
emit notificationsChanged();
}
});
// access rules
if (info_.join_rule == state::JoinRule::Public) {
if (info_.guest_access) {
accessRules_ = 0;
} else {
accessRules_ = 1;
}
} else {
accessRules_ = 2;
}
emit accessJoinRulesChanged();
}
QString
......@@ -25,9 +78,211 @@ RoomSettings::retrieveRoomInfo()
try {
usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString());
info_ = cache::singleRoomInfo(roomid_.toStdString());
//setAvatar();
// setAvatar();
} catch (const lmdb::error &) {
nhlog::db()->warn("failed to retrieve room info from cache: {}",
roomid_.toStdString());
}
}
int
RoomSettings::notifications()
{
return notifications_;
}
int
RoomSettings::accessJoinRules()
{
return accessRules_;
}
bool
RoomSettings::respondsToKeyRequests()
{
return usesEncryption_ && utils::respondsToKeyRequests(roomid_);
}
void
RoomSettings::changeKeyRequestsPreference(bool isOn)
{
utils::setKeyRequestsPreference(roomid_, isOn);
emit keyRequestsChanged();
}
void
RoomSettings::enableEncryption()
{
if (usesEncryption_)
return;
const auto room_id = roomid_.toStdString();
http::client()->enable_encryption(
room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
if (err) {
int status_code = static_cast<int>(err->status_code);
nhlog::net()->warn("failed to enable encryption in room ({}): {} {}",
room_id,
err->matrix_error.error,
status_code);
//emit enableEncryptionError(
// tr("Failed to enable encryption: %1")
// .arg(QString::fromStdString(err->matrix_error.error)));
usesEncryption_ = false;
emit encryptionChanged();
return;
}
nhlog::net()->info("enabled encryption on room ({})", room_id);
});
usesEncryption_ = true;
emit encryptionChanged();
}
bool
RoomSettings::canChangeJoinRules() const
{
try {
return cache::hasEnoughPowerLevel({EventType::RoomJoinRules},
roomid_.toStdString(),
utils::localUser().toStdString());
} catch (const lmdb::error &e) {
nhlog::db()->warn("lmdb error: {}", e.what());
}
return false;
}
bool
RoomSettings::isEncryptionEnabled() const
{
return usesEncryption_;
}
void
RoomSettings::changeNotifications(int currentIndex)
{
notifications_ = currentIndex;
std::string room_id = roomid_.toStdString();
if (notifications_ == 0) {
// mute room
// delete old rule first, then add new rule
mtx::pushrules::PushRule rule;
rule.actions = {mtx::pushrules::actions::dont_notify{}};
mtx::pushrules::PushCondition condition;
condition.kind = "event_match";
condition.key = "room_id";
condition.pattern = room_id;
rule.conditions = {condition};
http::client()->put_pushrules(
"global", "override", room_id, rule, [room_id](mtx::http::RequestErr &err) {
if (err)
nhlog::net()->error("failed to set pushrule for room {}: {} {}",
room_id,
static_cast<int>(err->status_code),
err->matrix_error.error);
http::client()->delete_pushrules(
"global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
});
} else if (notifications_ == 1) {
// mentions only
// delete old rule first, then add new rule
mtx::pushrules::PushRule rule;
rule.actions = {mtx::pushrules::actions::dont_notify{}};
http::client()->put_pushrules(
"global", "room", room_id, rule, [room_id](mtx::http::RequestErr &err) {
if (err)
nhlog::net()->error("failed to set pushrule for room {}: {} {}",
room_id,
static_cast<int>(err->status_code),
err->matrix_error.error);
http::client()->delete_pushrules(
"global", "override", room_id, [room_id](mtx::http::RequestErr &) {});
});
} else {
// all messages
http::client()->delete_pushrules(
"global", "override", room_id, [room_id](mtx::http::RequestErr &) {
http::client()->delete_pushrules(
"global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
});
}
}
void
RoomSettings::changeAccessRules(int index)
{
using namespace mtx::events::state;
auto guest_access = [](int index) -> state::GuestAccess {
state::GuestAccess event;
if (index == 0)
event.guest_access = state::AccessState::CanJoin;
else
event.guest_access = state::AccessState::Forbidden;
return event;
}(index);
auto join_rule = [](int index) -> state::JoinRules {
state::JoinRules event;
switch (index) {
case 0:
case 1:
event.join_rule = state::JoinRule::Public;
break;
default:
event.join_rule = state::JoinRule::Invite;
}
return event;
}(index);
updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
}
void
RoomSettings::updateAccessRules(const std::string &room_id,
const mtx::events::state::JoinRules &join_rule,
const mtx::events::state::GuestAccess &guest_access)
{
// startLoadingSpinner();
// resetErrorLabel();
http::client()->send_state_event(
room_id,
join_rule,
[this, room_id, guest_access](const mtx::responses::EventId &,
mtx::http::RequestErr err) {
if (err) {
nhlog::net()->warn("failed to send m.room.join_rule: {} {}",
static_cast<int>(err->status_code),
err->matrix_error.error);
// emit showErrorMessage(QString::fromStdString(err->matrix_error.error));
return;
}
http::client()->send_state_event(
room_id,
guest_access,
[this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
if (err) {
nhlog::net()->warn("failed to send m.room.guest_access: {} {}",
static_cast<int>(err->status_code),
err->matrix_error.error);
// emit showErrorMessage(
// QString::fromStdString(err->matrix_error.error));
return;
}
// emit signal that stops loading spinner and reset error label
});
});
}
\ No newline at end of file
......@@ -3,23 +3,52 @@
#include <QObject>
#include <QString>
#include <mtx/events/guest_access.hpp>
#include "CacheStructs.h"
class RoomSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(QString roomName READ roomName CONSTANT)
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
Q_PROPERTY(bool respondsToKeyRequests READ respondsToKeyRequests NOTIFY keyRequestsChanged)
public:
RoomSettings(QString roomid, QObject *parent = nullptr);
QString roomName() const;
int notifications();
int accessJoinRules();
bool respondsToKeyRequests();
//! Whether the user has enough power level to send m.room.join_rules events.
bool canChangeJoinRules() const;
bool isEncryptionEnabled() const;
Q_INVOKABLE void changeNotifications(int currentIndex);
Q_INVOKABLE void changeAccessRules(int index);
Q_INVOKABLE void changeKeyRequestsPreference(bool isOn);
Q_INVOKABLE void enableEncryption();
signals:
void notificationsChanged();
void accessJoinRulesChanged();
void keyRequestsChanged();
void encryptionChanged();
private:
void retrieveRoomInfo();
void updateAccessRules(const std::string &room_id,
const mtx::events::state::JoinRules &,
const mtx::events::state::GuestAccess &);
private:
QString roomid_;
bool usesEncryption_ = false;
RoomInfo info_;
int notifications_ = 0;
int accessRules_ = 0;
};
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment