diff --git a/include/Cache.h b/include/Cache.h index a39633a8..20f277a9 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -22,7 +22,9 @@ #include #include #include +#include #include +using mtx::events::state::JoinRule; struct RoomMember { @@ -74,15 +76,20 @@ struct RoomInfo bool is_invite = false; //! Total number of members in the room. int16_t member_count = 0; + //! Who can access to the room. + JoinRule join_rule = JoinRule::Public; + bool guest_access = false; }; inline void to_json(json &j, const RoomInfo &info) { - j["name"] = info.name; - j["topic"] = info.topic; - j["avatar_url"] = info.avatar_url; - j["is_invite"] = info.is_invite; + j["name"] = info.name; + j["topic"] = info.topic; + j["avatar_url"] = info.avatar_url; + j["is_invite"] = info.is_invite; + j["join_rule"] = info.join_rule; + j["guest_access"] = info.guest_access; if (info.member_count != 0) j["member_count"] = info.member_count; @@ -91,10 +98,12 @@ to_json(json &j, const RoomInfo &info) inline void from_json(const json &j, RoomInfo &info) { - info.name = j.at("name"); - info.topic = j.at("topic"); - info.avatar_url = j.at("avatar_url"); - info.is_invite = j.at("is_invite"); + info.name = j.at("name"); + info.topic = j.at("topic"); + info.avatar_url = j.at("avatar_url"); + info.is_invite = j.at("is_invite"); + info.join_rule = j.at("join_rule"); + info.guest_access = j.at("guest_access"); if (j.count("member_count")) info.member_count = j.at("member_count"); @@ -164,6 +173,9 @@ public: //! Calculate & return the name of the room. QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb); + //! Get room join rules + JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb); + bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb); //! Retrieve the topic of the room if any. QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb); //! Retrieve the room avatar's url if any. diff --git a/include/dialogs/RoomSettings.hpp b/include/dialogs/RoomSettings.hpp index df94fea3..79ca9375 100644 --- a/include/dialogs/RoomSettings.hpp +++ b/include/dialogs/RoomSettings.hpp @@ -11,6 +11,7 @@ class Avatar; class QPixmap; class QLayout; class QLabel; +class QComboBox; template class QSharedPointer; @@ -54,6 +55,9 @@ signals: protected: void paintEvent(QPaintEvent *event) override; +private slots: + void save_and_close(); + private: static constexpr int AvatarSize = 64; @@ -66,6 +70,8 @@ private: RoomInfo info_; QString room_id_; QImage avatarImg_; + + QComboBox *accessCombo; }; } // dialogs diff --git a/src/Cache.cc b/src/Cache.cc index 23d37f58..31e86a69 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -30,7 +30,7 @@ //! Should be changed when a breaking change occurs in the cache format. //! This will reset client's data. -static const std::string CURRENT_CACHE_FORMAT_VERSION("2018.04.21"); +static const std::string CURRENT_CACHE_FORMAT_VERSION("2018.05.11"); static const lmdb::val NEXT_BATCH_KEY("next_batch"); static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); @@ -550,7 +550,8 @@ Cache::roomsWithStateUpdates(const mtx::responses::Sync &res) RoomInfo Cache::singleRoomInfo(const std::string &room_id) { - auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto statesdb = getStatesDb(txn, room_id); lmdb::val data; @@ -559,6 +560,8 @@ Cache::singleRoomInfo(const std::string &room_id) try { RoomInfo tmp = json::parse(std::string(data.data(), data.size())); tmp.member_count = getMembersDb(txn, room_id).size(txn); + tmp.join_rule = getRoomJoinRule(txn, statesdb); + tmp.guest_access = getRoomGuestAccess(txn, statesdb); txn.commit(); @@ -584,12 +587,15 @@ Cache::getRoomInfo(const std::vector &rooms) for (const auto &room : rooms) { lmdb::val data; + auto statesdb = getStatesDb(txn, room); // Check if the room is joined. if (lmdb::dbi_get(txn, roomsDb_, lmdb::val(room), data)) { try { RoomInfo tmp = json::parse(std::string(data.data(), data.size())); tmp.member_count = getMembersDb(txn, room).size(txn); + tmp.join_rule = getRoomJoinRule(txn, statesdb); + tmp.guest_access = getRoomGuestAccess(txn, statesdb); room_info.emplace(QString::fromStdString(room), std::move(tmp)); } catch (const json::exception &e) { @@ -805,6 +811,50 @@ Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb) return "Empty Room"; } +JoinRule +Cache::getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + using namespace mtx::events; + using namespace mtx::events::state; + + lmdb::val event; + bool res = lmdb::dbi_get( + txn, statesdb, lmdb::val(to_string(mtx::events::EventType::RoomJoinRules)), event); + + if (res) { + try { + StateEvent msg = + json::parse(std::string(event.data(), event.size())); + return msg.content.join_rule; + } catch (const json::exception &e) { + qWarning() << e.what(); + } + } + return JoinRule::Knock; +} + +bool +Cache::getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb) +{ + using namespace mtx::events; + using namespace mtx::events::state; + + lmdb::val event; + bool res = lmdb::dbi_get( + txn, statesdb, lmdb::val(to_string(mtx::events::EventType::RoomGuestAccess)), event); + + if (res) { + try { + StateEvent msg = + json::parse(std::string(event.data(), event.size())); + return msg.content.guest_access == AccessState::CanJoin; + } catch (const json::exception &e) { + qWarning() << e.what(); + } + } + return false; +} + QString Cache::getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb) { diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index b85971b0..9bf4cf26 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -38,8 +38,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) setMaximumWidth(385); try { - auto res = cache::client()->getRoomInfo({room_id_.toStdString()}); - info_ = res[room_id_]; + info_ = cache::client()->singleRoomInfo(room_id_.toStdString()); setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url))); } catch (const lmdb::error &e) { @@ -75,13 +74,67 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) notifOptionLayout_->addWidget(notifLabel); notifOptionLayout_->addWidget(notifCombo, 0, Qt::AlignBottom | Qt::AlignRight); + auto accessOptionLayout = new QHBoxLayout(); + accessOptionLayout->setMargin(5); + auto accessLabel = new QLabel(tr("Room access"), this); + accessCombo = new QComboBox(this); + accessCombo->addItem(tr("Anyone and guests")); + accessCombo->addItem(tr("Anyone")); + accessCombo->addItem(tr("Invited users")); + accessCombo->setDisabled(true); + accessLabel->setStyleSheet("font-size: 15px;"); + + if(info_.join_rule == JoinRule::Public) + { + if(info_.guest_access) + { + accessCombo->setCurrentIndex(0); + } + else + { + accessCombo->setCurrentIndex(1); + } + } + else + { + accessCombo->setCurrentIndex(2); + } + + accessOptionLayout->addWidget(accessLabel); + accessOptionLayout->addWidget(accessCombo); + layout->addWidget(new TopSection(info_, avatarImg_, this)); layout->addLayout(notifOptionLayout_); layout->addLayout(notifOptionLayout_); + layout->addLayout(accessOptionLayout); layout->addLayout(btnLayout); connect(cancelBtn_, &FlatButton::clicked, this, &RoomSettings::closing); - connect(saveBtn_, &FlatButton::clicked, this, [this]() { emit closing(); }); + connect(saveBtn_, &FlatButton::clicked, this, &RoomSettings::save_and_close); +} + +void +RoomSettings::save_and_close() { + // TODO: Save access changes to the room + if (accessCombo->currentIndex()<2) { + if(info_.join_rule != JoinRule::Public) { + // Make join_rule Public + } + if(accessCombo->currentIndex()==0) { + if(!info_.guest_access) { + // Make guest_access CanJoin + } + } + } + else { + if(info_.join_rule != JoinRule::Invite) { + // Make join_rule invite + } + if(info_.guest_access) { + // Make guest_access forbidden + } + } + closing(); } void