mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Port top bar to Qml
Also fixes some resize issues with stupid workarounds to our resize logic. This really needs to be cleaned up at some point!
This commit is contained in:
parent
c4e4938d35
commit
640b0ee405
12 changed files with 267 additions and 448 deletions
|
@ -304,7 +304,6 @@ set(SRC_FILES
|
||||||
src/SideBarActions.cpp
|
src/SideBarActions.cpp
|
||||||
src/Splitter.cpp
|
src/Splitter.cpp
|
||||||
src/TextInputWidget.cpp
|
src/TextInputWidget.cpp
|
||||||
src/TopRoomBar.cpp
|
|
||||||
src/TrayIcon.cpp
|
src/TrayIcon.cpp
|
||||||
src/UserInfoWidget.cpp
|
src/UserInfoWidget.cpp
|
||||||
src/UserSettingsPage.cpp
|
src/UserSettingsPage.cpp
|
||||||
|
@ -512,7 +511,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/SideBarActions.h
|
src/SideBarActions.h
|
||||||
src/Splitter.h
|
src/Splitter.h
|
||||||
src/TextInputWidget.h
|
src/TextInputWidget.h
|
||||||
src/TopRoomBar.h
|
|
||||||
src/TrayIcon.h
|
src/TrayIcon.h
|
||||||
src/UserInfoWidget.h
|
src/UserInfoWidget.h
|
||||||
src/UserSettingsPage.h
|
src/UserSettingsPage.h
|
||||||
|
|
|
@ -50,6 +50,8 @@ Rectangle {
|
||||||
anchors.bottom: avatar.bottom
|
anchors.bottom: avatar.bottom
|
||||||
anchors.right: avatar.right
|
anchors.right: avatar.right
|
||||||
|
|
||||||
|
visible: !!userid
|
||||||
|
|
||||||
height: avatar.height / 6
|
height: avatar.height / 6
|
||||||
width: height
|
width: height
|
||||||
radius: settings.avatarCircles ? height / 2 : height / 4
|
radius: settings.avatarCircles ? height / 2 : height / 4
|
||||||
|
|
|
@ -115,6 +115,112 @@ Page {
|
||||||
z: 3
|
z: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
Rectangle {
|
||||||
|
id: topBar
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
implicitHeight: topLayout.height + 16
|
||||||
|
z: 3
|
||||||
|
|
||||||
|
color: colors.base
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: topLayout
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
//Layout.margins: 8
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: backToRoomsButton
|
||||||
|
|
||||||
|
Layout.column: 0
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.rowSpan: 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
visible: timelineManager.isNarrowView
|
||||||
|
|
||||||
|
image: ":/icons/icons/ui/angle-pointing-to-left.png"
|
||||||
|
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Back to room list")
|
||||||
|
|
||||||
|
onClicked: timelineManager.backToRooms()
|
||||||
|
}
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
Layout.column: 1
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.rowSpan: 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
width: avatarSize
|
||||||
|
height: avatarSize
|
||||||
|
url: chat.model.roomAvatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
|
displayName: chat.model.roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.column: 2
|
||||||
|
Layout.row: 0
|
||||||
|
|
||||||
|
font.pointSize: fontMetrics.font.pointSize * 1.1
|
||||||
|
text: chat.model.roomName
|
||||||
|
}
|
||||||
|
MatrixText {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.column: 2
|
||||||
|
Layout.row: 1
|
||||||
|
text: chat.model.roomTopic
|
||||||
|
Layout.maximumHeight: fontMetrics.lineSpacing * 2 // show 2 lines
|
||||||
|
clip: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: roomOptionsButton
|
||||||
|
|
||||||
|
Layout.column: 3
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.rowSpan: 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
image: ":/icons/icons/ui/vertical-ellipsis.png"
|
||||||
|
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Room options")
|
||||||
|
|
||||||
|
onClicked: roomOptionsMenu.popup(roomOptionsButton)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: roomOptionsMenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Invite users")
|
||||||
|
onTriggered: timelineManager.openInviteUsersDialog();
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Members")
|
||||||
|
onTriggered: timelineManager.openMemberListDialog();
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Leave room")
|
||||||
|
onTriggered: timelineManager.openLeaveRoomDialog();
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Settings")
|
||||||
|
onTriggered: timelineManager.openRoomSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: chat
|
id: chat
|
||||||
|
|
||||||
|
@ -122,13 +228,8 @@ Page {
|
||||||
|
|
||||||
cacheBuffer: 400
|
cacheBuffer: 400
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
Layout.fillWidth: true
|
||||||
anchors.top: parent.top
|
Layout.fillHeight: true
|
||||||
anchors.bottom: chatFooter.top
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
anchors.leftMargin: 4
|
|
||||||
anchors.rightMargin: scrollbar.width
|
|
||||||
|
|
||||||
model: timelineManager.timeline
|
model: timelineManager.timeline
|
||||||
|
|
||||||
|
@ -167,10 +268,6 @@ Page {
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar {
|
ScrollBar.vertical: ScrollBar {
|
||||||
id: scrollbar
|
id: scrollbar
|
||||||
parent: chat.parent
|
|
||||||
anchors.top: chat.top
|
|
||||||
anchors.right: chat.right
|
|
||||||
anchors.bottom: chat.bottom
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
@ -178,9 +275,9 @@ Page {
|
||||||
|
|
||||||
onCountChanged: if (atYEnd) model.currentIndex = 0 // Mark last event as read, since we are at the bottom
|
onCountChanged: if (atYEnd) model.currentIndex = 0 // Mark last event as read, since we are at the bottom
|
||||||
|
|
||||||
property int delegateMaxWidth: (settings.timelineMaxWidth > 100 && (parent.width - settings.timelineMaxWidth) > 32) ? settings.timelineMaxWidth : (parent.width - 32)
|
property int delegateMaxWidth: (settings.timelineMaxWidth > 100 && (parent.width - settings.timelineMaxWidth) > scrollbar.width*2) ? settings.timelineMaxWidth : (parent.width - scrollbar.width*2)
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Item {
|
||||||
// This would normally be previousSection, but our model's order is inverted.
|
// This would normally be previousSection, but our model's order is inverted.
|
||||||
property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1
|
property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1
|
||||||
|
|
||||||
|
@ -189,7 +286,6 @@ Page {
|
||||||
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
|
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
|
||||||
width: chat.delegateMaxWidth
|
width: chat.delegateMaxWidth
|
||||||
height: section ? section.height + timelinerow.height : timelinerow.height
|
height: section ? section.height + timelinerow.height : timelinerow.height
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
TimelineRow {
|
TimelineRow {
|
||||||
id: timelinerow
|
id: timelinerow
|
||||||
|
@ -309,17 +405,13 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
id: chatFooter
|
id: chatFooter
|
||||||
|
|
||||||
height: Math.max(fontMetrics.height * 1.2, footerContent.height)
|
implicitHeight: Math.max(fontMetrics.height * 1.2, footerContent.height)
|
||||||
anchors.left: parent.left
|
Layout.fillWidth: true
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
z: 3
|
z: 3
|
||||||
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: footerContent
|
id: footerContent
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -382,4 +474,5 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
105
src/ChatPage.cpp
105
src/ChatPage.cpp
|
@ -37,7 +37,6 @@
|
||||||
#include "SideBarActions.h"
|
#include "SideBarActions.h"
|
||||||
#include "Splitter.h"
|
#include "Splitter.h"
|
||||||
#include "TextInputWidget.h"
|
#include "TextInputWidget.h"
|
||||||
#include "TopRoomBar.h"
|
|
||||||
#include "UserInfoWidget.h"
|
#include "UserInfoWidget.h"
|
||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
@ -126,10 +125,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
contentLayout_->setSpacing(0);
|
contentLayout_->setSpacing(0);
|
||||||
contentLayout_->setMargin(0);
|
contentLayout_->setMargin(0);
|
||||||
|
|
||||||
top_bar_ = new TopRoomBar(this);
|
|
||||||
view_manager_ = new TimelineViewManager(userSettings_, &callManager_, this);
|
view_manager_ = new TimelineViewManager(userSettings_, &callManager_, this);
|
||||||
|
|
||||||
contentLayout_->addWidget(top_bar_);
|
|
||||||
contentLayout_->addWidget(view_manager_->getWidget());
|
contentLayout_->addWidget(view_manager_->getWidget());
|
||||||
|
|
||||||
activeCallBar_ = new ActiveCallBar(this);
|
activeCallBar_ = new ActiveCallBar(this);
|
||||||
|
@ -181,30 +178,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
room_list_->previousRoom();
|
room_list_->previousRoom();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(top_bar_, &TopRoomBar::mentionsClicked, this, [this](const QPoint &mentionsPos) {
|
|
||||||
if (user_mentions_popup_->isVisible()) {
|
|
||||||
user_mentions_popup_->hide();
|
|
||||||
} else {
|
|
||||||
showNotificationsDialog(mentionsPos);
|
|
||||||
http::client()->notifications(
|
|
||||||
1000,
|
|
||||||
"",
|
|
||||||
"highlight",
|
|
||||||
[this, mentionsPos](const mtx::responses::Notifications &res,
|
|
||||||
mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
nhlog::net()->warn(
|
|
||||||
"failed to retrieve notifications: {} ({})",
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit highlightedNotifsRetrieved(std::move(res), mentionsPos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
|
connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
|
||||||
connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
|
connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
|
||||||
if (http::client()->access_token().empty()) {
|
if (http::client()->access_token().empty()) {
|
||||||
|
@ -226,8 +199,9 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
|
|
||||||
connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
|
connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
|
||||||
|
|
||||||
connect(top_bar_, &TopRoomBar::showRoomList, splitter, &Splitter::showFullRoomList);
|
connect(
|
||||||
connect(top_bar_, &TopRoomBar::inviteUsers, this, [this](QStringList users) {
|
view_manager_, &TimelineViewManager::showRoomList, splitter, &Splitter::showFullRoomList);
|
||||||
|
connect(view_manager_, &TimelineViewManager::inviteUsers, this, [this](QStringList users) {
|
||||||
const auto room_id = current_room_.toStdString();
|
const auto room_id = current_room_.toStdString();
|
||||||
|
|
||||||
for (int ii = 0; ii < users.size(); ++ii) {
|
for (int ii = 0; ii < users.size(); ++ii) {
|
||||||
|
@ -252,7 +226,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::stopTyping);
|
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::stopTyping);
|
||||||
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
|
||||||
connect(room_list_, &RoomList::roomChanged, splitter, &Splitter::showChatView);
|
connect(room_list_, &RoomList::roomChanged, splitter, &Splitter::showChatView);
|
||||||
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
|
||||||
connect(
|
connect(
|
||||||
|
@ -487,8 +460,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
|
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
this, &ChatPage::updateGroupsInfo, communitiesList_, &CommunitiesList::setCommunities);
|
this, &ChatPage::updateGroupsInfo, communitiesList_, &CommunitiesList::setCommunities);
|
||||||
|
|
||||||
|
@ -588,11 +559,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
});
|
});
|
||||||
connect(this, &ChatPage::syncRoomlist, room_list_, &RoomList::sync);
|
connect(this, &ChatPage::syncRoomlist, room_list_, &RoomList::sync);
|
||||||
connect(this, &ChatPage::syncTags, communitiesList_, &CommunitiesList::syncTags);
|
connect(this, &ChatPage::syncTags, communitiesList_, &CommunitiesList::syncTags);
|
||||||
connect(
|
|
||||||
this, &ChatPage::syncTopBar, this, [this](const std::map<QString, RoomInfo> &updates) {
|
|
||||||
if (updates.find(currentRoom()) != updates.end())
|
|
||||||
changeTopRoomInfo(currentRoom());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Callbacks to update the user info (top left corner of the page).
|
// Callbacks to update the user info (top left corner of the page).
|
||||||
connect(this, &ChatPage::setUserAvatar, user_info_widget_, &UserInfoWidget::setAvatar);
|
connect(this, &ChatPage::setUserAvatar, user_info_widget_, &UserInfoWidget::setAvatar);
|
||||||
|
@ -657,7 +623,6 @@ void
|
||||||
ChatPage::resetUI()
|
ChatPage::resetUI()
|
||||||
{
|
{
|
||||||
room_list_->clear();
|
room_list_->clear();
|
||||||
top_bar_->reset();
|
|
||||||
user_info_widget_->reset();
|
user_info_widget_->reset();
|
||||||
view_manager_->clearAll();
|
view_manager_->clearAll();
|
||||||
|
|
||||||
|
@ -786,46 +751,6 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
|
||||||
tryInitialSync();
|
tryInitialSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ChatPage::updateTopBarAvatar(const QString &roomid, const QString &img)
|
|
||||||
{
|
|
||||||
if (current_room_ != roomid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
top_bar_->updateRoomAvatar(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ChatPage::changeTopRoomInfo(const QString &room_id)
|
|
||||||
{
|
|
||||||
if (room_id.isEmpty()) {
|
|
||||||
nhlog::ui()->warn("cannot switch to empty room_id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto room_info = cache::getRoomInfo({room_id.toStdString()});
|
|
||||||
|
|
||||||
if (room_info.find(room_id) == room_info.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto name = QString::fromStdString(room_info[room_id].name);
|
|
||||||
const auto avatar_url = QString::fromStdString(room_info[room_id].avatar_url);
|
|
||||||
|
|
||||||
top_bar_->updateRoomName(name);
|
|
||||||
top_bar_->updateRoomTopic(QString::fromStdString(room_info[room_id].topic));
|
|
||||||
|
|
||||||
top_bar_->updateRoomAvatarFromName(name);
|
|
||||||
if (!avatar_url.isEmpty())
|
|
||||||
top_bar_->updateRoomAvatar(avatar_url);
|
|
||||||
|
|
||||||
} catch (const lmdb::error &e) {
|
|
||||||
nhlog::ui()->error("failed to change top bar room info: {}", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
current_room_ = room_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ChatPage::showUnreadMessageNotification(int count)
|
ChatPage::showUnreadMessageNotification(int count)
|
||||||
{
|
{
|
||||||
|
@ -1070,7 +995,6 @@ ChatPage::handleSyncResponse(mtx::responses::Sync res)
|
||||||
|
|
||||||
auto updates = cache::roomUpdates(res);
|
auto updates = cache::roomUpdates(res);
|
||||||
|
|
||||||
emit syncTopBar(updates);
|
|
||||||
emit syncRoomlist(updates);
|
emit syncRoomlist(updates);
|
||||||
|
|
||||||
emit syncUI(res.rooms);
|
emit syncUI(res.rooms);
|
||||||
|
@ -1481,9 +1405,12 @@ ChatPage::getProfileInfo()
|
||||||
void
|
void
|
||||||
ChatPage::hideSideBars()
|
ChatPage::hideSideBars()
|
||||||
{
|
{
|
||||||
communitiesList_->hide();
|
// Don't hide side bar, if we are currently only showing the side bar!
|
||||||
sideBar_->hide();
|
if (view_manager_->getWidget()->isVisible()) {
|
||||||
top_bar_->enableBackButton();
|
communitiesList_->hide();
|
||||||
|
sideBar_->hide();
|
||||||
|
}
|
||||||
|
view_manager_->enableBackButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1493,23 +1420,19 @@ ChatPage::showSideBars()
|
||||||
communitiesList_->show();
|
communitiesList_->show();
|
||||||
|
|
||||||
sideBar_->show();
|
sideBar_->show();
|
||||||
top_bar_->disableBackButton();
|
view_manager_->disableBackButton();
|
||||||
|
content_->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
ChatPage::timelineWidth()
|
ChatPage::timelineWidth()
|
||||||
{
|
{
|
||||||
int sidebarWidth = sideBar_->size().width();
|
int sidebarWidth = sideBar_->minimumSize().width();
|
||||||
sidebarWidth += communitiesList_->size().width();
|
sidebarWidth += communitiesList_->minimumSize().width();
|
||||||
|
nhlog::ui()->info("timelineWidth: {}", size().width() - sidebarWidth);
|
||||||
|
|
||||||
return size().width() - sidebarWidth;
|
return size().width() - sidebarWidth;
|
||||||
}
|
}
|
||||||
bool
|
|
||||||
ChatPage::isSideBarExpanded()
|
|
||||||
{
|
|
||||||
const auto sz = splitter::calculateSidebarSizes(QFont{});
|
|
||||||
return sideBar_->size().width() > sz.normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ChatPage::initiateLogout()
|
ChatPage::initiateLogout()
|
||||||
|
|
|
@ -49,7 +49,6 @@ class SideBarActions;
|
||||||
class Splitter;
|
class Splitter;
|
||||||
class TextInputWidget;
|
class TextInputWidget;
|
||||||
class TimelineViewManager;
|
class TimelineViewManager;
|
||||||
class TopRoomBar;
|
|
||||||
class UserInfoWidget;
|
class UserInfoWidget;
|
||||||
class UserSettings;
|
class UserSettings;
|
||||||
|
|
||||||
|
@ -82,7 +81,6 @@ public:
|
||||||
|
|
||||||
//! Calculate the width of the message timeline.
|
//! Calculate the width of the message timeline.
|
||||||
uint64_t timelineWidth();
|
uint64_t timelineWidth();
|
||||||
bool isSideBarExpanded();
|
|
||||||
//! Hide the room & group list (if it was visible).
|
//! Hide the room & group list (if it was visible).
|
||||||
void hideSideBars();
|
void hideSideBars();
|
||||||
//! Show the room/group list (if it was visible).
|
//! Show the room/group list (if it was visible).
|
||||||
|
@ -150,7 +148,6 @@ signals:
|
||||||
void syncUI(const mtx::responses::Rooms &rooms);
|
void syncUI(const mtx::responses::Rooms &rooms);
|
||||||
void syncRoomlist(const std::map<QString, RoomInfo> &updates);
|
void syncRoomlist(const std::map<QString, RoomInfo> &updates);
|
||||||
void syncTags(const std::map<QString, RoomInfo> &updates);
|
void syncTags(const std::map<QString, RoomInfo> &updates);
|
||||||
void syncTopBar(const std::map<QString, RoomInfo> &updates);
|
|
||||||
void dropToLoginPageCb(const QString &msg);
|
void dropToLoginPageCb(const QString &msg);
|
||||||
|
|
||||||
void notifyMessage(const QString &roomid,
|
void notifyMessage(const QString &roomid,
|
||||||
|
@ -167,8 +164,6 @@ signals:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void showUnreadMessageNotification(int count);
|
void showUnreadMessageNotification(int count);
|
||||||
void updateTopBarAvatar(const QString &roomid, const QString &img);
|
|
||||||
void changeTopRoomInfo(const QString &room_id);
|
|
||||||
void logout();
|
void logout();
|
||||||
void removeRoom(const QString &room_id);
|
void removeRoom(const QString &room_id);
|
||||||
void dropToLoginPage(const QString &msg);
|
void dropToLoginPage(const QString &msg);
|
||||||
|
@ -239,7 +234,6 @@ private:
|
||||||
TimelineViewManager *view_manager_;
|
TimelineViewManager *view_manager_;
|
||||||
SideBarActions *sidebarActions_;
|
SideBarActions *sidebarActions_;
|
||||||
|
|
||||||
TopRoomBar *top_bar_;
|
|
||||||
TextInputWidget *text_input_;
|
TextInputWidget *text_input_;
|
||||||
ActiveCallBar *activeCallBar_;
|
ActiveCallBar *activeCallBar_;
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,8 @@ MainWindow::adjustSideBars()
|
||||||
const uint64_t timelineWidth = chat_page_->timelineWidth();
|
const uint64_t timelineWidth = chat_page_->timelineWidth();
|
||||||
const uint64_t minAvailableWidth = sz.collapsePoint + sz.groups;
|
const uint64_t minAvailableWidth = sz.collapsePoint + sz.groups;
|
||||||
|
|
||||||
if (timelineWidth < minAvailableWidth && !chat_page_->isSideBarExpanded()) {
|
nhlog::ui()->info("timelineWidth: {}, min {}", timelineWidth, minAvailableWidth);
|
||||||
|
if (timelineWidth < minAvailableWidth) {
|
||||||
chat_page_->hideSideBars();
|
chat_page_->hideSideBars();
|
||||||
} else {
|
} else {
|
||||||
chat_page_->showSideBars();
|
chat_page_->showSideBars();
|
||||||
|
|
|
@ -1,229 +0,0 @@
|
||||||
/*
|
|
||||||
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPen>
|
|
||||||
#include <QPoint>
|
|
||||||
#include <QStyle>
|
|
||||||
#include <QStyleOption>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "TopRoomBar.h"
|
|
||||||
#include "Utils.h"
|
|
||||||
#include "ui/Avatar.h"
|
|
||||||
#include "ui/FlatButton.h"
|
|
||||||
#include "ui/Menu.h"
|
|
||||||
#include "ui/OverlayModal.h"
|
|
||||||
#include "ui/TextLabel.h"
|
|
||||||
|
|
||||||
TopRoomBar::TopRoomBar(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, buttonSize_{32}
|
|
||||||
{
|
|
||||||
QFont f;
|
|
||||||
f.setPointSizeF(f.pointSizeF());
|
|
||||||
|
|
||||||
const int fontHeight = QFontMetrics(f).height();
|
|
||||||
const int widgetMargin = fontHeight / 3;
|
|
||||||
const int contentHeight = fontHeight * 3;
|
|
||||||
|
|
||||||
setFixedHeight(contentHeight + widgetMargin);
|
|
||||||
|
|
||||||
topLayout_ = new QHBoxLayout(this);
|
|
||||||
topLayout_->setSpacing(widgetMargin);
|
|
||||||
topLayout_->setContentsMargins(
|
|
||||||
2 * widgetMargin, widgetMargin, 2 * widgetMargin, widgetMargin);
|
|
||||||
|
|
||||||
avatar_ = new Avatar(this, fontHeight * 2);
|
|
||||||
avatar_->setLetter("");
|
|
||||||
|
|
||||||
textLayout_ = new QVBoxLayout();
|
|
||||||
textLayout_->setSpacing(0);
|
|
||||||
textLayout_->setMargin(0);
|
|
||||||
|
|
||||||
QFont roomFont;
|
|
||||||
roomFont.setPointSizeF(roomFont.pointSizeF() * 1.1);
|
|
||||||
roomFont.setWeight(QFont::Medium);
|
|
||||||
|
|
||||||
nameLabel_ = new QLabel(this);
|
|
||||||
nameLabel_->setFont(roomFont);
|
|
||||||
nameLabel_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
|
|
||||||
|
|
||||||
QFont descriptionFont;
|
|
||||||
|
|
||||||
topicLabel_ = new TextLabel(this);
|
|
||||||
topicLabel_->setLineWrapMode(QTextEdit::NoWrap);
|
|
||||||
topicLabel_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
topicLabel_->setFont(descriptionFont);
|
|
||||||
topicLabel_->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
topicLabel_->setOpenExternalLinks(true);
|
|
||||||
topicLabel_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
|
|
||||||
|
|
||||||
textLayout_->addWidget(nameLabel_);
|
|
||||||
textLayout_->addWidget(topicLabel_);
|
|
||||||
|
|
||||||
settingsBtn_ = new FlatButton(this);
|
|
||||||
settingsBtn_->setToolTip(tr("Room options"));
|
|
||||||
settingsBtn_->setFixedSize(buttonSize_, buttonSize_);
|
|
||||||
settingsBtn_->setCornerRadius(buttonSize_ / 2);
|
|
||||||
|
|
||||||
mentionsBtn_ = new FlatButton(this);
|
|
||||||
mentionsBtn_->setToolTip(tr("Mentions"));
|
|
||||||
mentionsBtn_->setFixedSize(buttonSize_, buttonSize_);
|
|
||||||
mentionsBtn_->setCornerRadius(buttonSize_ / 2);
|
|
||||||
|
|
||||||
QIcon settings_icon;
|
|
||||||
settings_icon.addFile(":/icons/icons/ui/vertical-ellipsis.png");
|
|
||||||
settingsBtn_->setIcon(settings_icon);
|
|
||||||
settingsBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));
|
|
||||||
|
|
||||||
QIcon mentions_icon;
|
|
||||||
mentions_icon.addFile(":/icons/icons/ui/at-solid.svg");
|
|
||||||
mentionsBtn_->setIcon(mentions_icon);
|
|
||||||
mentionsBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));
|
|
||||||
|
|
||||||
backBtn_ = new FlatButton(this);
|
|
||||||
backBtn_->setFixedSize(buttonSize_, buttonSize_);
|
|
||||||
backBtn_->setCornerRadius(buttonSize_ / 2);
|
|
||||||
|
|
||||||
QIcon backIcon;
|
|
||||||
backIcon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
|
|
||||||
backBtn_->setIcon(backIcon);
|
|
||||||
backBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));
|
|
||||||
backBtn_->hide();
|
|
||||||
|
|
||||||
connect(backBtn_, &QPushButton::clicked, this, &TopRoomBar::showRoomList);
|
|
||||||
|
|
||||||
topLayout_->addWidget(avatar_);
|
|
||||||
topLayout_->addWidget(backBtn_);
|
|
||||||
topLayout_->addLayout(textLayout_, 1);
|
|
||||||
topLayout_->addWidget(mentionsBtn_, 0, Qt::AlignRight);
|
|
||||||
topLayout_->addWidget(settingsBtn_, 0, Qt::AlignRight);
|
|
||||||
|
|
||||||
menu_ = new Menu(this);
|
|
||||||
|
|
||||||
inviteUsers_ = new QAction(tr("Invite users"), this);
|
|
||||||
connect(inviteUsers_, &QAction::triggered, this, [this]() {
|
|
||||||
MainWindow::instance()->openInviteUsersDialog(
|
|
||||||
[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();
|
|
||||||
});
|
|
||||||
|
|
||||||
roomSettings_ = new QAction(tr("Settings"), this);
|
|
||||||
connect(roomSettings_, &QAction::triggered, this, []() {
|
|
||||||
MainWindow::instance()->openRoomSettings();
|
|
||||||
});
|
|
||||||
|
|
||||||
menu_->addAction(inviteUsers_);
|
|
||||||
menu_->addAction(roomMembers_);
|
|
||||||
menu_->addAction(leaveRoom_);
|
|
||||||
menu_->addAction(roomSettings_);
|
|
||||||
|
|
||||||
connect(settingsBtn_, &QPushButton::clicked, this, [this]() {
|
|
||||||
auto pos = mapToGlobal(settingsBtn_->pos());
|
|
||||||
menu_->popup(
|
|
||||||
QPoint(pos.x() + buttonSize_ - menu_->sizeHint().width(), pos.y() + buttonSize_));
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(mentionsBtn_, &QPushButton::clicked, this, [this]() {
|
|
||||||
auto pos = mapToGlobal(mentionsBtn_->pos());
|
|
||||||
emit mentionsClicked(pos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::enableBackButton()
|
|
||||||
{
|
|
||||||
avatar_->hide();
|
|
||||||
backBtn_->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::disableBackButton()
|
|
||||||
{
|
|
||||||
avatar_->show();
|
|
||||||
backBtn_->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::updateRoomAvatarFromName(const QString &name)
|
|
||||||
{
|
|
||||||
avatar_->setLetter(utils::firstChar(name));
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::reset()
|
|
||||||
{
|
|
||||||
nameLabel_->setText("");
|
|
||||||
topicLabel_->setText("");
|
|
||||||
avatar_->setLetter("");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::updateRoomAvatar(const QString &avatar_image)
|
|
||||||
{
|
|
||||||
avatar_->setImage(avatar_image);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::updateRoomName(const QString &name)
|
|
||||||
{
|
|
||||||
nameLabel_->setText(name);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::updateRoomTopic(QString topic)
|
|
||||||
{
|
|
||||||
topic.replace(conf::strings::url_regex, conf::strings::url_html);
|
|
||||||
topicLabel_->clearLinks();
|
|
||||||
topicLabel_->setHtml(topic);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::mousePressEvent(QMouseEvent *)
|
|
||||||
{
|
|
||||||
if (roomSettings_ != nullptr)
|
|
||||||
roomSettings_->trigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TopRoomBar::paintEvent(QPaintEvent *)
|
|
||||||
{
|
|
||||||
QStyleOption opt;
|
|
||||||
opt.init(this);
|
|
||||||
QPainter p(this);
|
|
||||||
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
/*
|
|
||||||
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QColor>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class Avatar;
|
|
||||||
class FlatButton;
|
|
||||||
class Menu;
|
|
||||||
class TextLabel;
|
|
||||||
class OverlayModal;
|
|
||||||
|
|
||||||
class QLabel;
|
|
||||||
class QHBoxLayout;
|
|
||||||
class QVBoxLayout;
|
|
||||||
|
|
||||||
class TopRoomBar : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor)
|
|
||||||
|
|
||||||
public:
|
|
||||||
TopRoomBar(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void updateRoomAvatar(const QString &avatar_image);
|
|
||||||
void updateRoomName(const QString &name);
|
|
||||||
void updateRoomTopic(QString topic);
|
|
||||||
void updateRoomAvatarFromName(const QString &name);
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
QColor borderColor() const { return borderColor_; }
|
|
||||||
void setBorderColor(QColor &color) { borderColor_ = color; }
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
//! Add a "back-arrow" button that can switch to roomlist only view.
|
|
||||||
void enableBackButton();
|
|
||||||
//! Replace the "back-arrow" button with the avatar of the room.
|
|
||||||
void disableBackButton();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void inviteUsers(QStringList users);
|
|
||||||
void showRoomList();
|
|
||||||
void mentionsClicked(const QPoint &pos);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *) override;
|
|
||||||
void paintEvent(QPaintEvent *) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QHBoxLayout *topLayout_ = nullptr;
|
|
||||||
QVBoxLayout *textLayout_ = nullptr;
|
|
||||||
|
|
||||||
QLabel *nameLabel_ = nullptr;
|
|
||||||
TextLabel *topicLabel_ = nullptr;
|
|
||||||
|
|
||||||
Menu *menu_;
|
|
||||||
QAction *leaveRoom_ = nullptr;
|
|
||||||
QAction *roomMembers_ = nullptr;
|
|
||||||
QAction *roomSettings_ = nullptr;
|
|
||||||
QAction *inviteUsers_ = nullptr;
|
|
||||||
|
|
||||||
FlatButton *settingsBtn_;
|
|
||||||
FlatButton *mentionsBtn_;
|
|
||||||
FlatButton *backBtn_;
|
|
||||||
|
|
||||||
Avatar *avatar_;
|
|
||||||
|
|
||||||
int buttonSize_;
|
|
||||||
|
|
||||||
QColor borderColor_;
|
|
||||||
};
|
|
|
@ -517,6 +517,25 @@ TimelineModel::fetchMore(const QModelIndex &)
|
||||||
events.fetchMore();
|
events.fetchMore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::syncState(const mtx::responses::State &s)
|
||||||
|
{
|
||||||
|
using namespace mtx::events;
|
||||||
|
|
||||||
|
for (const auto &e : s.events) {
|
||||||
|
if (std::holds_alternative<StateEvent<state::Avatar>>(e))
|
||||||
|
emit roomAvatarUrlChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Name>>(e))
|
||||||
|
emit roomNameChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
||||||
|
emit roomTopicChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
|
||||||
|
emit roomAvatarUrlChanged();
|
||||||
|
emit roomNameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
||||||
{
|
{
|
||||||
|
@ -526,6 +545,7 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
||||||
events.handleSync(timeline);
|
events.handleSync(timeline);
|
||||||
|
|
||||||
using namespace mtx::events;
|
using namespace mtx::events;
|
||||||
|
|
||||||
for (auto e : timeline.events) {
|
for (auto e : timeline.events) {
|
||||||
if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
|
if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
|
||||||
MegolmSessionIndex index;
|
MegolmSessionIndex index;
|
||||||
|
@ -549,6 +569,16 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
||||||
emit newCallEvent(event);
|
emit newCallEvent(event);
|
||||||
},
|
},
|
||||||
e);
|
e);
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Avatar>>(e))
|
||||||
|
emit roomAvatarUrlChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Name>>(e))
|
||||||
|
emit roomNameChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
||||||
|
emit roomTopicChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
|
||||||
|
emit roomAvatarUrlChanged();
|
||||||
|
emit roomNameChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateLastMessage();
|
updateLastMessage();
|
||||||
}
|
}
|
||||||
|
@ -1594,3 +1624,37 @@ TimelineModel::formatMemberEvent(QString id)
|
||||||
|
|
||||||
return rendered;
|
return rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
TimelineModel::roomName() const
|
||||||
|
{
|
||||||
|
auto info = cache::getRoomInfo({room_id_.toStdString()});
|
||||||
|
|
||||||
|
if (!info.count(room_id_))
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return QString::fromStdString(info[room_id_].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
TimelineModel::roomAvatarUrl() const
|
||||||
|
{
|
||||||
|
auto info = cache::getRoomInfo({room_id_.toStdString()});
|
||||||
|
|
||||||
|
if (!info.count(room_id_))
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return QString::fromStdString(info[room_id_].avatar_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
TimelineModel::roomTopic() const
|
||||||
|
{
|
||||||
|
auto info = cache::getRoomInfo({room_id_.toStdString()});
|
||||||
|
|
||||||
|
if (!info.count(room_id_))
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return utils::replaceEmoji(utils::linkifyMessage(
|
||||||
|
utils::escapeBlacklistedHtml(QString::fromStdString(info[room_id_].topic))));
|
||||||
|
}
|
||||||
|
|
|
@ -137,6 +137,9 @@ class TimelineModel : public QAbstractListModel
|
||||||
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
|
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
|
bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
|
||||||
|
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
||||||
|
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
|
||||||
|
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TimelineModel(TimelineViewManager *manager,
|
explicit TimelineModel(TimelineViewManager *manager,
|
||||||
|
@ -217,6 +220,7 @@ public:
|
||||||
|
|
||||||
void updateLastMessage();
|
void updateLastMessage();
|
||||||
void addEvents(const mtx::responses::Timeline &events);
|
void addEvents(const mtx::responses::Timeline &events);
|
||||||
|
void syncState(const mtx::responses::State &state);
|
||||||
template<class T>
|
template<class T>
|
||||||
void sendMessageEvent(const T &content, mtx::events::EventType eventType);
|
void sendMessageEvent(const T &content, mtx::events::EventType eventType);
|
||||||
RelatedInfo relatedInfo(QString id);
|
RelatedInfo relatedInfo(QString id);
|
||||||
|
@ -253,6 +257,10 @@ public slots:
|
||||||
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
|
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
|
||||||
void clearTimeline() { events.clearTimeline(); }
|
void clearTimeline() { events.clearTimeline(); }
|
||||||
|
|
||||||
|
QString roomName() const;
|
||||||
|
QString roomTopic() const;
|
||||||
|
QString roomAvatarUrl() const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void addPendingMessage(mtx::events::collections::TimelineEvents event);
|
void addPendingMessage(mtx::events::collections::TimelineEvents event);
|
||||||
|
|
||||||
|
@ -270,6 +278,10 @@ signals:
|
||||||
void newMessageToSend(mtx::events::collections::TimelineEvents event);
|
void newMessageToSend(mtx::events::collections::TimelineEvents event);
|
||||||
void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
|
void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
|
||||||
|
|
||||||
|
void roomNameChanged();
|
||||||
|
void roomTopicChanged();
|
||||||
|
void roomAvatarUrlChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendEncryptedMessageEvent(const std::string &txn_id,
|
void sendEncryptedMessageEvent(const std::string &txn_id,
|
||||||
nlohmann::json content,
|
nlohmann::json content,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "ColorImageProvider.h"
|
#include "ColorImageProvider.h"
|
||||||
#include "DelegateChooser.h"
|
#include "DelegateChooser.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "MxcImageProvider.h"
|
#include "MxcImageProvider.h"
|
||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
|
@ -76,7 +77,7 @@ TimelineViewManager::userStatus(QString id) const
|
||||||
|
|
||||||
TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings,
|
TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings,
|
||||||
CallManager *callManager,
|
CallManager *callManager,
|
||||||
QWidget *parent)
|
ChatPage *parent)
|
||||||
: imgProvider(new MxcImageProvider())
|
: imgProvider(new MxcImageProvider())
|
||||||
, colorImgProvider(new ColorImageProvider())
|
, colorImgProvider(new ColorImageProvider())
|
||||||
, blurhashProvider(new BlurhashProvider())
|
, blurhashProvider(new BlurhashProvider())
|
||||||
|
@ -131,15 +132,12 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
|
||||||
view->engine()->addImageProvider("blurhash", blurhashProvider);
|
view->engine()->addImageProvider("blurhash", blurhashProvider);
|
||||||
view->setSource(QUrl("qrc:///qml/TimelineView.qml"));
|
view->setSource(QUrl("qrc:///qml/TimelineView.qml"));
|
||||||
|
|
||||||
connect(dynamic_cast<ChatPage *>(parent),
|
connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette);
|
||||||
&ChatPage::themeChanged,
|
connect(parent,
|
||||||
this,
|
|
||||||
&TimelineViewManager::updateColorPalette);
|
|
||||||
connect(dynamic_cast<ChatPage *>(parent),
|
|
||||||
&ChatPage::decryptSidebarChanged,
|
&ChatPage::decryptSidebarChanged,
|
||||||
this,
|
this,
|
||||||
&TimelineViewManager::updateEncryptedDescriptions);
|
&TimelineViewManager::updateEncryptedDescriptions);
|
||||||
connect(dynamic_cast<ChatPage *>(parent), &ChatPage::loggedOut, this, [this]() {
|
connect(parent, &ChatPage::loggedOut, this, [this]() {
|
||||||
isInitialSync_ = true;
|
isInitialSync_ = true;
|
||||||
emit initialSyncChanged(true);
|
emit initialSyncChanged(true);
|
||||||
});
|
});
|
||||||
|
@ -157,6 +155,7 @@ TimelineViewManager::sync(const mtx::responses::Rooms &rooms)
|
||||||
&TimelineModel::newCallEvent,
|
&TimelineModel::newCallEvent,
|
||||||
callManager_,
|
callManager_,
|
||||||
&CallManager::syncEvent);
|
&CallManager::syncEvent);
|
||||||
|
room_model->syncState(room.state);
|
||||||
room_model->addEvents(room.timeline);
|
room_model->addEvents(room.timeline);
|
||||||
if (!isInitialSync_)
|
if (!isInitialSync_)
|
||||||
disconnect(room_model.data(),
|
disconnect(room_model.data(),
|
||||||
|
@ -245,6 +244,28 @@ TimelineViewManager::openLink(QString link) const
|
||||||
QDesktopServices::openUrl(link);
|
QDesktopServices::openUrl(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::openInviteUsersDialog()
|
||||||
|
{
|
||||||
|
MainWindow::instance()->openInviteUsersDialog(
|
||||||
|
[this](const QStringList &invitees) { emit inviteUsers(invitees); });
|
||||||
|
}
|
||||||
|
void
|
||||||
|
TimelineViewManager::openMemberListDialog() const
|
||||||
|
{
|
||||||
|
MainWindow::instance()->openMemberListDialog();
|
||||||
|
}
|
||||||
|
void
|
||||||
|
TimelineViewManager::openLeaveRoomDialog() const
|
||||||
|
{
|
||||||
|
MainWindow::instance()->openLeaveRoomDialog();
|
||||||
|
}
|
||||||
|
void
|
||||||
|
TimelineViewManager::openRoomSettings() const
|
||||||
|
{
|
||||||
|
MainWindow::instance()->openRoomSettings();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::updateReadReceipts(const QString &room_id,
|
TimelineViewManager::updateReadReceipts(const QString &room_id,
|
||||||
const std::vector<QString> &event_ids)
|
const std::vector<QString> &event_ids)
|
||||||
|
|
|
@ -21,6 +21,7 @@ class BlurhashProvider;
|
||||||
class CallManager;
|
class CallManager;
|
||||||
class ColorImageProvider;
|
class ColorImageProvider;
|
||||||
class UserSettings;
|
class UserSettings;
|
||||||
|
class ChatPage;
|
||||||
|
|
||||||
class TimelineViewManager : public QObject
|
class TimelineViewManager : public QObject
|
||||||
{
|
{
|
||||||
|
@ -30,11 +31,13 @@ class TimelineViewManager : public QObject
|
||||||
TimelineModel *timeline MEMBER timeline_ READ activeTimeline NOTIFY activeTimelineChanged)
|
TimelineModel *timeline MEMBER timeline_ READ activeTimeline NOTIFY activeTimelineChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
|
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
|
||||||
|
Q_PROPERTY(
|
||||||
|
bool isNarrowView MEMBER isNarrowView_ READ isNarrowView NOTIFY narrowViewChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TimelineViewManager(QSharedPointer<UserSettings> userSettings,
|
TimelineViewManager(QSharedPointer<UserSettings> userSettings,
|
||||||
CallManager *callManager,
|
CallManager *callManager,
|
||||||
QWidget *parent = nullptr);
|
ChatPage *parent = nullptr);
|
||||||
QWidget *getWidget() const { return container; }
|
QWidget *getWidget() const { return container; }
|
||||||
|
|
||||||
void sync(const mtx::responses::Rooms &rooms);
|
void sync(const mtx::responses::Rooms &rooms);
|
||||||
|
@ -44,6 +47,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
|
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
|
||||||
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
|
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
|
||||||
|
bool isNarrowView() const { return isNarrowView_; }
|
||||||
Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const;
|
Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const;
|
||||||
Q_INVOKABLE QColor userColor(QString id, QColor background);
|
Q_INVOKABLE QColor userColor(QString id, QColor background);
|
||||||
|
|
||||||
|
@ -52,6 +56,11 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void openLink(QString link) const;
|
Q_INVOKABLE void openLink(QString link) const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void openInviteUsersDialog();
|
||||||
|
Q_INVOKABLE void openMemberListDialog() const;
|
||||||
|
Q_INVOKABLE void openLeaveRoomDialog() const;
|
||||||
|
Q_INVOKABLE void openRoomSettings() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clearRoomMessageCount(QString roomid);
|
void clearRoomMessageCount(QString roomid);
|
||||||
void updateRoomsLastMessage(QString roomid, const DescInfo &info);
|
void updateRoomsLastMessage(QString roomid, const DescInfo &info);
|
||||||
|
@ -59,6 +68,9 @@ signals:
|
||||||
void initialSyncChanged(bool isInitialSync);
|
void initialSyncChanged(bool isInitialSync);
|
||||||
void replyingEventChanged(QString replyingEvent);
|
void replyingEventChanged(QString replyingEvent);
|
||||||
void replyClosed();
|
void replyClosed();
|
||||||
|
void inviteUsers(QStringList users);
|
||||||
|
void showRoomList();
|
||||||
|
void narrowViewChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
|
||||||
|
@ -108,6 +120,23 @@ public slots:
|
||||||
timeline_->clearTimeline();
|
timeline_->clearTimeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void enableBackButton()
|
||||||
|
{
|
||||||
|
if (isNarrowView_)
|
||||||
|
return;
|
||||||
|
isNarrowView_ = true;
|
||||||
|
emit narrowViewChanged();
|
||||||
|
}
|
||||||
|
void disableBackButton()
|
||||||
|
{
|
||||||
|
if (!isNarrowView_)
|
||||||
|
return;
|
||||||
|
isNarrowView_ = false;
|
||||||
|
emit narrowViewChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void backToRooms() { emit showRoomList(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef USE_QUICK_VIEW
|
#ifdef USE_QUICK_VIEW
|
||||||
QQuickView *view;
|
QQuickView *view;
|
||||||
|
@ -125,6 +154,7 @@ private:
|
||||||
CallManager *callManager_ = nullptr;
|
CallManager *callManager_ = nullptr;
|
||||||
|
|
||||||
bool isInitialSync_ = true;
|
bool isInitialSync_ = true;
|
||||||
|
bool isNarrowView_ = false;
|
||||||
|
|
||||||
QSharedPointer<UserSettings> settings;
|
QSharedPointer<UserSettings> settings;
|
||||||
QHash<QString, QColor> userColors;
|
QHash<QString, QColor> userColors;
|
||||||
|
|
Loading…
Reference in a new issue