React to externally left and joined rooms, and add "leave room" button in room menu (#75)
* Initial "join room" feature. * React correctly to remotely joined rooms. * Leaving rooms implemented both locally using the room menu in nheko, and reacting properly when leaving a room remotely from another client.
This commit is contained in:
parent
ea296321c9
commit
7ad45d8d64
@ -123,6 +123,8 @@ set(SRC_FILES
|
|||||||
src/TimelineView.cc
|
src/TimelineView.cc
|
||||||
src/TimelineViewManager.cc
|
src/TimelineViewManager.cc
|
||||||
src/InputValidator.cc
|
src/InputValidator.cc
|
||||||
|
src/JoinRoomDialog.cc
|
||||||
|
src/LeaveRoomDialog.cc
|
||||||
src/Login.cc
|
src/Login.cc
|
||||||
src/LoginPage.cc
|
src/LoginPage.cc
|
||||||
src/LogoutDialog.cc
|
src/LogoutDialog.cc
|
||||||
@ -203,9 +205,11 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
include/EmojiPickButton.h
|
include/EmojiPickButton.h
|
||||||
include/ImageItem.h
|
include/ImageItem.h
|
||||||
include/ImageOverlayDialog.h
|
include/ImageOverlayDialog.h
|
||||||
|
include/JoinRoomDialog.h
|
||||||
include/TimelineItem.h
|
include/TimelineItem.h
|
||||||
include/TimelineView.h
|
include/TimelineView.h
|
||||||
include/TimelineViewManager.h
|
include/TimelineViewManager.h
|
||||||
|
include/LeaveRoomDialog.h
|
||||||
include/LoginPage.h
|
include/LoginPage.h
|
||||||
include/LogoutDialog.h
|
include/LogoutDialog.h
|
||||||
include/MainWindow.h
|
include/MainWindow.h
|
||||||
|
@ -37,6 +37,8 @@ public:
|
|||||||
inline void unmount();
|
inline void unmount();
|
||||||
inline QString memberDbName(const QString &roomid);
|
inline QString memberDbName(const QString &roomid);
|
||||||
|
|
||||||
|
void removeRoom(const QString &roomid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
||||||
void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state);
|
void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state);
|
||||||
|
@ -61,6 +61,8 @@ private slots:
|
|||||||
void changeTopRoomInfo(const QString &room_id);
|
void changeTopRoomInfo(const QString &room_id);
|
||||||
void startSync();
|
void startSync();
|
||||||
void logout();
|
void logout();
|
||||||
|
void addRoom(const QString &room_id);
|
||||||
|
void removeRoom(const QString &room_id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
22
include/JoinRoomDialog.h
Normal file
22
include/JoinRoomDialog.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
#include "FlatButton.h"
|
||||||
|
|
||||||
|
class JoinRoomDialog : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
JoinRoomDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void closing(bool isJoining, QString roomAlias);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FlatButton *confirmBtn_;
|
||||||
|
FlatButton *cancelBtn_;
|
||||||
|
|
||||||
|
QLineEdit *roomAliasEdit_;
|
||||||
|
};
|
19
include/LeaveRoomDialog.h
Normal file
19
include/LeaveRoomDialog.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
#include "FlatButton.h"
|
||||||
|
|
||||||
|
class LeaveRoomDialog : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit LeaveRoomDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void closing(bool isLeaving);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FlatButton *confirmBtn_;
|
||||||
|
FlatButton *cancelBtn_;
|
||||||
|
};
|
@ -52,6 +52,8 @@ public:
|
|||||||
void downloadImage(const QString &event_id, const QUrl &url);
|
void downloadImage(const QString &event_id, const QUrl &url);
|
||||||
void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept;
|
void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept;
|
||||||
void uploadImage(const QString &roomid, const QString &filename);
|
void uploadImage(const QString &roomid, const QString &filename);
|
||||||
|
void joinRoom(const QString &roomIdOrAlias);
|
||||||
|
void leaveRoom(const QString &roomId);
|
||||||
|
|
||||||
inline QUrl getHomeServer();
|
inline QUrl getHomeServer();
|
||||||
inline int transactionId();
|
inline int transactionId();
|
||||||
@ -94,6 +96,8 @@ signals:
|
|||||||
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||||
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||||
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
||||||
|
void joinedRoom(const QString &room_id);
|
||||||
|
void leftRoom(const QString &room_id);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onResponse(QNetworkReply *reply);
|
void onResponse(QNetworkReply *reply);
|
||||||
@ -115,6 +119,8 @@ private:
|
|||||||
Sync,
|
Sync,
|
||||||
UserAvatar,
|
UserAvatar,
|
||||||
Versions,
|
Versions,
|
||||||
|
JoinRoom,
|
||||||
|
LeaveRoom,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Response handlers.
|
// Response handlers.
|
||||||
@ -132,6 +138,8 @@ private:
|
|||||||
void onSyncResponse(QNetworkReply *reply);
|
void onSyncResponse(QNetworkReply *reply);
|
||||||
void onUserAvatarResponse(QNetworkReply *reply);
|
void onUserAvatarResponse(QNetworkReply *reply);
|
||||||
void onVersionsResponse(QNetworkReply *reply);
|
void onVersionsResponse(QNetworkReply *reply);
|
||||||
|
void onJoinRoomResponse(QNetworkReply *reply);
|
||||||
|
void onLeaveRoomResponse(QNetworkReply *reply);
|
||||||
|
|
||||||
// Client API prefix.
|
// Client API prefix.
|
||||||
QString clientApiUrl_;
|
QString clientApiUrl_;
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clicked(const QString &room_id);
|
void clicked(const QString &room_id);
|
||||||
|
void leaveRoom(const QString &room_id);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setPressedState(bool state);
|
void setPressedState(bool state);
|
||||||
@ -86,6 +87,7 @@ private:
|
|||||||
|
|
||||||
Menu *menu_;
|
Menu *menu_;
|
||||||
QAction *toggleNotifications_;
|
QAction *toggleNotifications_;
|
||||||
|
QAction *leaveRoom_;
|
||||||
|
|
||||||
QSharedPointer<RoomSettings> roomSettings_;
|
QSharedPointer<RoomSettings> roomSettings_;
|
||||||
|
|
||||||
|
@ -17,12 +17,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "JoinRoomDialog.h"
|
||||||
|
#include "LeaveRoomDialog.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
|
#include "OverlayModal.h"
|
||||||
#include "RoomInfoListItem.h"
|
#include "RoomInfoListItem.h"
|
||||||
#include "RoomState.h"
|
#include "RoomState.h"
|
||||||
#include "Sync.h"
|
#include "Sync.h"
|
||||||
@ -41,6 +45,11 @@ public:
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void addRoom(const QSharedPointer<RoomSettings> &settings,
|
||||||
|
const RoomState &state,
|
||||||
|
const QString &room_id);
|
||||||
|
void removeRoom(const QString &room_id, bool reset);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void roomChanged(const QString &room_id);
|
void roomChanged(const QString &room_id);
|
||||||
void totalUnreadMessageCountUpdated(int count);
|
void totalUnreadMessageCountUpdated(int count);
|
||||||
@ -50,6 +59,9 @@ public slots:
|
|||||||
void highlightSelectedRoom(const QString &room_id);
|
void highlightSelectedRoom(const QString &room_id);
|
||||||
void updateUnreadMessageCount(const QString &roomid, int count);
|
void updateUnreadMessageCount(const QString &roomid, int count);
|
||||||
void updateRoomDescription(const QString &roomid, const DescInfo &info);
|
void updateRoomDescription(const QString &roomid, const DescInfo &info);
|
||||||
|
void closeJoinRoomDialog(bool isJoining, QString roomAlias);
|
||||||
|
void openLeaveRoomDialog(const QString &room_id);
|
||||||
|
void closeLeaveRoomDialog(bool leaving, const QString &room_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void calculateUnreadMessageCount();
|
void calculateUnreadMessageCount();
|
||||||
@ -59,6 +71,14 @@ private:
|
|||||||
QScrollArea *scrollArea_;
|
QScrollArea *scrollArea_;
|
||||||
QWidget *scrollAreaContents_;
|
QWidget *scrollAreaContents_;
|
||||||
|
|
||||||
|
QPushButton *joinRoomButton_;
|
||||||
|
|
||||||
|
OverlayModal *joinRoomModal_;
|
||||||
|
JoinRoomDialog *joinRoomDialog_;
|
||||||
|
|
||||||
|
OverlayModal *leaveRoomModal;
|
||||||
|
LeaveRoomDialog *leaveRoomDialog_;
|
||||||
|
|
||||||
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
||||||
|
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
|
@ -171,15 +171,42 @@ JoinedRoom::timeline() const
|
|||||||
return timeline_;
|
return timeline_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LeftRoom : public Deserializable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline State state() const;
|
||||||
|
inline Timeline timeline() const;
|
||||||
|
|
||||||
|
void deserialize(const QJsonValue &data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
State state_;
|
||||||
|
Timeline timeline_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline State
|
||||||
|
LeftRoom::state() const
|
||||||
|
{
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Timeline
|
||||||
|
LeftRoom::timeline() const
|
||||||
|
{
|
||||||
|
return timeline_;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Add support for invited and left rooms.
|
// TODO: Add support for invited and left rooms.
|
||||||
class Rooms : public Deserializable
|
class Rooms : public Deserializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline QMap<QString, JoinedRoom> join() const;
|
inline QMap<QString, JoinedRoom> join() const;
|
||||||
|
inline QMap<QString, LeftRoom> leave() const;
|
||||||
void deserialize(const QJsonValue &data) override;
|
void deserialize(const QJsonValue &data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<QString, JoinedRoom> join_;
|
QMap<QString, JoinedRoom> join_;
|
||||||
|
QMap<QString, LeftRoom> leave_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QMap<QString, JoinedRoom>
|
inline QMap<QString, JoinedRoom>
|
||||||
@ -188,6 +215,12 @@ Rooms::join() const
|
|||||||
return join_;
|
return join_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QMap<QString, LeftRoom>
|
||||||
|
Rooms::leave() const
|
||||||
|
{
|
||||||
|
return leave_;
|
||||||
|
}
|
||||||
|
|
||||||
class SyncResponse : public Deserializable
|
class SyncResponse : public Deserializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -40,6 +40,10 @@ public:
|
|||||||
void initialize(const Rooms &rooms);
|
void initialize(const Rooms &rooms);
|
||||||
// Empty initialization.
|
// Empty initialization.
|
||||||
void initialize(const QList<QString> &rooms);
|
void initialize(const QList<QString> &rooms);
|
||||||
|
|
||||||
|
void addRoom(const JoinedRoom &room, const QString &room_id);
|
||||||
|
void addRoom(const QString &room_id);
|
||||||
|
|
||||||
void sync(const Rooms &rooms);
|
void sync(const Rooms &rooms);
|
||||||
void clearAll();
|
void clearAll();
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "LeaveRoomDialog.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
#include "OverlayModal.h"
|
||||||
#include "RoomSettings.h"
|
#include "RoomSettings.h"
|
||||||
|
|
||||||
static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a>";
|
static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a>";
|
||||||
@ -51,9 +53,15 @@ public:
|
|||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void leaveRoom();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void closeLeaveRoomDialog(bool leaving);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHBoxLayout *topLayout_;
|
QHBoxLayout *topLayout_;
|
||||||
QVBoxLayout *textLayout_;
|
QVBoxLayout *textLayout_;
|
||||||
@ -65,9 +73,13 @@ private:
|
|||||||
|
|
||||||
QMenu *menu_;
|
QMenu *menu_;
|
||||||
QAction *toggleNotifications_;
|
QAction *toggleNotifications_;
|
||||||
|
QAction *leaveRoom_;
|
||||||
|
|
||||||
FlatButton *settingsBtn_;
|
FlatButton *settingsBtn_;
|
||||||
|
|
||||||
|
OverlayModal *leaveRoomModal;
|
||||||
|
LeaveRoomDialog *leaveRoomDialog_;
|
||||||
|
|
||||||
Avatar *avatar_;
|
Avatar *avatar_;
|
||||||
|
|
||||||
int buttonSize_;
|
int buttonSize_;
|
||||||
|
10
src/Cache.cc
10
src/Cache.cc
@ -153,6 +153,16 @@ Cache::insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cache::removeRoom(const QString &roomid)
|
||||||
|
{
|
||||||
|
auto txn = lmdb::txn::begin(env_, nullptr, 0);
|
||||||
|
|
||||||
|
lmdb::dbi_del(txn, roomDb_, lmdb::val(roomid.toUtf8(), roomid.toUtf8().size()), nullptr);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
QMap<QString, RoomState>
|
QMap<QString, RoomState>
|
||||||
Cache::states()
|
Cache::states()
|
||||||
{
|
{
|
||||||
|
@ -114,6 +114,9 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
connect(user_info_widget_, SIGNAL(logout()), client_.data(), SLOT(logout()));
|
connect(user_info_widget_, SIGNAL(logout()), client_.data(), SLOT(logout()));
|
||||||
connect(client_.data(), SIGNAL(loggedOut()), this, SLOT(logout()));
|
connect(client_.data(), SIGNAL(loggedOut()), this, SLOT(logout()));
|
||||||
|
|
||||||
|
connect(
|
||||||
|
top_bar_, &TopRoomBar::leaveRoom, this, [=]() { client_->leaveRoom(current_room_); });
|
||||||
|
|
||||||
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
||||||
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
||||||
connect(
|
connect(
|
||||||
@ -190,6 +193,14 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
SIGNAL(ownAvatarRetrieved(const QPixmap &)),
|
SIGNAL(ownAvatarRetrieved(const QPixmap &)),
|
||||||
this,
|
this,
|
||||||
SLOT(setOwnAvatar(const QPixmap &)));
|
SLOT(setOwnAvatar(const QPixmap &)));
|
||||||
|
connect(client_.data(),
|
||||||
|
SIGNAL(joinedRoom(const QString &)),
|
||||||
|
this,
|
||||||
|
SLOT(addRoom(const QString &)));
|
||||||
|
connect(client_.data(),
|
||||||
|
SIGNAL(leftRoom(const QString &)),
|
||||||
|
this,
|
||||||
|
SLOT(removeRoom(const QString &)));
|
||||||
|
|
||||||
AvatarProvider::init(client);
|
AvatarProvider::init(client);
|
||||||
}
|
}
|
||||||
@ -293,8 +304,9 @@ ChatPage::syncCompleted(const SyncResponse &response)
|
|||||||
RoomState room_state;
|
RoomState room_state;
|
||||||
|
|
||||||
// Merge the new updates for rooms that we are tracking.
|
// Merge the new updates for rooms that we are tracking.
|
||||||
if (state_manager_.contains(it.key()))
|
if (state_manager_.contains(it.key())) {
|
||||||
room_state = state_manager_[it.key()];
|
room_state = state_manager_[it.key()];
|
||||||
|
}
|
||||||
|
|
||||||
room_state.updateFromEvents(it.value().state().events());
|
room_state.updateFromEvents(it.value().state().events());
|
||||||
room_state.updateFromEvents(it.value().timeline().events());
|
room_state.updateFromEvents(it.value().timeline().events());
|
||||||
@ -307,13 +319,48 @@ ChatPage::syncCompleted(const SyncResponse &response)
|
|||||||
oldState.update(room_state);
|
oldState.update(room_state);
|
||||||
state_manager_.insert(it.key(), oldState);
|
state_manager_.insert(it.key(), oldState);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "New rooms cannot be added after initial sync, yet.";
|
RoomState room_state;
|
||||||
|
|
||||||
|
// Build the current state from the timeline and state events.
|
||||||
|
room_state.updateFromEvents(it.value().state().events());
|
||||||
|
room_state.updateFromEvents(it.value().timeline().events());
|
||||||
|
|
||||||
|
// Remove redundant memberships.
|
||||||
|
room_state.removeLeaveMemberships();
|
||||||
|
|
||||||
|
// Resolve room name and avatar. e.g in case of one-to-one chats.
|
||||||
|
room_state.resolveName();
|
||||||
|
room_state.resolveAvatar();
|
||||||
|
|
||||||
|
updateDisplayNames(room_state);
|
||||||
|
|
||||||
|
state_manager_.insert(it.key(), room_state);
|
||||||
|
settingsManager_.insert(
|
||||||
|
it.key(), QSharedPointer<RoomSettings>(new RoomSettings(it.key())));
|
||||||
|
|
||||||
|
for (const auto membership : room_state.memberships) {
|
||||||
|
auto uid = membership.sender();
|
||||||
|
auto url = membership.content().avatarUrl();
|
||||||
|
|
||||||
|
if (!url.toString().isEmpty())
|
||||||
|
AvatarProvider::setAvatarUrl(uid, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
view_manager_->addRoom(it.value(), it.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.key() == current_room_)
|
if (it.key() == current_room_)
|
||||||
changeTopRoomInfo(it.key());
|
changeTopRoomInfo(it.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto leave = response.rooms().leave();
|
||||||
|
|
||||||
|
for (auto it = leave.constBegin(); it != leave.constEnd(); it++) {
|
||||||
|
if (state_manager_.contains(it.key())) {
|
||||||
|
removeRoom(it.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cache_->setState(response.nextBatch(), state_manager_);
|
cache_->setState(response.nextBatch(), state_manager_);
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
@ -537,6 +584,38 @@ ChatPage::showQuickSwitcher()
|
|||||||
quickSwitcherModal_->fadeIn();
|
quickSwitcherModal_->fadeIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ChatPage::addRoom(const QString &room_id)
|
||||||
|
{
|
||||||
|
if (!state_manager_.contains(room_id)) {
|
||||||
|
RoomState room_state;
|
||||||
|
|
||||||
|
state_manager_.insert(room_id, room_state);
|
||||||
|
settingsManager_.insert(room_id,
|
||||||
|
QSharedPointer<RoomSettings>(new RoomSettings(room_id)));
|
||||||
|
|
||||||
|
room_list_->addRoom(settingsManager_[room_id], state_manager_[room_id], room_id);
|
||||||
|
|
||||||
|
this->changeTopRoomInfo(room_id);
|
||||||
|
room_list_->highlightSelectedRoom(room_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ChatPage::removeRoom(const QString &room_id)
|
||||||
|
{
|
||||||
|
state_manager_.remove(room_id);
|
||||||
|
settingsManager_.remove(room_id);
|
||||||
|
try {
|
||||||
|
cache_->removeRoom(room_id);
|
||||||
|
} catch (const lmdb::error &e) {
|
||||||
|
qCritical() << "The cache couldn't be updated: " << e.what();
|
||||||
|
// TODO: Notify the user.
|
||||||
|
cache_->unmount();
|
||||||
|
}
|
||||||
|
room_list_->removeRoom(room_id, room_id == current_room_);
|
||||||
|
}
|
||||||
|
|
||||||
ChatPage::~ChatPage()
|
ChatPage::~ChatPage()
|
||||||
{
|
{
|
||||||
sync_timer_->stop();
|
sync_timer_->stop();
|
||||||
|
@ -34,12 +34,13 @@ EmojiPanel::EmojiPanel(QWidget *parent)
|
|||||||
, animationDuration_{ 100 }
|
, animationDuration_{ 100 }
|
||||||
, categoryIconSize_{ 20 }
|
, categoryIconSize_{ 20 }
|
||||||
{
|
{
|
||||||
setStyleSheet(
|
setStyleSheet("QWidget {background: #fff; color: #e8e8e8; border: none;}"
|
||||||
"QWidget {background: #fff; color: #e8e8e8; border: none;}"
|
"QScrollBar:vertical { background-color: #fff; width: 8px; margin: 0px "
|
||||||
"QScrollBar:vertical { background-color: #fff; width: 8px; margin: 0px 2px 0 2px; }"
|
"2px 0 2px; }"
|
||||||
"QScrollBar::handle:vertical { background-color: #d6dde3; min-height: 20px; }"
|
"QScrollBar::handle:vertical { background-color: #d6dde3; min-height: "
|
||||||
"QScrollBar::add-line:vertical { border: none; background: none; }"
|
"20px; }"
|
||||||
"QScrollBar::sub-line:vertical { border: none; background: none; }");
|
"QScrollBar::add-line:vertical { border: none; background: none; }"
|
||||||
|
"QScrollBar::sub-line:vertical { border: none; background: none; }");
|
||||||
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
setAttribute(Qt::WA_ShowWithoutActivating, true);
|
setAttribute(Qt::WA_ShowWithoutActivating, true);
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
const QRegExp MXID_REGEX("@[A-Za-z0-9._%+-]+:[A-Za-z0-9.-]{1,126}\\.[A-Za-z]{1,63}");
|
const QRegExp MXID_REGEX("@[A-Za-z0-9._%+-]+:[A-Za-z0-9.-]{1,126}\\.[A-Za-z]{1,63}");
|
||||||
const QRegExp LOCALPART_REGEX("[A-za-z0-9._%+-]{3,}");
|
const QRegExp LOCALPART_REGEX("[A-za-z0-9._%+-]{3,}");
|
||||||
const QRegExp PASSWORD_REGEX(".{8,}");
|
const QRegExp PASSWORD_REGEX(".{8,}");
|
||||||
const QRegExp DOMAIN_REGEX(
|
const QRegExp DOMAIN_REGEX("(?!\\-)(?:[a-zA-Z\\d\\-]{0,62}[a-zA-Z\\d]\\.){1,"
|
||||||
"(?!\\-)(?:[a-zA-Z\\d\\-]{0,62}[a-zA-Z\\d]\\.){1,126}(?!\\d+)[a-zA-Z\\d]{1,63}");
|
"126}(?!\\d+)[a-zA-Z\\d]{1,63}");
|
||||||
|
|
||||||
QRegExpValidator InputValidator::Id(MXID_REGEX);
|
QRegExpValidator InputValidator::Id(MXID_REGEX);
|
||||||
QRegExpValidator InputValidator::Localpart(LOCALPART_REGEX);
|
QRegExpValidator InputValidator::Localpart(LOCALPART_REGEX);
|
||||||
|
49
src/JoinRoomDialog.cc
Normal file
49
src/JoinRoomDialog.cc
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "JoinRoomDialog.h"
|
||||||
|
#include "Theme.h"
|
||||||
|
|
||||||
|
JoinRoomDialog::JoinRoomDialog(QWidget *parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
{
|
||||||
|
setMaximumSize(400, 400);
|
||||||
|
setStyleSheet("background-color: #fff");
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
layout->setSpacing(30);
|
||||||
|
layout->setMargin(20);
|
||||||
|
|
||||||
|
auto buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->setSpacing(0);
|
||||||
|
buttonLayout->setMargin(0);
|
||||||
|
|
||||||
|
confirmBtn_ = new FlatButton("JOIN", this);
|
||||||
|
confirmBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
||||||
|
cancelBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
buttonLayout->addStretch(1);
|
||||||
|
buttonLayout->addWidget(confirmBtn_);
|
||||||
|
buttonLayout->addWidget(cancelBtn_);
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(conf::headerFontSize);
|
||||||
|
|
||||||
|
auto label = new QLabel(tr("Room alias to join:"), this);
|
||||||
|
label->setFont(font);
|
||||||
|
label->setStyleSheet("color: #333333");
|
||||||
|
|
||||||
|
roomAliasEdit_ = new QLineEdit(this);
|
||||||
|
|
||||||
|
layout->addWidget(label);
|
||||||
|
layout->addWidget(roomAliasEdit_);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
connect(confirmBtn_, &QPushButton::clicked, [=]() {
|
||||||
|
emit closing(true, roomAliasEdit_->text());
|
||||||
|
});
|
||||||
|
connect(cancelBtn_, &QPushButton::clicked, [=]() { emit closing(false, nullptr); });
|
||||||
|
}
|
44
src/LeaveRoomDialog.cc
Normal file
44
src/LeaveRoomDialog.cc
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "LeaveRoomDialog.h"
|
||||||
|
#include "Theme.h"
|
||||||
|
|
||||||
|
LeaveRoomDialog::LeaveRoomDialog(QWidget *parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
{
|
||||||
|
setMaximumSize(400, 400);
|
||||||
|
setStyleSheet("background-color: #fff");
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
layout->setSpacing(30);
|
||||||
|
layout->setMargin(20);
|
||||||
|
|
||||||
|
auto buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->setSpacing(0);
|
||||||
|
buttonLayout->setMargin(0);
|
||||||
|
|
||||||
|
confirmBtn_ = new FlatButton("LEAVE", this);
|
||||||
|
confirmBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
||||||
|
cancelBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
buttonLayout->addStretch(1);
|
||||||
|
buttonLayout->addWidget(confirmBtn_);
|
||||||
|
buttonLayout->addWidget(cancelBtn_);
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(conf::headerFontSize);
|
||||||
|
|
||||||
|
auto label = new QLabel(tr("Are you sure you want to leave?"), this);
|
||||||
|
label->setFont(font);
|
||||||
|
label->setStyleSheet("color: #333333");
|
||||||
|
|
||||||
|
layout->addWidget(label);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
connect(confirmBtn_, &QPushButton::clicked, [=]() { emit closing(true); });
|
||||||
|
connect(cancelBtn_, &QPushButton::clicked, [=]() { emit closing(false); });
|
||||||
|
}
|
@ -462,6 +462,40 @@ MatrixClient::onMessagesResponse(QNetworkReply *reply)
|
|||||||
emit messagesRetrieved(room_id, msgs);
|
emit messagesRetrieved(room_id, msgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::onJoinRoomResponse(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
if (status == 0 || status >= 400) {
|
||||||
|
qWarning() << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = reply->readAll();
|
||||||
|
QJsonDocument response = QJsonDocument::fromJson(data);
|
||||||
|
QString room_id = response.object()["room_id"].toString();
|
||||||
|
emit joinedRoom(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::onLeaveRoomResponse(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
if (status == 0 || status >= 400) {
|
||||||
|
qWarning() << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString room_id = reply->property("room_id").toString();
|
||||||
|
emit leftRoom(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MatrixClient::onResponse(QNetworkReply *reply)
|
MatrixClient::onResponse(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
@ -508,6 +542,12 @@ MatrixClient::onResponse(QNetworkReply *reply)
|
|||||||
case Endpoint::Messages:
|
case Endpoint::Messages:
|
||||||
onMessagesResponse(reply);
|
onMessagesResponse(reply);
|
||||||
break;
|
break;
|
||||||
|
case Endpoint::JoinRoom:
|
||||||
|
onJoinRoomResponse(reply);
|
||||||
|
break;
|
||||||
|
case Endpoint::LeaveRoom:
|
||||||
|
onLeaveRoomResponse(reply);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -571,7 +611,8 @@ void
|
|||||||
MatrixClient::sync() noexcept
|
MatrixClient::sync() noexcept
|
||||||
{
|
{
|
||||||
QJsonObject filter{ { "room",
|
QJsonObject filter{ { "room",
|
||||||
QJsonObject{ { "ephemeral", QJsonObject{ { "limit", 0 } } } } },
|
QJsonObject{ { "include_leave", true },
|
||||||
|
{ "ephemeral", QJsonObject{ { "limit", 0 } } } } },
|
||||||
{ "presence", QJsonObject{ { "limit", 0 } } } };
|
{ "presence", QJsonObject{ { "limit", 0 } } } };
|
||||||
|
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
@ -842,3 +883,38 @@ MatrixClient::uploadImage(const QString &roomid, const QString &filename)
|
|||||||
reply->setProperty("room_id", roomid);
|
reply->setProperty("room_id", roomid);
|
||||||
reply->setProperty("filename", filename);
|
reply->setProperty("filename", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::joinRoom(const QString &roomIdOrAlias)
|
||||||
|
{
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("access_token", token_);
|
||||||
|
|
||||||
|
QUrl endpoint(server_);
|
||||||
|
endpoint.setPath(clientApiUrl_ + QString("/join/%1").arg(roomIdOrAlias));
|
||||||
|
endpoint.setQuery(query);
|
||||||
|
|
||||||
|
QNetworkRequest request(endpoint);
|
||||||
|
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
QNetworkReply *reply = post(request, "{}");
|
||||||
|
reply->setProperty("endpoint", static_cast<int>(Endpoint::JoinRoom));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatrixClient::leaveRoom(const QString &roomId)
|
||||||
|
{
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("access_token", token_);
|
||||||
|
|
||||||
|
QUrl endpoint(server_);
|
||||||
|
endpoint.setPath(clientApiUrl_ + QString("/rooms/%1/leave").arg(roomId));
|
||||||
|
endpoint.setQuery(query);
|
||||||
|
|
||||||
|
QNetworkRequest request(endpoint);
|
||||||
|
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
QNetworkReply *reply = post(request, "{}");
|
||||||
|
reply->setProperty("room_id", roomId);
|
||||||
|
reply->setProperty("endpoint", static_cast<int>(Endpoint::LeaveRoom));
|
||||||
|
}
|
||||||
|
@ -53,12 +53,15 @@ RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
|||||||
menu_ = new Menu(this);
|
menu_ = new Menu(this);
|
||||||
|
|
||||||
toggleNotifications_ = new QAction(notificationText(), this);
|
toggleNotifications_ = new QAction(notificationText(), this);
|
||||||
|
|
||||||
connect(toggleNotifications_, &QAction::triggered, this, [=]() {
|
connect(toggleNotifications_, &QAction::triggered, this, [=]() {
|
||||||
roomSettings_->toggleNotifications();
|
roomSettings_->toggleNotifications();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
leaveRoom_ = new QAction(tr("Leave room"), this);
|
||||||
|
connect(leaveRoom_, &QAction::triggered, this, [=]() { emit leaveRoom(room_id); });
|
||||||
|
|
||||||
menu_->addAction(toggleNotifications_);
|
menu_->addAction(toggleNotifications_);
|
||||||
|
menu_->addAction(leaveRoom_);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "RoomInfoListItem.h"
|
#include "RoomInfoListItem.h"
|
||||||
#include "RoomList.h"
|
#include "RoomList.h"
|
||||||
#include "Sync.h"
|
#include "Sync.h"
|
||||||
@ -69,6 +70,36 @@ RoomList::clear()
|
|||||||
rooms_.clear();
|
rooms_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomList::addRoom(const QSharedPointer<RoomSettings> &settings,
|
||||||
|
const RoomState &state,
|
||||||
|
const QString &room_id)
|
||||||
|
{
|
||||||
|
RoomInfoListItem *room_item = new RoomInfoListItem(settings, state, room_id, scrollArea_);
|
||||||
|
connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
|
||||||
|
connect(room_item, &RoomInfoListItem::leaveRoom, this, &RoomList::openLeaveRoomDialog);
|
||||||
|
|
||||||
|
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||||
|
|
||||||
|
client_->fetchRoomAvatar(room_id, state.getAvatar());
|
||||||
|
|
||||||
|
contentsLayout_->insertWidget(0, room_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomList::removeRoom(const QString &room_id, bool reset)
|
||||||
|
{
|
||||||
|
rooms_.remove(room_id);
|
||||||
|
|
||||||
|
if (rooms_.isEmpty() || !reset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto first_room = rooms_.first();
|
||||||
|
first_room->setPressedState(true);
|
||||||
|
|
||||||
|
emit roomChanged(rooms_.firstKey());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RoomList::updateUnreadMessageCount(const QString &roomid, int count)
|
RoomList::updateUnreadMessageCount(const QString &roomid, int count)
|
||||||
{
|
{
|
||||||
@ -116,6 +147,7 @@ RoomList::setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &set
|
|||||||
new RoomInfoListItem(settings[room_id], state, room_id, scrollArea_);
|
new RoomInfoListItem(settings[room_id], state, room_id, scrollArea_);
|
||||||
connect(
|
connect(
|
||||||
room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
|
room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
|
||||||
|
connect(room_item, &RoomInfoListItem::leaveRoom, this, &RoomList::openLeaveRoomDialog);
|
||||||
|
|
||||||
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||||
|
|
||||||
@ -132,6 +164,21 @@ RoomList::setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &set
|
|||||||
emit roomChanged(rooms_.firstKey());
|
emit roomChanged(rooms_.firstKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomList::openLeaveRoomDialog(const QString &room_id)
|
||||||
|
{
|
||||||
|
leaveRoomDialog_ = new LeaveRoomDialog(this);
|
||||||
|
connect(leaveRoomDialog_,
|
||||||
|
&LeaveRoomDialog::closing, this,
|
||||||
|
[=](bool leaving) { closeLeaveRoomDialog(leaving, room_id); });
|
||||||
|
|
||||||
|
leaveRoomModal = new OverlayModal(MainWindow::instance(), leaveRoomDialog_);
|
||||||
|
leaveRoomModal->setDuration(0);
|
||||||
|
leaveRoomModal->setColor(QColor(55, 55, 55, 170));
|
||||||
|
|
||||||
|
leaveRoomModal->fadeIn();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RoomList::sync(const QMap<QString, RoomState> &states)
|
RoomList::sync(const QMap<QString, RoomState> &states)
|
||||||
{
|
{
|
||||||
@ -139,9 +186,10 @@ RoomList::sync(const QMap<QString, RoomState> &states)
|
|||||||
auto room_id = it.key();
|
auto room_id = it.key();
|
||||||
auto state = it.value();
|
auto state = it.value();
|
||||||
|
|
||||||
// TODO: Add the new room to the list.
|
if (!rooms_.contains(room_id)) {
|
||||||
if (!rooms_.contains(room_id))
|
addRoom(
|
||||||
continue;
|
QSharedPointer<RoomSettings>(new RoomSettings(room_id)), state, room_id);
|
||||||
|
}
|
||||||
|
|
||||||
auto room = rooms_[room_id];
|
auto room = rooms_[room_id];
|
||||||
|
|
||||||
@ -203,3 +251,23 @@ RoomList::updateRoomDescription(const QString &roomid, const DescInfo &info)
|
|||||||
|
|
||||||
rooms_.value(roomid)->setDescriptionMessage(info);
|
rooms_.value(roomid)->setDescriptionMessage(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomList::closeJoinRoomDialog(bool isJoining, QString roomAlias)
|
||||||
|
{
|
||||||
|
joinRoomModal_->fadeOut();
|
||||||
|
|
||||||
|
if (isJoining) {
|
||||||
|
client_->joinRoom(roomAlias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomList::closeLeaveRoomDialog(bool leaving, const QString &room_id)
|
||||||
|
{
|
||||||
|
leaveRoomModal->fadeOut();
|
||||||
|
|
||||||
|
if (leaving) {
|
||||||
|
client_->leaveRoom(room_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
41
src/Sync.cc
41
src/Sync.cc
@ -90,7 +90,6 @@ Rooms::deserialize(const QJsonValue &data)
|
|||||||
|
|
||||||
for (auto it = join.constBegin(); it != join.constEnd(); it++) {
|
for (auto it = join.constBegin(); it != join.constEnd(); it++) {
|
||||||
JoinedRoom tmp_room;
|
JoinedRoom tmp_room;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tmp_room.deserialize(it.value());
|
tmp_room.deserialize(it.value());
|
||||||
join_.insert(it.key(), tmp_room);
|
join_.insert(it.key(), tmp_room);
|
||||||
@ -112,7 +111,19 @@ Rooms::deserialize(const QJsonValue &data)
|
|||||||
if (!object.value("leave").isObject()) {
|
if (!object.value("leave").isObject()) {
|
||||||
throw DeserializationException("rooms/leave must be a JSON object");
|
throw DeserializationException("rooms/leave must be a JSON object");
|
||||||
}
|
}
|
||||||
// TODO: Implement leave handling
|
auto leave = object.value("leave").toObject();
|
||||||
|
|
||||||
|
for (auto it = leave.constBegin(); it != leave.constEnd(); it++) {
|
||||||
|
LeftRoom tmp_room;
|
||||||
|
|
||||||
|
try {
|
||||||
|
tmp_room.deserialize(it.value());
|
||||||
|
leave_.insert(it.key(), tmp_room);
|
||||||
|
} catch (DeserializationException &e) {
|
||||||
|
qWarning() << e.what();
|
||||||
|
qWarning() << "Skipping malformed object for room" << it.key();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +195,32 @@ JoinedRoom::deserialize(const QJsonValue &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LeftRoom::deserialize(const QJsonValue &data)
|
||||||
|
{
|
||||||
|
if (!data.isObject())
|
||||||
|
throw DeserializationException("LeftRoom is not a JSON object");
|
||||||
|
|
||||||
|
QJsonObject object = data.toObject();
|
||||||
|
|
||||||
|
if (!object.contains("state"))
|
||||||
|
throw DeserializationException("leave/state is missing");
|
||||||
|
|
||||||
|
if (!object.contains("timeline"))
|
||||||
|
throw DeserializationException("leave/timeline is missing");
|
||||||
|
|
||||||
|
if (!object.value("state").isObject())
|
||||||
|
throw DeserializationException("leave/state should be an object");
|
||||||
|
|
||||||
|
QJsonObject state = object.value("state").toObject();
|
||||||
|
|
||||||
|
if (!state.contains("events"))
|
||||||
|
throw DeserializationException("leave/state/events is missing");
|
||||||
|
|
||||||
|
state_.deserialize(state.value("events"));
|
||||||
|
timeline_.deserialize(object.value("timeline"));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Event::deserialize(const QJsonValue &data)
|
Event::deserialize(const QJsonValue &data)
|
||||||
{
|
{
|
||||||
|
@ -101,19 +101,7 @@ void
|
|||||||
TimelineViewManager::initialize(const Rooms &rooms)
|
TimelineViewManager::initialize(const Rooms &rooms)
|
||||||
{
|
{
|
||||||
for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
|
for (auto it = rooms.join().constBegin(); it != rooms.join().constEnd(); it++) {
|
||||||
auto roomid = it.key();
|
addRoom(it.value(), it.key());
|
||||||
|
|
||||||
// Create a history view with the room events.
|
|
||||||
TimelineView *view = new TimelineView(it.value().timeline(), client_, it.key());
|
|
||||||
views_.insert(it.key(), QSharedPointer<TimelineView>(view));
|
|
||||||
|
|
||||||
connect(view,
|
|
||||||
&TimelineView::updateLastTimelineMessage,
|
|
||||||
this,
|
|
||||||
&TimelineViewManager::updateRoomsLastMessage);
|
|
||||||
|
|
||||||
// Add the view in the widget stack.
|
|
||||||
addWidget(view);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,20 +109,42 @@ void
|
|||||||
TimelineViewManager::initialize(const QList<QString> &rooms)
|
TimelineViewManager::initialize(const QList<QString> &rooms)
|
||||||
{
|
{
|
||||||
for (const auto &roomid : rooms) {
|
for (const auto &roomid : rooms) {
|
||||||
// Create a history view without any events.
|
addRoom(roomid);
|
||||||
TimelineView *view = new TimelineView(client_, roomid);
|
|
||||||
views_.insert(roomid, QSharedPointer<TimelineView>(view));
|
|
||||||
|
|
||||||
connect(view,
|
|
||||||
&TimelineView::updateLastTimelineMessage,
|
|
||||||
this,
|
|
||||||
&TimelineViewManager::updateRoomsLastMessage);
|
|
||||||
|
|
||||||
// Add the view in the widget stack.
|
|
||||||
addWidget(view);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::addRoom(const JoinedRoom &room, const QString &room_id)
|
||||||
|
{
|
||||||
|
// Create a history view with the room events.
|
||||||
|
TimelineView *view = new TimelineView(room.timeline(), client_, room_id);
|
||||||
|
views_.insert(room_id, QSharedPointer<TimelineView>(view));
|
||||||
|
|
||||||
|
connect(view,
|
||||||
|
&TimelineView::updateLastTimelineMessage,
|
||||||
|
this,
|
||||||
|
&TimelineViewManager::updateRoomsLastMessage);
|
||||||
|
|
||||||
|
// Add the view in the widget stack.
|
||||||
|
addWidget(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::addRoom(const QString &room_id)
|
||||||
|
{
|
||||||
|
// Create a history view without any events.
|
||||||
|
TimelineView *view = new TimelineView(client_, room_id);
|
||||||
|
views_.insert(room_id, QSharedPointer<TimelineView>(view));
|
||||||
|
|
||||||
|
connect(view,
|
||||||
|
&TimelineView::updateLastTimelineMessage,
|
||||||
|
this,
|
||||||
|
&TimelineViewManager::updateRoomsLastMessage);
|
||||||
|
|
||||||
|
// Add the view in the widget stack.
|
||||||
|
addWidget(view);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::sync(const Rooms &rooms)
|
TimelineViewManager::sync(const Rooms &rooms)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "TopRoomBar.h"
|
#include "TopRoomBar.h"
|
||||||
|
|
||||||
TopRoomBar::TopRoomBar(QWidget *parent)
|
TopRoomBar::TopRoomBar(QWidget *parent)
|
||||||
@ -83,7 +84,21 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||||||
roomSettings_->toggleNotifications();
|
roomSettings_->toggleNotifications();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
leaveRoom_ = new QAction(tr("Leave room"), this);
|
||||||
|
connect(leaveRoom_, &QAction::triggered, this, [=]() {
|
||||||
|
leaveRoomDialog_ = new LeaveRoomDialog(this);
|
||||||
|
connect(
|
||||||
|
leaveRoomDialog_, SIGNAL(closing(bool)), this, SLOT(closeLeaveRoomDialog(bool)));
|
||||||
|
|
||||||
|
leaveRoomModal = new OverlayModal(MainWindow::instance(), leaveRoomDialog_);
|
||||||
|
leaveRoomModal->setDuration(100);
|
||||||
|
leaveRoomModal->setColor(QColor(55, 55, 55, 170));
|
||||||
|
|
||||||
|
leaveRoomModal->fadeIn();
|
||||||
|
});
|
||||||
|
|
||||||
menu_->addAction(toggleNotifications_);
|
menu_->addAction(toggleNotifications_);
|
||||||
|
menu_->addAction(leaveRoom_);
|
||||||
|
|
||||||
connect(settingsBtn_, &QPushButton::clicked, this, [=]() {
|
connect(settingsBtn_, &QPushButton::clicked, this, [=]() {
|
||||||
if (roomSettings_->isNotificationsEnabled())
|
if (roomSettings_->isNotificationsEnabled())
|
||||||
@ -99,6 +114,16 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||||||
setLayout(topLayout_);
|
setLayout(topLayout_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TopRoomBar::closeLeaveRoomDialog(bool leaving)
|
||||||
|
{
|
||||||
|
leaveRoomModal->fadeOut();
|
||||||
|
|
||||||
|
if (leaving) {
|
||||||
|
emit leaveRoom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TopRoomBar::updateRoomAvatarFromName(const QString &name)
|
TopRoomBar::updateRoomAvatarFromName(const QString &name)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user