mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-10-30 09:30:47 +03:00
Add prototype room settings menu
This commit is contained in:
parent
21c68c5824
commit
3097037c3d
14 changed files with 309 additions and 12 deletions
|
@ -106,6 +106,7 @@ set(SRC_FILES
|
|||
src/dialogs/Logout.cc
|
||||
src/dialogs/ReadReceipts.cc
|
||||
src/dialogs/ReCaptcha.cpp
|
||||
src/dialogs/RoomSettings.cpp
|
||||
|
||||
# Emoji
|
||||
src/emoji/Category.cc
|
||||
|
@ -222,6 +223,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||
include/dialogs/Logout.h
|
||||
include/dialogs/ReadReceipts.h
|
||||
include/dialogs/ReCaptcha.hpp
|
||||
include/dialogs/RoomSettings.hpp
|
||||
|
||||
# Emoji
|
||||
include/emoji/Category.h
|
||||
|
|
|
@ -64,6 +64,8 @@ struct RoomInfo
|
|||
std::string avatar_url;
|
||||
//! Whether or not the room is an invite.
|
||||
bool is_invite = false;
|
||||
//! Total number of members in the room.
|
||||
int16_t member_count = 0;
|
||||
};
|
||||
|
||||
inline void
|
||||
|
@ -73,6 +75,9 @@ to_json(json &j, const RoomInfo &info)
|
|||
j["topic"] = info.topic;
|
||||
j["avatar_url"] = info.avatar_url;
|
||||
j["is_invite"] = info.is_invite;
|
||||
|
||||
if (info.member_count != 0)
|
||||
j["member_count"] = info.member_count;
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -82,6 +87,9 @@ from_json(const json &j, RoomInfo &info)
|
|||
info.topic = j.at("topic");
|
||||
info.avatar_url = j.at("avatar_url");
|
||||
info.is_invite = j.at("is_invite");
|
||||
|
||||
if (j.count("member_count"))
|
||||
info.member_count = j.at("member_count");
|
||||
}
|
||||
|
||||
//! Basic information per member;
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
}
|
||||
|
||||
QSharedPointer<UserSettings> userSettings() { return userSettings_; }
|
||||
QSharedPointer<Cache> cache() { return cache_; }
|
||||
|
||||
signals:
|
||||
void contentLoaded();
|
||||
|
|
|
@ -50,6 +50,7 @@ class JoinRoom;
|
|||
class LeaveRoom;
|
||||
class Logout;
|
||||
class ReCaptcha;
|
||||
class RoomSettings;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
std::function<void(const mtx::requests::CreateRoom &request)> callback);
|
||||
void openJoinRoomDialog(std::function<void(const QString &room_id)> callback);
|
||||
void openLogoutDialog(std::function<void()> callback);
|
||||
void openRoomSettings(const QString &room_id = "");
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
@ -147,4 +149,8 @@ private:
|
|||
QSharedPointer<OverlayModal> logoutModal_;
|
||||
//! Logout dialog.
|
||||
QSharedPointer<dialogs::Logout> logoutDialog_;
|
||||
//! Room settings modal.
|
||||
QSharedPointer<OverlayModal> roomSettingsModal_;
|
||||
//! Room settings dialog.
|
||||
QSharedPointer<dialogs::RoomSettings> roomSettingsDialog_;
|
||||
};
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <QIcon>
|
||||
#include <QImage>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QPaintEvent>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
|
@ -66,8 +65,9 @@ private:
|
|||
QLabel *nameLabel_;
|
||||
Label *topicLabel_;
|
||||
|
||||
QMenu *menu_;
|
||||
Menu *menu_;
|
||||
QAction *leaveRoom_;
|
||||
QAction *roomSettings_;
|
||||
QAction *inviteUsers_;
|
||||
|
||||
FlatButton *settingsBtn_;
|
||||
|
|
88
include/dialogs/RoomSettings.hpp
Normal file
88
include/dialogs/RoomSettings.hpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QImage>
|
||||
|
||||
#include "Cache.h"
|
||||
|
||||
class FlatButton;
|
||||
class TextField;
|
||||
class Avatar;
|
||||
class QPixmap;
|
||||
class QLayout;
|
||||
class QLabel;
|
||||
|
||||
template<class T>
|
||||
class QSharedPointer;
|
||||
|
||||
class TopSection : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
|
||||
|
||||
public:
|
||||
TopSection(const RoomInfo &info, const QImage &img, QWidget *parent = nullptr)
|
||||
: QWidget{parent}
|
||||
, info_{std::move(info)}
|
||||
{
|
||||
textColor_ = palette().color(QPalette::Text);
|
||||
avatar_ = QPixmap::fromImage(img.scaled(
|
||||
AvatarSize, AvatarSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
QSize sizeHint() const override
|
||||
{
|
||||
QFont font;
|
||||
font.setPixelSize(18);
|
||||
return QSize(200, AvatarSize + QFontMetrics(font).ascent() + 6 * Padding);
|
||||
}
|
||||
|
||||
QColor textColor() const { return textColor_; }
|
||||
void setTextColor(QColor &color) { textColor_ = color; }
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
static constexpr int AvatarSize = 72;
|
||||
static constexpr int Padding = 5;
|
||||
|
||||
RoomInfo info_;
|
||||
QPixmap avatar_;
|
||||
QColor textColor_;
|
||||
};
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
class RoomSettings : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RoomSettings(const QString &room_id,
|
||||
QSharedPointer<Cache> cache,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void closing();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
static constexpr int AvatarSize = 64;
|
||||
|
||||
void setAvatar(const QImage &img) { avatarImg_ = img; }
|
||||
|
||||
QSharedPointer<Cache> cache_;
|
||||
|
||||
// Button section
|
||||
FlatButton *saveBtn_;
|
||||
FlatButton *cancelBtn_;
|
||||
|
||||
RoomInfo info_;
|
||||
QString room_id_;
|
||||
QImage avatarImg_;
|
||||
};
|
||||
|
||||
} // dialogs
|
|
@ -103,7 +103,7 @@ public:
|
|||
drawPixmap(region, pix);
|
||||
}
|
||||
|
||||
void drawLetterAvatar(const QChar &c,
|
||||
void drawLetterAvatar(const QString &c,
|
||||
const QColor &penColor,
|
||||
const QColor &brushColor,
|
||||
int w,
|
||||
|
|
|
@ -136,6 +136,7 @@ dialogs--Logout,
|
|||
dialogs--ReCaptcha,
|
||||
dialogs--LeaveRoom,
|
||||
dialogs--CreateRoom,
|
||||
dialogs--RoomSettings,
|
||||
dialogs--InviteUsers,
|
||||
dialogs--ReadReceipts,
|
||||
dialogs--JoinRoom,
|
||||
|
@ -147,6 +148,10 @@ dialogs--JoinRoom > QLineEdit {
|
|||
color: #caccd1;
|
||||
}
|
||||
|
||||
TopSection {
|
||||
qproperty-textColor: #caccd1;
|
||||
}
|
||||
|
||||
QListWidget,
|
||||
WelcomePage,
|
||||
LoginPage,
|
||||
|
|
|
@ -138,6 +138,7 @@ dialogs--Logout,
|
|||
dialogs--ReCaptcha,
|
||||
dialogs--LeaveRoom,
|
||||
dialogs--CreateRoom,
|
||||
dialogs--RoomSettings,
|
||||
dialogs--InviteUsers,
|
||||
dialogs--ReadReceipts,
|
||||
dialogs--JoinRoom,
|
||||
|
@ -147,6 +148,10 @@ QListWidget {
|
|||
color: #333;
|
||||
}
|
||||
|
||||
TopSection {
|
||||
qproperty-textColor: #333;
|
||||
}
|
||||
|
||||
WelcomePage,
|
||||
LoginPage,
|
||||
RegisterPage {
|
||||
|
|
22
src/Cache.cc
22
src/Cache.cc
|
@ -538,9 +538,10 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms)
|
|||
// Check if the room is joined.
|
||||
if (lmdb::dbi_get(txn, roomsDb_, lmdb::val(room), data)) {
|
||||
try {
|
||||
room_info.emplace(
|
||||
QString::fromStdString(room),
|
||||
json::parse(std::string(data.data(), data.size())));
|
||||
RoomInfo tmp = json::parse(std::string(data.data(), data.size()));
|
||||
tmp.member_count = getMembersDb(txn, room).size(txn);
|
||||
|
||||
room_info.emplace(QString::fromStdString(room), std::move(tmp));
|
||||
} catch (const json::exception &e) {
|
||||
qWarning()
|
||||
<< "failed to parse room info:" << QString::fromStdString(room)
|
||||
|
@ -550,9 +551,12 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms)
|
|||
// Check if the room is an invite.
|
||||
if (lmdb::dbi_get(txn, invitesDb_, lmdb::val(room), data)) {
|
||||
try {
|
||||
room_info.emplace(
|
||||
QString::fromStdString(room),
|
||||
json::parse(std::string(data.data(), data.size())));
|
||||
RoomInfo tmp =
|
||||
json::parse(std::string(data.data(), data.size()));
|
||||
tmp.member_count = getInviteMembersDb(txn, room).size(txn);
|
||||
|
||||
room_info.emplace(QString::fromStdString(room),
|
||||
std::move(tmp));
|
||||
} catch (const json::exception &e) {
|
||||
qWarning() << "failed to parse room info for invite:"
|
||||
<< QString::fromStdString(room)
|
||||
|
@ -581,7 +585,8 @@ Cache::roomInfo(bool withInvites)
|
|||
// Gather info about the joined rooms.
|
||||
auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
|
||||
while (roomsCursor.get(room_id, room_data, MDB_NEXT)) {
|
||||
RoomInfo tmp = json::parse(std::move(room_data));
|
||||
RoomInfo tmp = json::parse(std::move(room_data));
|
||||
tmp.member_count = getMembersDb(txn, room_id).size(txn);
|
||||
result.insert(QString::fromStdString(std::move(room_id)), std::move(tmp));
|
||||
}
|
||||
roomsCursor.close();
|
||||
|
@ -590,7 +595,8 @@ Cache::roomInfo(bool withInvites)
|
|||
// Gather info about the invites.
|
||||
auto invitesCursor = lmdb::cursor::open(txn, invitesDb_);
|
||||
while (invitesCursor.get(room_id, room_data, MDB_NEXT)) {
|
||||
RoomInfo tmp = json::parse(room_data);
|
||||
RoomInfo tmp = json::parse(room_data);
|
||||
tmp.member_count = getInviteMembersDb(txn, room_id).size(txn);
|
||||
result.insert(QString::fromStdString(std::move(room_id)), std::move(tmp));
|
||||
}
|
||||
invitesCursor.close();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Painter.h"
|
||||
#include "Ripple.h"
|
||||
#include "RippleOverlay.h"
|
||||
#include "Utils.h"
|
||||
|
||||
CommunitiesListItem::CommunitiesListItem(QSharedPointer<Community> community,
|
||||
QString community_id,
|
||||
|
@ -74,7 +75,7 @@ CommunitiesListItem::paintEvent(QPaintEvent *)
|
|||
font.setPixelSize(conf::roomlist::fonts::communityBubble);
|
||||
p.setFont(font);
|
||||
|
||||
p.drawLetterAvatar(community_->getName()[0],
|
||||
p.drawLetterAvatar(utils::firstChar(community_->getName()),
|
||||
avatarFgColor_,
|
||||
avatarBgColor_,
|
||||
width(),
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "dialogs/JoinRoom.h"
|
||||
#include "dialogs/LeaveRoom.h"
|
||||
#include "dialogs/Logout.h"
|
||||
#include "dialogs/RoomSettings.hpp"
|
||||
|
||||
MainWindow *MainWindow::instance_ = nullptr;
|
||||
|
||||
|
@ -262,6 +263,27 @@ MainWindow::hasActiveUser()
|
|||
settings.contains("auth/user_id");
|
||||
}
|
||||
|
||||
void
|
||||
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));
|
||||
|
||||
connect(roomSettingsDialog_.data(), &dialogs::RoomSettings::closing, this, [this]() {
|
||||
roomSettingsModal_->hide();
|
||||
});
|
||||
|
||||
roomSettingsModal_ =
|
||||
QSharedPointer<OverlayModal>(new OverlayModal(this, roomSettingsDialog_.data()));
|
||||
roomSettingsModal_->setColor(QColor(30, 30, 30, 170));
|
||||
|
||||
roomSettingsModal_->show();
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::openLeaveRoomDialog(const QString &room_id)
|
||||
{
|
||||
|
|
|
@ -95,8 +95,14 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||
MainWindow::instance()->openLeaveRoomDialog();
|
||||
});
|
||||
|
||||
roomSettings_ = new QAction(tr("Settings"), this);
|
||||
connect(roomSettings_, &QAction::triggered, this, []() {
|
||||
MainWindow::instance()->openRoomSettings();
|
||||
});
|
||||
|
||||
menu_->addAction(inviteUsers_);
|
||||
menu_->addAction(leaveRoom_);
|
||||
menu_->addAction(roomSettings_);
|
||||
|
||||
connect(settingsBtn_, &QPushButton::clicked, this, [this]() {
|
||||
auto pos = mapToGlobal(settingsBtn_->pos());
|
||||
|
|
147
src/dialogs/RoomSettings.cpp
Normal file
147
src/dialogs/RoomSettings.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
#include "Avatar.h"
|
||||
#include "Config.h"
|
||||
#include "FlatButton.h"
|
||||
#include "Painter.h"
|
||||
#include "Utils.h"
|
||||
#include "dialogs/RoomSettings.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QSharedPointer>
|
||||
#include <QStyleOption>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace dialogs;
|
||||
|
||||
RoomSettings::RoomSettings(const QString &room_id, QSharedPointer<Cache> cache, QWidget *parent)
|
||||
: QFrame(parent)
|
||||
, cache_{cache}
|
||||
, room_id_{std::move(room_id)}
|
||||
{
|
||||
setMaximumWidth(385);
|
||||
|
||||
try {
|
||||
auto res = cache_->getRoomInfo({room_id_.toStdString()});
|
||||
info_ = res[room_id_];
|
||||
|
||||
setAvatar(QImage::fromData(cache_->image(info_.avatar_url)));
|
||||
} catch (const lmdb::error &e) {
|
||||
qWarning() << "failed to retrieve room info from cache" << room_id;
|
||||
}
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(30);
|
||||
layout->setMargin(20);
|
||||
|
||||
saveBtn_ = new FlatButton("SAVE", this);
|
||||
saveBtn_->setFontSize(conf::btn::fontSize);
|
||||
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
||||
cancelBtn_->setFontSize(conf::btn::fontSize);
|
||||
|
||||
auto btnLayout = new QHBoxLayout();
|
||||
btnLayout->setSpacing(0);
|
||||
btnLayout->setMargin(0);
|
||||
btnLayout->addStretch(1);
|
||||
btnLayout->addWidget(saveBtn_);
|
||||
btnLayout->addWidget(cancelBtn_);
|
||||
|
||||
auto notifOptionLayout_ = new QHBoxLayout;
|
||||
notifOptionLayout_->setMargin(5);
|
||||
auto themeLabel_ = 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;");
|
||||
|
||||
notifOptionLayout_->addWidget(themeLabel_);
|
||||
notifOptionLayout_->addWidget(notifCombo, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||
|
||||
layout->addWidget(new TopSection(info_, avatarImg_, this));
|
||||
layout->addLayout(notifOptionLayout_);
|
||||
layout->addLayout(btnLayout);
|
||||
|
||||
connect(cancelBtn_, &FlatButton::clicked, this, &RoomSettings::closing);
|
||||
connect(saveBtn_, &FlatButton::clicked, this, [this]() { emit closing(); });
|
||||
}
|
||||
|
||||
void
|
||||
RoomSettings::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
}
|
||||
|
||||
void
|
||||
TopSection::paintEvent(QPaintEvent *)
|
||||
{
|
||||
Painter p(this);
|
||||
PainterHighQualityEnabler hq(p);
|
||||
|
||||
constexpr int textPadding = 23;
|
||||
constexpr int textStartX = AvatarSize + 5 * Padding;
|
||||
const int availableTextWidth = width() - textStartX;
|
||||
|
||||
constexpr int nameFont = 15;
|
||||
constexpr int membersFont = 14;
|
||||
constexpr int labelFont = 18;
|
||||
|
||||
QFont font;
|
||||
font.setPixelSize(labelFont);
|
||||
font.setWeight(70);
|
||||
|
||||
p.setFont(font);
|
||||
p.setPen(textColor());
|
||||
p.drawTextLeft(Padding, Padding, "Room settings");
|
||||
p.translate(0, textPadding + QFontMetrics(p.font()).ascent());
|
||||
|
||||
p.save();
|
||||
p.translate(textStartX, 2 * Padding);
|
||||
|
||||
// Draw the name.
|
||||
font.setPixelSize(membersFont);
|
||||
const auto members = QString("%1 members").arg(info_.member_count);
|
||||
|
||||
font.setPixelSize(nameFont);
|
||||
const auto name = QFontMetrics(font).elidedText(
|
||||
QString::fromStdString(info_.name), Qt::ElideRight, availableTextWidth - 4 * Padding);
|
||||
|
||||
font.setWeight(60);
|
||||
p.setFont(font);
|
||||
p.drawTextLeft(0, 0, name);
|
||||
|
||||
// Draw the number of members
|
||||
p.translate(0, QFontMetrics(p.font()).ascent() + 2 * Padding);
|
||||
|
||||
font.setPixelSize(membersFont);
|
||||
font.setWeight(50);
|
||||
p.setFont(font);
|
||||
p.drawTextLeft(0, 0, members);
|
||||
p.restore();
|
||||
|
||||
if (avatar_.isNull()) {
|
||||
font.setPixelSize(AvatarSize / 2);
|
||||
font.setWeight(60);
|
||||
p.setFont(font);
|
||||
|
||||
p.translate(Padding, Padding);
|
||||
p.drawLetterAvatar(utils::firstChar(name),
|
||||
QColor("white"),
|
||||
QColor("black"),
|
||||
AvatarSize + Padding,
|
||||
AvatarSize + Padding,
|
||||
AvatarSize);
|
||||
} else {
|
||||
QRect avatarRegion(Padding, Padding, AvatarSize, AvatarSize);
|
||||
|
||||
QPainterPath pp;
|
||||
pp.addEllipse(avatarRegion.center(), AvatarSize, AvatarSize);
|
||||
|
||||
p.setClipPath(pp);
|
||||
p.drawPixmap(avatarRegion, avatar_);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue