mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 03:00:46 +03:00
parent
101bf47443
commit
f11044b5eb
12 changed files with 352 additions and 93 deletions
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <QDir>
|
||||
#include <lmdb++.h>
|
||||
#include <mtx/responses.hpp>
|
||||
|
||||
class RoomState;
|
||||
|
||||
|
@ -33,10 +34,15 @@ public:
|
|||
QString nextBatchToken() const;
|
||||
QMap<QString, RoomState> states();
|
||||
|
||||
using Invites = std::map<std::string, mtx::responses::InvitedRoom>;
|
||||
Invites invites();
|
||||
void setInvites(const Invites &invites);
|
||||
|
||||
void deleteData();
|
||||
void unmount() { isMounted_ = false; };
|
||||
|
||||
void removeRoom(const QString &roomid);
|
||||
void removeInvite(const QString &roomid);
|
||||
void setup();
|
||||
|
||||
bool isFormatValid();
|
||||
|
@ -49,6 +55,7 @@ private:
|
|||
lmdb::env env_;
|
||||
lmdb::dbi stateDb_;
|
||||
lmdb::dbi roomDb_;
|
||||
lmdb::dbi invitesDb_;
|
||||
|
||||
bool isMounted_;
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ private slots:
|
|||
void logout();
|
||||
void addRoom(const QString &room_id);
|
||||
void removeRoom(const QString &room_id);
|
||||
void removeInvite(const QString &room_id);
|
||||
|
||||
private:
|
||||
using UserID = QString;
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <QSharedPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <mtx/responses.hpp>
|
||||
|
||||
#include "RoomState.h"
|
||||
|
||||
class Menu;
|
||||
|
@ -52,12 +54,17 @@ class RoomInfoListItem : public QWidget
|
|||
Q_PROPERTY(QColor highlightedSubtitleColor READ highlightedSubtitleColor WRITE
|
||||
setHighlightedSubtitleColor)
|
||||
|
||||
Q_PROPERTY(QColor btnColor READ btnColor WRITE setBtnColor)
|
||||
Q_PROPERTY(QColor btnTextColor READ btnTextColor WRITE setBtnTextColor)
|
||||
|
||||
public:
|
||||
RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
||||
RoomState state,
|
||||
QString room_id,
|
||||
QWidget *parent = 0);
|
||||
|
||||
RoomInfoListItem(QString room_id, mtx::responses::InvitedRoom room, QWidget *parent = 0);
|
||||
|
||||
~RoomInfoListItem();
|
||||
|
||||
void updateUnreadMessageCount(int count);
|
||||
|
@ -71,35 +78,36 @@ public:
|
|||
void setAvatar(const QImage &avatar_image);
|
||||
void setDescriptionMessage(const DescInfo &info);
|
||||
|
||||
inline QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
|
||||
inline QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
|
||||
inline QColor backgroundColor() const { return backgroundColor_; }
|
||||
QColor highlightedBackgroundColor() const { return highlightedBackgroundColor_; }
|
||||
QColor hoverBackgroundColor() const { return hoverBackgroundColor_; }
|
||||
QColor backgroundColor() const { return backgroundColor_; }
|
||||
|
||||
inline QColor highlightedTitleColor() const { return highlightedTitleColor_; }
|
||||
inline QColor highlightedSubtitleColor() const { return highlightedSubtitleColor_; }
|
||||
QColor highlightedTitleColor() const { return highlightedTitleColor_; }
|
||||
QColor highlightedSubtitleColor() const { return highlightedSubtitleColor_; }
|
||||
|
||||
inline QColor titleColor() const { return titleColor_; }
|
||||
inline QColor subtitleColor() const { return subtitleColor_; }
|
||||
QColor titleColor() const { return titleColor_; }
|
||||
QColor subtitleColor() const { return subtitleColor_; }
|
||||
QColor btnColor() const { return btnColor_; }
|
||||
QColor btnTextColor() const { return btnTextColor_; }
|
||||
|
||||
inline void setHighlightedBackgroundColor(QColor &color)
|
||||
{
|
||||
highlightedBackgroundColor_ = color;
|
||||
}
|
||||
inline void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; }
|
||||
inline void setBackgroundColor(QColor &color) { backgroundColor_ = color; }
|
||||
void setHighlightedBackgroundColor(QColor &color) { highlightedBackgroundColor_ = color; }
|
||||
void setHoverBackgroundColor(QColor &color) { hoverBackgroundColor_ = color; }
|
||||
void setBackgroundColor(QColor &color) { backgroundColor_ = color; }
|
||||
|
||||
inline void setHighlightedTitleColor(QColor &color) { highlightedTitleColor_ = color; }
|
||||
inline void setHighlightedSubtitleColor(QColor &color)
|
||||
{
|
||||
highlightedSubtitleColor_ = color;
|
||||
}
|
||||
void setHighlightedTitleColor(QColor &color) { highlightedTitleColor_ = color; }
|
||||
void setHighlightedSubtitleColor(QColor &color) { highlightedSubtitleColor_ = color; }
|
||||
|
||||
inline void setTitleColor(QColor &color) { titleColor_ = color; }
|
||||
inline void setSubtitleColor(QColor &color) { subtitleColor_ = color; }
|
||||
void setTitleColor(QColor &color) { titleColor_ = color; }
|
||||
void setSubtitleColor(QColor &color) { subtitleColor_ = color; }
|
||||
|
||||
void setBtnColor(QColor &color) { btnColor_ = color; }
|
||||
void setBtnTextColor(QColor &color) { btnTextColor_ = color; }
|
||||
|
||||
signals:
|
||||
void clicked(const QString &room_id);
|
||||
void leaveRoom(const QString &room_id);
|
||||
void acceptInvite(const QString &room_id);
|
||||
void declineInvite(const QString &room_id);
|
||||
|
||||
public slots:
|
||||
void setPressedState(bool state);
|
||||
|
@ -111,15 +119,33 @@ protected:
|
|||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
|
||||
private:
|
||||
QString notificationText();
|
||||
void init(QWidget *parent);
|
||||
QString roomName()
|
||||
{
|
||||
if (roomType_ == RoomType::Joined)
|
||||
return state_.getName();
|
||||
|
||||
const int Padding = 7;
|
||||
const int IconSize = 48;
|
||||
return roomName_;
|
||||
}
|
||||
|
||||
QString notificationText();
|
||||
|
||||
RippleOverlay *ripple_overlay_;
|
||||
|
||||
enum class RoomType
|
||||
{
|
||||
Joined,
|
||||
Invited,
|
||||
};
|
||||
|
||||
RoomType roomType_ = RoomType::Joined;
|
||||
|
||||
// State information for the joined rooms.
|
||||
RoomState state_;
|
||||
|
||||
// State information for the invited rooms.
|
||||
mtx::responses::InvitedRoom invitedRoom_;
|
||||
|
||||
QString roomId_;
|
||||
QString roomName_;
|
||||
|
||||
|
@ -135,7 +161,6 @@ private:
|
|||
|
||||
bool isPressed_ = false;
|
||||
|
||||
int maxHeight_;
|
||||
int unreadMsgCount_ = 0;
|
||||
|
||||
QColor highlightedBackgroundColor_;
|
||||
|
@ -147,4 +172,10 @@ private:
|
|||
|
||||
QColor titleColor_;
|
||||
QColor subtitleColor_;
|
||||
|
||||
QColor btnColor_;
|
||||
QColor btnTextColor_;
|
||||
|
||||
QRectF acceptBtnRegion_;
|
||||
QRectF declineBtnRegion_;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include <mtx.hpp>
|
||||
|
||||
#include "dialogs/LeaveRoom.h"
|
||||
|
||||
class LeaveRoomDialog;
|
||||
|
@ -47,17 +49,21 @@ public:
|
|||
const QMap<QString, RoomState> &states);
|
||||
void sync(const QMap<QString, RoomState> &states,
|
||||
QMap<QString, QSharedPointer<RoomSettings>> &settings);
|
||||
void syncInvites(const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
|
||||
|
||||
void clear();
|
||||
|
||||
void addRoom(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||
const RoomState &state,
|
||||
const QString &room_id);
|
||||
void addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRoom &room);
|
||||
void removeRoom(const QString &room_id, bool reset);
|
||||
|
||||
signals:
|
||||
void roomChanged(const QString &room_id);
|
||||
void totalUnreadMessageCountUpdated(int count);
|
||||
void acceptInvite(const QString &room_id);
|
||||
void declineInvite(const QString &room_id);
|
||||
|
||||
public slots:
|
||||
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ff5a9c887af1a8cffd13876abcf4c079a8525bd3
|
||||
Subproject commit 582c6956c464e80f738c57ded239c3fb613f1c24
|
|
@ -49,6 +49,9 @@ RoomInfoListItem {
|
|||
|
||||
qproperty-highlightedTitleColor: #e4e5e8;
|
||||
qproperty-highlightedSubtitleColor: #e4e5e8;
|
||||
|
||||
qproperty-btnColor: #414A59;
|
||||
qproperty-btnTextColor: white;
|
||||
}
|
||||
|
||||
LoadingIndicator {
|
||||
|
|
|
@ -47,6 +47,9 @@ RoomInfoListItem {
|
|||
|
||||
qproperty-highlightedTitleColor: white;
|
||||
qproperty-highlightedSubtitleColor: white;
|
||||
|
||||
qproperty-btnColor: #ccc;
|
||||
qproperty-btnTextColor: #333;
|
||||
}
|
||||
|
||||
#ChatPageLoadSpinner {
|
||||
|
|
|
@ -55,6 +55,9 @@ RoomInfoListItem {
|
|||
|
||||
qproperty-highlightedTitleColor: palette(light);
|
||||
qproperty-highlightedSubtitleColor: palette(light);
|
||||
|
||||
qproperty-btnColor: palette(light);
|
||||
qproperty-btnTextColor: palette(text);
|
||||
}
|
||||
|
||||
LoadingIndicator {
|
||||
|
|
95
src/Cache.cc
95
src/Cache.cc
|
@ -33,6 +33,7 @@ Cache::Cache(const QString &userId)
|
|||
: env_{nullptr}
|
||||
, stateDb_{0}
|
||||
, roomDb_{0}
|
||||
, invitesDb_{0}
|
||||
, isMounted_{false}
|
||||
, userId_{userId}
|
||||
{}
|
||||
|
@ -86,9 +87,10 @@ Cache::setup()
|
|||
env_.open(statePath.toStdString().c_str());
|
||||
}
|
||||
|
||||
auto txn = lmdb::txn::begin(env_);
|
||||
stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE);
|
||||
roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
|
||||
auto txn = lmdb::txn::begin(env_);
|
||||
stateDb_ = lmdb::dbi::open(txn, "state", MDB_CREATE);
|
||||
roomDb_ = lmdb::dbi::open(txn, "rooms", MDB_CREATE);
|
||||
invitesDb_ = lmdb::dbi::open(txn, "invites", MDB_CREATE);
|
||||
|
||||
txn.commit();
|
||||
|
||||
|
@ -174,6 +176,20 @@ Cache::removeRoom(const QString &roomid)
|
|||
txn.commit();
|
||||
}
|
||||
|
||||
void
|
||||
Cache::removeInvite(const QString &room_id)
|
||||
{
|
||||
if (!isMounted_)
|
||||
return;
|
||||
|
||||
auto txn = lmdb::txn::begin(env_, nullptr, 0);
|
||||
|
||||
lmdb::dbi_del(
|
||||
txn, invitesDb_, lmdb::val(room_id.toUtf8(), room_id.toUtf8().size()), nullptr);
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
QMap<QString, RoomState>
|
||||
Cache::states()
|
||||
{
|
||||
|
@ -310,3 +326,76 @@ Cache::setCurrentFormat()
|
|||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
std::map<std::string, mtx::responses::InvitedRoom>
|
||||
Cache::invites()
|
||||
{
|
||||
std::map<std::string, mtx::responses::InvitedRoom> invites;
|
||||
|
||||
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
|
||||
auto cursor = lmdb::cursor::open(txn, invitesDb_);
|
||||
|
||||
std::string room_id;
|
||||
std::string payload;
|
||||
|
||||
mtx::responses::InvitedRoom state;
|
||||
|
||||
while (cursor.get(room_id, payload, MDB_NEXT)) {
|
||||
state = nlohmann::json::parse(payload);
|
||||
invites.emplace(room_id, state);
|
||||
}
|
||||
|
||||
if (invites.size() > 0)
|
||||
qDebug() << "Retrieved" << invites.size() << "invites";
|
||||
|
||||
cursor.close();
|
||||
|
||||
txn.commit();
|
||||
|
||||
return invites;
|
||||
}
|
||||
|
||||
void
|
||||
Cache::setInvites(const std::map<std::string, mtx::responses::InvitedRoom> &invites)
|
||||
{
|
||||
if (!isMounted_)
|
||||
return;
|
||||
|
||||
using Aliases = mtx::events::StrippedEvent<mtx::events::state::Aliases>;
|
||||
using Avatar = mtx::events::StrippedEvent<mtx::events::state::Avatar>;
|
||||
using Member = mtx::events::StrippedEvent<mtx::events::state::Member>;
|
||||
using Name = mtx::events::StrippedEvent<mtx::events::state::Name>;
|
||||
using Topic = mtx::events::StrippedEvent<mtx::events::state::Topic>;
|
||||
|
||||
try {
|
||||
auto txn = lmdb::txn::begin(env_);
|
||||
|
||||
for (auto it = invites.cbegin(); it != invites.cend(); ++it) {
|
||||
nlohmann::json j;
|
||||
|
||||
for (const auto &e : it->second.invite_state) {
|
||||
if (mpark::holds_alternative<Name>(e)) {
|
||||
j["invite_state"]["events"].push_back(mpark::get<Name>(e));
|
||||
} else if (mpark::holds_alternative<Topic>(e)) {
|
||||
j["invite_state"]["events"].push_back(mpark::get<Topic>(e));
|
||||
} else if (mpark::holds_alternative<Avatar>(e)) {
|
||||
j["invite_state"]["events"].push_back(
|
||||
mpark::get<Avatar>(e));
|
||||
} else if (mpark::holds_alternative<Aliases>(e)) {
|
||||
j["invite_state"]["events"].push_back(
|
||||
mpark::get<Aliases>(e));
|
||||
} else if (mpark::holds_alternative<Member>(e)) {
|
||||
j["invite_state"]["events"].push_back(
|
||||
mpark::get<Member>(e));
|
||||
}
|
||||
}
|
||||
|
||||
lmdb::dbi_put(txn, invitesDb_, lmdb::val(it->first), lmdb::val(j.dump()));
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
} catch (const lmdb::error &e) {
|
||||
qCritical() << "setInvitedRooms: " << e.what();
|
||||
unmount();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,9 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
connect(
|
||||
room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView);
|
||||
|
||||
connect(room_list_, &RoomList::acceptInvite, client_.data(), &MatrixClient::joinRoom);
|
||||
connect(room_list_, &RoomList::declineInvite, client_.data(), &MatrixClient::leaveRoom);
|
||||
|
||||
connect(view_manager_,
|
||||
&TimelineViewManager::clearRoomMessageCount,
|
||||
room_list_,
|
||||
|
@ -266,8 +269,9 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||
this,
|
||||
&ChatPage::updateOwnProfileInfo);
|
||||
connect(client_.data(), &MatrixClient::ownAvatarRetrieved, this, &ChatPage::setOwnAvatar);
|
||||
connect(client_.data(), &MatrixClient::joinedRoom, this, [=]() {
|
||||
connect(client_.data(), &MatrixClient::joinedRoom, this, [=](const QString &room_id) {
|
||||
emit showNotification("You joined the room.");
|
||||
removeInvite(room_id);
|
||||
});
|
||||
connect(client_.data(), &MatrixClient::invitedUser, this, [=](QString, QString user) {
|
||||
emit showNotification(QString("Invited user %1").arg(user));
|
||||
|
@ -400,8 +404,11 @@ ChatPage::syncCompleted(const mtx::responses::Sync &response)
|
|||
|
||||
auto stateDiff = generateMembershipDifference(response.rooms.join, state_manager_);
|
||||
QtConcurrent::run(cache_.data(), &Cache::setState, nextBatchToken, stateDiff);
|
||||
QtConcurrent::run(cache_.data(), &Cache::setInvites, response.rooms.invite);
|
||||
|
||||
room_list_->sync(state_manager_, settingsManager_);
|
||||
room_list_->syncInvites(response.rooms.invite);
|
||||
|
||||
view_manager_->sync(response.rooms);
|
||||
|
||||
client_->setNextBatchToken(nextBatchToken);
|
||||
|
@ -445,12 +452,14 @@ ChatPage::initialSyncCompleted(const mtx::responses::Sync &response)
|
|||
&Cache::setState,
|
||||
QString::fromStdString(response.next_batch),
|
||||
state_manager_);
|
||||
QtConcurrent::run(cache_.data(), &Cache::setInvites, response.rooms.invite);
|
||||
|
||||
// Populate timelines with messages.
|
||||
view_manager_->initialize(response.rooms);
|
||||
|
||||
// Initialize room list.
|
||||
room_list_->setInitialRooms(settingsManager_, state_manager_);
|
||||
room_list_->syncInvites(response.rooms.invite);
|
||||
|
||||
client_->setNextBatchToken(QString::fromStdString(response.next_batch));
|
||||
client_->sync();
|
||||
|
@ -552,6 +561,7 @@ ChatPage::loadStateFromCache()
|
|||
|
||||
// Initialize room list from the restored state and settings.
|
||||
room_list_->setInitialRooms(settingsManager_, state_manager_);
|
||||
room_list_->syncInvites(cache_->invites());
|
||||
|
||||
// Check periodically if the timelines have been loaded.
|
||||
consensusTimer_->start(CONSENSUS_TIMEOUT);
|
||||
|
@ -629,6 +639,7 @@ ChatPage::removeRoom(const QString &room_id)
|
|||
settingsManager_.remove(room_id);
|
||||
try {
|
||||
cache_->removeRoom(room_id);
|
||||
cache_->removeInvite(room_id);
|
||||
} catch (const lmdb::error &e) {
|
||||
qCritical() << "The cache couldn't be updated: " << e.what();
|
||||
// TODO: Notify the user.
|
||||
|
@ -638,6 +649,21 @@ ChatPage::removeRoom(const QString &room_id)
|
|||
room_list_->removeRoom(room_id, room_id == current_room_);
|
||||
}
|
||||
|
||||
void
|
||||
ChatPage::removeInvite(const QString &room_id)
|
||||
{
|
||||
try {
|
||||
cache_->removeInvite(room_id);
|
||||
} catch (const lmdb::error &e) {
|
||||
qCritical() << "The cache couldn't be updated: " << e.what();
|
||||
// TODO: Notify the user.
|
||||
cache_->unmount();
|
||||
cache_->deleteData();
|
||||
}
|
||||
|
||||
room_list_->removeRoom(room_id, room_id == current_room_);
|
||||
}
|
||||
|
||||
void
|
||||
ChatPage::updateTypingUsers(const QString &roomid, const std::vector<std::string> &user_ids)
|
||||
{
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#include <variant.hpp>
|
||||
|
||||
#include "Config.h"
|
||||
#include "Menu.h"
|
||||
#include "Ripple.h"
|
||||
|
@ -26,6 +29,44 @@
|
|||
#include "RoomSettings.h"
|
||||
#include "Theme.h"
|
||||
|
||||
constexpr int Padding = 7;
|
||||
constexpr int IconSize = 48;
|
||||
constexpr int MaxHeight = IconSize + 2 * Padding;
|
||||
|
||||
constexpr int InviteBtnX = IconSize + 2 * Padding;
|
||||
constexpr int InviteBtnY = IconSize / 2 + Padding;
|
||||
|
||||
void
|
||||
RoomInfoListItem::init(QWidget *parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
setMouseTracking(true);
|
||||
setAttribute(Qt::WA_Hover);
|
||||
|
||||
setFixedHeight(MaxHeight);
|
||||
|
||||
QPainterPath path;
|
||||
path.addRect(0, 0, parent->width(), height());
|
||||
|
||||
ripple_overlay_ = new RippleOverlay(this);
|
||||
ripple_overlay_->setClipPath(path);
|
||||
ripple_overlay_->setClipping(true);
|
||||
}
|
||||
|
||||
RoomInfoListItem::RoomInfoListItem(QString room_id,
|
||||
mtx::responses::InvitedRoom room,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, roomType_{RoomType::Invited}
|
||||
, invitedRoom_{std::move(room)}
|
||||
, roomId_{std::move(room_id)}
|
||||
{
|
||||
init(parent);
|
||||
|
||||
roomAvatar_ = QString::fromStdString(invitedRoom_.avatar());
|
||||
roomName_ = QString::fromStdString(invitedRoom_.name());
|
||||
}
|
||||
|
||||
RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
||||
RoomState state,
|
||||
QString room_id,
|
||||
|
@ -35,21 +76,9 @@ RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
|||
, roomId_(room_id)
|
||||
, roomSettings_{settings}
|
||||
, isPressed_(false)
|
||||
, maxHeight_(IconSize + 2 * Padding)
|
||||
, unreadMsgCount_(0)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
setMouseTracking(true);
|
||||
setAttribute(Qt::WA_Hover);
|
||||
|
||||
setFixedHeight(maxHeight_);
|
||||
|
||||
QPainterPath path;
|
||||
path.addRect(0, 0, parent->width(), height());
|
||||
|
||||
ripple_overlay_ = new RippleOverlay(this);
|
||||
ripple_overlay_->setClipPath(path);
|
||||
ripple_overlay_->setClipping(true);
|
||||
init(parent);
|
||||
|
||||
menu_ = new Menu(this);
|
||||
|
||||
|
@ -99,82 +128,100 @@ RoomInfoListItem::paintEvent(QPaintEvent *event)
|
|||
font.setPixelSize(conf::fontSize);
|
||||
QFontMetrics metrics(font);
|
||||
|
||||
QPen titlePen(titleColor_);
|
||||
QPen subtitlePen(subtitleColor_);
|
||||
|
||||
if (isPressed_) {
|
||||
p.fillRect(rect(), highlightedBackgroundColor_);
|
||||
titlePen.setColor(highlightedTitleColor_);
|
||||
subtitlePen.setColor(highlightedSubtitleColor_);
|
||||
} else if (underMouse()) {
|
||||
p.fillRect(rect(), hoverBackgroundColor_);
|
||||
} else {
|
||||
p.fillRect(rect(), backgroundColor_);
|
||||
}
|
||||
|
||||
// p.setPen(QColor("#333"));
|
||||
|
||||
QRect avatarRegion(Padding, Padding, IconSize, IconSize);
|
||||
|
||||
// Description line with the default font.
|
||||
int bottom_y = maxHeight_ - Padding - Padding / 3 - metrics.ascent() / 2;
|
||||
int bottom_y = MaxHeight - Padding - Padding / 3 - metrics.ascent() / 2;
|
||||
|
||||
if (width() > ui::sidebar::SmallSize) {
|
||||
if (isPressed_) {
|
||||
QPen pen(highlightedTitleColor_);
|
||||
p.setPen(pen);
|
||||
} else {
|
||||
QPen pen(titleColor_);
|
||||
p.setPen(pen);
|
||||
}
|
||||
font.setPixelSize(conf::roomlist::fonts::heading);
|
||||
p.setFont(font);
|
||||
p.setPen(titlePen);
|
||||
|
||||
// Name line.
|
||||
QFontMetrics fontNameMetrics(font);
|
||||
int top_y = 2 * Padding + fontNameMetrics.ascent() / 2;
|
||||
|
||||
auto name = metrics.elidedText(
|
||||
state_.getName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8);
|
||||
roomName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8);
|
||||
p.drawText(QPoint(2 * Padding + IconSize, top_y), name);
|
||||
|
||||
if (isPressed_) {
|
||||
QPen pen(highlightedSubtitleColor_);
|
||||
p.setPen(pen);
|
||||
} else {
|
||||
QPen pen(subtitleColor_);
|
||||
p.setPen(pen);
|
||||
}
|
||||
if (roomType_ == RoomType::Joined) {
|
||||
font.setPixelSize(conf::fontSize);
|
||||
p.setFont(font);
|
||||
p.setPen(subtitlePen);
|
||||
|
||||
font.setPixelSize(conf::fontSize);
|
||||
p.setFont(font);
|
||||
auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5;
|
||||
|
||||
auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5;
|
||||
// The limit is the space between the end of the avatar and the start of the
|
||||
// timestamp.
|
||||
int usernameLimit =
|
||||
std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20);
|
||||
auto userName =
|
||||
metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit);
|
||||
|
||||
// The limit is the space between the end of the avatar and the start of the
|
||||
// timestamp.
|
||||
int usernameLimit =
|
||||
std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20);
|
||||
auto userName =
|
||||
metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit);
|
||||
|
||||
font.setBold(true);
|
||||
p.setFont(font);
|
||||
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName);
|
||||
|
||||
int nameWidth = QFontMetrics(font).width(userName);
|
||||
|
||||
font.setBold(false);
|
||||
p.setFont(font);
|
||||
|
||||
// The limit is the space between the end of the username and the start of
|
||||
// the timestamp.
|
||||
int descriptionLimit =
|
||||
std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5);
|
||||
auto description =
|
||||
metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
|
||||
p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), description);
|
||||
|
||||
// We either show the bubble or the last message timestamp.
|
||||
if (unreadMsgCount_ == 0) {
|
||||
font.setBold(true);
|
||||
p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y),
|
||||
lastMsgInfo_.timestamp);
|
||||
p.setFont(font);
|
||||
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName);
|
||||
|
||||
int nameWidth = QFontMetrics(font).width(userName);
|
||||
|
||||
font.setBold(false);
|
||||
p.setFont(font);
|
||||
|
||||
// The limit is the space between the end of the username and the start of
|
||||
// the timestamp.
|
||||
int descriptionLimit = std::max(
|
||||
0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5);
|
||||
auto description =
|
||||
metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
|
||||
p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y),
|
||||
description);
|
||||
|
||||
// We either show the bubble or the last message timestamp.
|
||||
if (unreadMsgCount_ == 0) {
|
||||
font.setBold(true);
|
||||
p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y),
|
||||
lastMsgInfo_.timestamp);
|
||||
}
|
||||
} else {
|
||||
int btnWidth = (width() - IconSize - 6 * Padding) / 2;
|
||||
|
||||
acceptBtnRegion_ = QRectF(InviteBtnX, InviteBtnY, btnWidth, 20);
|
||||
declineBtnRegion_ =
|
||||
QRectF(InviteBtnX + btnWidth + 2 * Padding, InviteBtnY, btnWidth, 20);
|
||||
|
||||
QPainterPath acceptPath;
|
||||
acceptPath.addRoundedRect(acceptBtnRegion_, 10, 10);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.fillPath(acceptPath, btnColor_);
|
||||
p.drawPath(acceptPath);
|
||||
|
||||
QPainterPath declinePath;
|
||||
declinePath.addRoundedRect(declineBtnRegion_, 10, 10);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.fillPath(declinePath, btnColor_);
|
||||
p.drawPath(declinePath);
|
||||
|
||||
p.setPen(QPen(btnTextColor_));
|
||||
p.setFont(font);
|
||||
p.drawText(acceptBtnRegion_, Qt::AlignCenter, tr("Accept"));
|
||||
p.drawText(declineBtnRegion_, Qt::AlignCenter, tr("Decline"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,8 +243,7 @@ RoomInfoListItem::paintEvent(QPaintEvent *event)
|
|||
p.setFont(font);
|
||||
p.setPen(QColor("#333"));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawText(
|
||||
avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.getName()[0]));
|
||||
p.drawText(avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(roomName()[0]));
|
||||
} else {
|
||||
p.save();
|
||||
|
||||
|
@ -289,6 +335,9 @@ RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event)
|
|||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
if (roomType_ == RoomType::Invited)
|
||||
return;
|
||||
|
||||
toggleNotifications_->setText(notificationText());
|
||||
menu_->popup(event->globalPos());
|
||||
}
|
||||
|
@ -301,6 +350,18 @@ RoomInfoListItem::mousePressEvent(QMouseEvent *event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (roomType_ == RoomType::Invited) {
|
||||
const auto point = event->pos();
|
||||
|
||||
if (acceptBtnRegion_.contains(point))
|
||||
emit acceptInvite(roomId_);
|
||||
|
||||
if (declineBtnRegion_.contains(point))
|
||||
emit declineInvite(roomId_);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
emit clicked(roomId_);
|
||||
|
||||
setPressedState(true);
|
||||
|
|
|
@ -287,3 +287,32 @@ RoomList::paintEvent(QPaintEvent *)
|
|||
QPainter p(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::syncInvites(const std::map<std::string, mtx::responses::InvitedRoom> &rooms)
|
||||
{
|
||||
for (auto it = rooms.cbegin(); it != rooms.cend(); ++it) {
|
||||
const auto room_id = QString::fromStdString(it->first);
|
||||
|
||||
if (!rooms_.contains(room_id))
|
||||
addInvitedRoom(room_id, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RoomList::addInvitedRoom(const QString &room_id, const mtx::responses::InvitedRoom &room)
|
||||
{
|
||||
auto room_item = new RoomInfoListItem(room_id, room, scrollArea_);
|
||||
connect(room_item, &RoomInfoListItem::acceptInvite, this, &RoomList::acceptInvite);
|
||||
connect(room_item, &RoomInfoListItem::declineInvite, this, &RoomList::declineInvite);
|
||||
|
||||
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||
|
||||
auto avatarUrl = QString::fromStdString(room.avatar());
|
||||
|
||||
if (!avatarUrl.isEmpty())
|
||||
client_->fetchRoomAvatar(room_id, avatarUrl);
|
||||
|
||||
int pos = contentsLayout_->count() - 1;
|
||||
contentsLayout_->insertWidget(pos, room_item);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue