mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-10-30 09:30:47 +03:00
Add member list
This commit is contained in:
parent
3097037c3d
commit
763330fd3c
13 changed files with 300 additions and 14 deletions
|
@ -102,6 +102,7 @@ set(SRC_FILES
|
|||
src/dialogs/PreviewUploadOverlay.cc
|
||||
src/dialogs/InviteUsers.cc
|
||||
src/dialogs/JoinRoom.cc
|
||||
src/dialogs/MemberList.cpp
|
||||
src/dialogs/LeaveRoom.cc
|
||||
src/dialogs/Logout.cc
|
||||
src/dialogs/ReadReceipts.cc
|
||||
|
@ -219,6 +220,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||
include/dialogs/PreviewUploadOverlay.h
|
||||
include/dialogs/InviteUsers.h
|
||||
include/dialogs/JoinRoom.h
|
||||
include/dialogs/MemberList.hpp
|
||||
include/dialogs/LeaveRoom.h
|
||||
include/dialogs/Logout.h
|
||||
include/dialogs/ReadReceipts.h
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
#include <lmdb++.h>
|
||||
#include <mtx/responses.hpp>
|
||||
|
||||
struct RoomMember
|
||||
{
|
||||
QString user_id;
|
||||
QString display_name;
|
||||
QImage avatar;
|
||||
};
|
||||
|
||||
struct SearchResult
|
||||
{
|
||||
QString user_id;
|
||||
|
@ -32,6 +39,7 @@ struct SearchResult
|
|||
|
||||
Q_DECLARE_METATYPE(SearchResult)
|
||||
Q_DECLARE_METATYPE(QVector<SearchResult>)
|
||||
Q_DECLARE_METATYPE(RoomMember);
|
||||
|
||||
//! Used to uniquely identify a list of read receipts.
|
||||
struct ReadReceiptKey
|
||||
|
@ -164,6 +172,11 @@ public:
|
|||
lmdb::dbi &membersdb,
|
||||
const QString &room_id);
|
||||
|
||||
//! Retrieve member info from a room.
|
||||
std::vector<RoomMember> getMembers(const std::string &room_id,
|
||||
std::size_t startIndex = 0,
|
||||
std::size_t len = 30);
|
||||
|
||||
void saveState(const mtx::responses::Sync &res);
|
||||
bool isInitialized() const;
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ class InviteUsers;
|
|||
class JoinRoom;
|
||||
class LeaveRoom;
|
||||
class Logout;
|
||||
class MemberList;
|
||||
class ReCaptcha;
|
||||
class RoomSettings;
|
||||
}
|
||||
|
@ -70,6 +71,7 @@ public:
|
|||
void openJoinRoomDialog(std::function<void(const QString &room_id)> callback);
|
||||
void openLogoutDialog(std::function<void()> callback);
|
||||
void openRoomSettings(const QString &room_id = "");
|
||||
void openMemberListDialog(const QString &room_id = "");
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
@ -153,4 +155,8 @@ private:
|
|||
QSharedPointer<OverlayModal> roomSettingsModal_;
|
||||
//! Room settings dialog.
|
||||
QSharedPointer<dialogs::RoomSettings> roomSettingsDialog_;
|
||||
//! Member list modal.
|
||||
QSharedPointer<OverlayModal> memberListModal_;
|
||||
//! Member list dialog.
|
||||
QSharedPointer<dialogs::MemberList> memberListDialog_;
|
||||
};
|
||||
|
|
|
@ -67,6 +67,7 @@ private:
|
|||
|
||||
Menu *menu_;
|
||||
QAction *leaveRoom_;
|
||||
QAction *roomMembers_;
|
||||
QAction *roomSettings_;
|
||||
QAction *inviteUsers_;
|
||||
|
||||
|
|
57
include/dialogs/MemberList.hpp
Normal file
57
include/dialogs/MemberList.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QListWidget>
|
||||
|
||||
class Avatar;
|
||||
class Cache;
|
||||
class FlatButton;
|
||||
class QHBoxLayout;
|
||||
class QLabel;
|
||||
class QVBoxLayout;
|
||||
|
||||
struct RoomMember;
|
||||
|
||||
template<class T>
|
||||
class QSharedPointer;
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
class MemberItem : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MemberItem(const RoomMember &member, QWidget *parent);
|
||||
|
||||
private:
|
||||
QHBoxLayout *topLayout_;
|
||||
QVBoxLayout *textLayout_;
|
||||
|
||||
Avatar *avatar_;
|
||||
|
||||
QLabel *userName_;
|
||||
QLabel *userId_;
|
||||
};
|
||||
|
||||
class MemberList : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MemberList(const QString &room_id, QSharedPointer<Cache> cache, QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void addUsers(const std::vector<RoomMember> &users);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void moveButtonToBottom();
|
||||
|
||||
private:
|
||||
QString room_id_;
|
||||
QLabel *topLabel_;
|
||||
QListWidget *list_;
|
||||
QSharedPointer<Cache> cache_;
|
||||
FlatButton *moreBtn_;
|
||||
};
|
||||
} // dialogs
|
|
@ -140,6 +140,7 @@ dialogs--RoomSettings,
|
|||
dialogs--InviteUsers,
|
||||
dialogs--ReadReceipts,
|
||||
dialogs--JoinRoom,
|
||||
dialogs--MemberList,
|
||||
dialogs--PreviewUploadOverlay,
|
||||
dialogs--CreateRoom > QLineEdit,
|
||||
dialogs--InviteUsers > QLineEdit,
|
||||
|
|
|
@ -141,6 +141,7 @@ dialogs--CreateRoom,
|
|||
dialogs--RoomSettings,
|
||||
dialogs--InviteUsers,
|
||||
dialogs--ReadReceipts,
|
||||
dialogs--MemberList,
|
||||
dialogs--JoinRoom,
|
||||
dialogs--PreviewUploadOverlay,
|
||||
QListWidget {
|
||||
|
|
42
src/Cache.cc
42
src/Cache.cc
|
@ -1045,6 +1045,48 @@ Cache::searchUsers(const std::string &room_id, const std::string &query, std::ui
|
|||
return results;
|
||||
}
|
||||
|
||||
std::vector<RoomMember>
|
||||
Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
|
||||
{
|
||||
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
|
||||
auto db = getMembersDb(txn, room_id);
|
||||
auto cursor = lmdb::cursor::open(txn, db);
|
||||
|
||||
std::size_t currentIndex = 0;
|
||||
|
||||
const auto endIndex = std::min(startIndex + len, db.size(txn));
|
||||
|
||||
std::vector<RoomMember> members;
|
||||
|
||||
std::string user_id, user_data;
|
||||
while (cursor.get(user_id, user_data, MDB_NEXT)) {
|
||||
if (currentIndex < startIndex) {
|
||||
currentIndex += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentIndex >= endIndex)
|
||||
break;
|
||||
|
||||
try {
|
||||
MemberInfo tmp = json::parse(user_data);
|
||||
members.emplace_back(
|
||||
RoomMember{QString::fromStdString(user_id),
|
||||
QString::fromStdString(tmp.name),
|
||||
QImage::fromData(image(txn, tmp.avatar_url))});
|
||||
} catch (const json::exception &e) {
|
||||
qWarning() << e.what();
|
||||
}
|
||||
|
||||
currentIndex += 1;
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
txn.commit();
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
QHash<QString, QString> Cache::DisplayNames;
|
||||
QHash<QString, QString> Cache::AvatarUrls;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "dialogs/JoinRoom.h"
|
||||
#include "dialogs/LeaveRoom.h"
|
||||
#include "dialogs/Logout.h"
|
||||
#include "dialogs/MemberList.hpp"
|
||||
#include "dialogs/RoomSettings.hpp"
|
||||
|
||||
MainWindow *MainWindow::instance_ = nullptr;
|
||||
|
@ -268,8 +269,6 @@ MainWindow::openRoomSettings(const QString &room_id)
|
|||
{
|
||||
const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : "";
|
||||
|
||||
qDebug() << "room settings" << roomToSearch;
|
||||
|
||||
roomSettingsDialog_ = QSharedPointer<dialogs::RoomSettings>(
|
||||
new dialogs::RoomSettings(roomToSearch, chat_page_->cache(), this));
|
||||
|
||||
|
@ -279,11 +278,24 @@ MainWindow::openRoomSettings(const QString &room_id)
|
|||
|
||||
roomSettingsModal_ =
|
||||
QSharedPointer<OverlayModal>(new OverlayModal(this, roomSettingsDialog_.data()));
|
||||
roomSettingsModal_->setColor(QColor(30, 30, 30, 170));
|
||||
|
||||
roomSettingsModal_->show();
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::openMemberListDialog(const QString &room_id)
|
||||
{
|
||||
const auto roomToSearch = room_id.isEmpty() ? chat_page_->currentRoom() : "";
|
||||
|
||||
memberListDialog_ = QSharedPointer<dialogs::MemberList>(
|
||||
new dialogs::MemberList(roomToSearch, chat_page_->cache(), this));
|
||||
|
||||
memberListModal_ =
|
||||
QSharedPointer<OverlayModal>(new OverlayModal(this, memberListDialog_.data()));
|
||||
|
||||
memberListModal_->show();
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::openLeaveRoomDialog(const QString &room_id)
|
||||
{
|
||||
|
@ -325,6 +337,7 @@ MainWindow::showOverlayProgressBar()
|
|||
progressModal_ =
|
||||
QSharedPointer<OverlayModal>(new OverlayModal(this, spinner_.data()),
|
||||
[](OverlayModal *modal) { modal->deleteLater(); });
|
||||
progressModal_->setColor(QColor(30, 30, 30));
|
||||
progressModal_->setDismissible(false);
|
||||
progressModal_->show();
|
||||
}
|
||||
|
@ -377,7 +390,6 @@ MainWindow::openJoinRoomDialog(std::function<void(const QString &room_id)> callb
|
|||
if (joinRoomModal_.isNull()) {
|
||||
joinRoomModal_ = QSharedPointer<OverlayModal>(
|
||||
new OverlayModal(MainWindow::instance(), joinRoomDialog_.data()));
|
||||
joinRoomModal_->setColor(QColor(30, 30, 30, 170));
|
||||
}
|
||||
|
||||
joinRoomModal_->show();
|
||||
|
@ -406,7 +418,6 @@ MainWindow::openCreateRoomDialog(
|
|||
if (createRoomModal_.isNull()) {
|
||||
createRoomModal_ = QSharedPointer<OverlayModal>(
|
||||
new OverlayModal(MainWindow::instance(), createRoomDialog_.data()));
|
||||
createRoomModal_->setColor(QColor(30, 30, 30, 170));
|
||||
}
|
||||
|
||||
createRoomModal_->show();
|
||||
|
@ -431,7 +442,6 @@ MainWindow::openLogoutDialog(std::function<void()> callback)
|
|||
if (logoutModal_.isNull()) {
|
||||
logoutModal_ = QSharedPointer<OverlayModal>(
|
||||
new OverlayModal(MainWindow::instance(), logoutDialog_.data()));
|
||||
logoutModal_->setColor(QColor(30, 30, 30, 170));
|
||||
}
|
||||
|
||||
logoutModal_->show();
|
||||
|
|
|
@ -90,6 +90,11 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||
[this](const QStringList &invitees) { emit inviteUsers(invitees); });
|
||||
});
|
||||
|
||||
roomMembers_ = new QAction(tr("Members"), this);
|
||||
connect(roomMembers_, &QAction::triggered, this, []() {
|
||||
MainWindow::instance()->openMemberListDialog();
|
||||
});
|
||||
|
||||
leaveRoom_ = new QAction(tr("Leave room"), this);
|
||||
connect(leaveRoom_, &QAction::triggered, this, []() {
|
||||
MainWindow::instance()->openLeaveRoomDialog();
|
||||
|
@ -101,6 +106,7 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||
});
|
||||
|
||||
menu_->addAction(inviteUsers_);
|
||||
menu_->addAction(roomMembers_);
|
||||
menu_->addAction(leaveRoom_);
|
||||
menu_->addAction(roomSettings_);
|
||||
|
||||
|
|
145
src/dialogs/MemberList.cpp
Normal file
145
src/dialogs/MemberList.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#include <QListWidgetItem>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Config.h"
|
||||
#include "FlatButton.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "Cache.h"
|
||||
#include "dialogs/MemberList.hpp"
|
||||
|
||||
using namespace dialogs;
|
||||
|
||||
MemberItem::MemberItem(const RoomMember &member, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
topLayout_ = new QHBoxLayout(this);
|
||||
topLayout_->setMargin(0);
|
||||
|
||||
textLayout_ = new QVBoxLayout;
|
||||
textLayout_->setMargin(0);
|
||||
textLayout_->setSpacing(0);
|
||||
|
||||
avatar_ = new Avatar(this);
|
||||
avatar_->setSize(44);
|
||||
avatar_->setLetter(utils::firstChar(member.display_name));
|
||||
|
||||
if (!member.avatar.isNull())
|
||||
avatar_->setImage(member.avatar);
|
||||
|
||||
QFont nameFont, idFont;
|
||||
nameFont.setWeight(65);
|
||||
nameFont.setPixelSize(conf::receipts::font + 1);
|
||||
idFont.setWeight(50);
|
||||
idFont.setPixelSize(conf::receipts::font);
|
||||
|
||||
userName_ = new QLabel(member.display_name, this);
|
||||
userName_->setFont(nameFont);
|
||||
|
||||
userId_ = new QLabel(member.user_id, this);
|
||||
userId_->setFont(idFont);
|
||||
|
||||
textLayout_->addWidget(userName_);
|
||||
textLayout_->addWidget(userId_);
|
||||
|
||||
topLayout_->addWidget(avatar_);
|
||||
topLayout_->addLayout(textLayout_, 1);
|
||||
}
|
||||
|
||||
MemberList::MemberList(const QString &room_id, QSharedPointer<Cache> cache, QWidget *parent)
|
||||
: QFrame(parent)
|
||||
, room_id_{room_id}
|
||||
, cache_{cache}
|
||||
{
|
||||
setMaximumSize(420, 380);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(30);
|
||||
layout->setMargin(20);
|
||||
|
||||
list_ = new QListWidget;
|
||||
list_->setFrameStyle(QFrame::NoFrame);
|
||||
list_->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
list_->setAttribute(Qt::WA_MacShowFocusRect, 0);
|
||||
list_->setSpacing(5);
|
||||
|
||||
QFont font;
|
||||
font.setPixelSize(conf::headerFontSize);
|
||||
|
||||
topLabel_ = new QLabel(tr("Room members"), this);
|
||||
topLabel_->setAlignment(Qt::AlignCenter);
|
||||
topLabel_->setFont(font);
|
||||
|
||||
layout->addWidget(topLabel_);
|
||||
layout->addWidget(list_);
|
||||
|
||||
list_->clear();
|
||||
|
||||
// Add button at the bottom.
|
||||
moreBtn_ = new FlatButton(tr("SHOW MORE"), this);
|
||||
auto item = new QListWidgetItem;
|
||||
item->setSizeHint(moreBtn_->minimumSizeHint());
|
||||
item->setFlags(Qt::NoItemFlags);
|
||||
item->setTextAlignment(Qt::AlignCenter);
|
||||
list_->insertItem(0, item);
|
||||
list_->setItemWidget(item, moreBtn_);
|
||||
|
||||
connect(moreBtn_, &FlatButton::clicked, this, [this]() {
|
||||
const size_t numMembers = list_->count() - 1;
|
||||
|
||||
if (numMembers > 0)
|
||||
addUsers(cache_->getMembers(room_id_.toStdString(), numMembers));
|
||||
});
|
||||
|
||||
try {
|
||||
addUsers(cache_->getMembers(room_id_.toStdString()));
|
||||
} catch (const lmdb::error &e) {
|
||||
qCritical() << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MemberList::moveButtonToBottom()
|
||||
{
|
||||
auto item = new QListWidgetItem(list_);
|
||||
item->setSizeHint(moreBtn_->minimumSizeHint());
|
||||
item->setFlags(Qt::NoItemFlags);
|
||||
item->setTextAlignment(Qt::AlignCenter);
|
||||
list_->setItemWidget(item, moreBtn_);
|
||||
list_->addItem(item);
|
||||
}
|
||||
|
||||
void
|
||||
MemberList::addUsers(const std::vector<RoomMember> &members)
|
||||
{
|
||||
if (members.size() == 0) {
|
||||
moreBtn_->hide();
|
||||
} else {
|
||||
moreBtn_->show();
|
||||
}
|
||||
|
||||
for (const auto &member : members) {
|
||||
auto user = new MemberItem(member, this);
|
||||
auto item = new QListWidgetItem;
|
||||
|
||||
item->setSizeHint(user->minimumSizeHint());
|
||||
item->setFlags(Qt::NoItemFlags);
|
||||
item->setTextAlignment(Qt::AlignCenter);
|
||||
|
||||
list_->insertItem(list_->count() - 1, item);
|
||||
list_->setItemWidget(item, user);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MemberList::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
}
|
|
@ -49,18 +49,20 @@ RoomSettings::RoomSettings(const QString &room_id, QSharedPointer<Cache> cache,
|
|||
|
||||
auto notifOptionLayout_ = new QHBoxLayout;
|
||||
notifOptionLayout_->setMargin(5);
|
||||
auto themeLabel_ = new QLabel(tr("Notifications"), this);
|
||||
auto notifLabel = new QLabel(tr("Notifications"), this);
|
||||
auto notifCombo = new QComboBox(this);
|
||||
notifCombo->addItem("Nothing");
|
||||
notifCombo->addItem("Mentions only");
|
||||
notifCombo->addItem("All messages");
|
||||
themeLabel_->setStyleSheet("font-size: 15px;");
|
||||
notifCombo->setDisabled(true);
|
||||
notifCombo->addItem(tr("Muted"));
|
||||
notifCombo->addItem(tr("Mentions only"));
|
||||
notifCombo->addItem(tr("All messages"));
|
||||
notifLabel->setStyleSheet("font-size: 15px;");
|
||||
|
||||
notifOptionLayout_->addWidget(themeLabel_);
|
||||
notifOptionLayout_->addWidget(notifLabel);
|
||||
notifOptionLayout_->addWidget(notifCombo, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||
|
||||
layout->addWidget(new TopSection(info_, avatarImg_, this));
|
||||
layout->addLayout(notifOptionLayout_);
|
||||
layout->addLayout(notifOptionLayout_);
|
||||
layout->addLayout(btnLayout);
|
||||
|
||||
connect(cancelBtn_, &FlatButton::clicked, this, &RoomSettings::closing);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
OverlayModal::OverlayModal(QWidget *parent, QWidget *content)
|
||||
: OverlayWidget(parent)
|
||||
, content_{content}
|
||||
, color_{QColor(55, 55, 55)}
|
||||
, color_{QColor(30, 30, 30, 170)}
|
||||
{
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addWidget(content);
|
||||
|
|
Loading…
Reference in a new issue