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:
Nicolas Werner 2020-09-03 17:01:58 +02:00
parent c4e4938d35
commit 640b0ee405
12 changed files with 267 additions and 448 deletions

View file

@ -304,7 +304,6 @@ set(SRC_FILES
src/SideBarActions.cpp
src/Splitter.cpp
src/TextInputWidget.cpp
src/TopRoomBar.cpp
src/TrayIcon.cpp
src/UserInfoWidget.cpp
src/UserSettingsPage.cpp
@ -512,7 +511,6 @@ qt5_wrap_cpp(MOC_HEADERS
src/SideBarActions.h
src/Splitter.h
src/TextInputWidget.h
src/TopRoomBar.h
src/TrayIcon.h
src/UserInfoWidget.h
src/UserSettingsPage.h

View file

@ -50,6 +50,8 @@ Rectangle {
anchors.bottom: avatar.bottom
anchors.right: avatar.right
visible: !!userid
height: avatar.height / 6
width: height
radius: settings.avatarCircles ? height / 2 : height / 4

View file

@ -115,6 +115,112 @@ Page {
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 {
id: chat
@ -122,13 +228,8 @@ Page {
cacheBuffer: 400
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.bottom: chatFooter.top
width: parent.width
anchors.leftMargin: 4
anchors.rightMargin: scrollbar.width
Layout.fillWidth: true
Layout.fillHeight: true
model: timelineManager.timeline
@ -167,10 +268,6 @@ Page {
ScrollBar.vertical: ScrollBar {
id: scrollbar
parent: chat.parent
anchors.top: chat.top
anchors.right: chat.right
anchors.bottom: chat.bottom
}
spacing: 4
@ -178,9 +275,9 @@ Page {
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.
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
width: chat.delegateMaxWidth
height: section ? section.height + timelinerow.height : timelinerow.height
color: "transparent"
TimelineRow {
id: timelinerow
@ -309,17 +405,13 @@ Page {
}
}
Rectangle {
Item {
id: chatFooter
height: Math.max(fontMetrics.height * 1.2, footerContent.height)
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
implicitHeight: Math.max(fontMetrics.height * 1.2, footerContent.height)
Layout.fillWidth: true
z: 3
color: "transparent"
Column {
id: footerContent
anchors.left: parent.left
@ -382,4 +474,5 @@ Page {
}
}
}
}
}

View file

@ -37,7 +37,6 @@
#include "SideBarActions.h"
#include "Splitter.h"
#include "TextInputWidget.h"
#include "TopRoomBar.h"
#include "UserInfoWidget.h"
#include "UserSettingsPage.h"
#include "Utils.h"
@ -126,10 +125,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
contentLayout_->setSpacing(0);
contentLayout_->setMargin(0);
top_bar_ = new TopRoomBar(this);
view_manager_ = new TimelineViewManager(userSettings_, &callManager_, this);
contentLayout_->addWidget(top_bar_);
contentLayout_->addWidget(view_manager_->getWidget());
activeCallBar_ = new ActiveCallBar(this);
@ -181,30 +178,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
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);
connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
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(top_bar_, &TopRoomBar::showRoomList, splitter, &Splitter::showFullRoomList);
connect(top_bar_, &TopRoomBar::inviteUsers, this, [this](QStringList users) {
connect(
view_manager_, &TimelineViewManager::showRoomList, splitter, &Splitter::showFullRoomList);
connect(view_manager_, &TimelineViewManager::inviteUsers, this, [this](QStringList users) {
const auto room_id = current_room_.toStdString();
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, this, &ChatPage::changeTopRoomInfo);
connect(room_list_, &RoomList::roomChanged, splitter, &Splitter::showChatView);
connect(room_list_, &RoomList::roomChanged, text_input_, &TextInputWidget::focusLineEdit);
connect(
@ -487,8 +460,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
}
});
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
connect(
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::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).
connect(this, &ChatPage::setUserAvatar, user_info_widget_, &UserInfoWidget::setAvatar);
@ -657,7 +623,6 @@ void
ChatPage::resetUI()
{
room_list_->clear();
top_bar_->reset();
user_info_widget_->reset();
view_manager_->clearAll();
@ -786,46 +751,6 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
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
ChatPage::showUnreadMessageNotification(int count)
{
@ -1070,7 +995,6 @@ ChatPage::handleSyncResponse(mtx::responses::Sync res)
auto updates = cache::roomUpdates(res);
emit syncTopBar(updates);
emit syncRoomlist(updates);
emit syncUI(res.rooms);
@ -1481,9 +1405,12 @@ ChatPage::getProfileInfo()
void
ChatPage::hideSideBars()
{
communitiesList_->hide();
sideBar_->hide();
top_bar_->enableBackButton();
// Don't hide side bar, if we are currently only showing the side bar!
if (view_manager_->getWidget()->isVisible()) {
communitiesList_->hide();
sideBar_->hide();
}
view_manager_->enableBackButton();
}
void
@ -1493,23 +1420,19 @@ ChatPage::showSideBars()
communitiesList_->show();
sideBar_->show();
top_bar_->disableBackButton();
view_manager_->disableBackButton();
content_->show();
}
uint64_t
ChatPage::timelineWidth()
{
int sidebarWidth = sideBar_->size().width();
sidebarWidth += communitiesList_->size().width();
int sidebarWidth = sideBar_->minimumSize().width();
sidebarWidth += communitiesList_->minimumSize().width();
nhlog::ui()->info("timelineWidth: {}", size().width() - sidebarWidth);
return size().width() - sidebarWidth;
}
bool
ChatPage::isSideBarExpanded()
{
const auto sz = splitter::calculateSidebarSizes(QFont{});
return sideBar_->size().width() > sz.normal;
}
void
ChatPage::initiateLogout()

View file

@ -49,7 +49,6 @@ class SideBarActions;
class Splitter;
class TextInputWidget;
class TimelineViewManager;
class TopRoomBar;
class UserInfoWidget;
class UserSettings;
@ -82,7 +81,6 @@ public:
//! Calculate the width of the message timeline.
uint64_t timelineWidth();
bool isSideBarExpanded();
//! Hide the room & group list (if it was visible).
void hideSideBars();
//! Show the room/group list (if it was visible).
@ -150,7 +148,6 @@ signals:
void syncUI(const mtx::responses::Rooms &rooms);
void syncRoomlist(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 notifyMessage(const QString &roomid,
@ -167,8 +164,6 @@ signals:
private slots:
void showUnreadMessageNotification(int count);
void updateTopBarAvatar(const QString &roomid, const QString &img);
void changeTopRoomInfo(const QString &room_id);
void logout();
void removeRoom(const QString &room_id);
void dropToLoginPage(const QString &msg);
@ -239,7 +234,6 @@ private:
TimelineViewManager *view_manager_;
SideBarActions *sidebarActions_;
TopRoomBar *top_bar_;
TextInputWidget *text_input_;
ActiveCallBar *activeCallBar_;

View file

@ -200,7 +200,8 @@ MainWindow::adjustSideBars()
const uint64_t timelineWidth = chat_page_->timelineWidth();
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();
} else {
chat_page_->showSideBars();

View file

@ -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);
}

View file

@ -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_;
};

View file

@ -517,6 +517,25 @@ TimelineModel::fetchMore(const QModelIndex &)
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
TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
{
@ -526,6 +545,7 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
events.handleSync(timeline);
using namespace mtx::events;
for (auto e : timeline.events) {
if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
MegolmSessionIndex index;
@ -549,6 +569,16 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
emit newCallEvent(event);
},
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();
}
@ -1594,3 +1624,37 @@ TimelineModel::formatMemberEvent(QString id)
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))));
}

View file

@ -137,6 +137,9 @@ class TimelineModel : public QAbstractListModel
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
Q_PROPERTY(
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:
explicit TimelineModel(TimelineViewManager *manager,
@ -217,6 +220,7 @@ public:
void updateLastMessage();
void addEvents(const mtx::responses::Timeline &events);
void syncState(const mtx::responses::State &state);
template<class T>
void sendMessageEvent(const T &content, mtx::events::EventType eventType);
RelatedInfo relatedInfo(QString id);
@ -253,6 +257,10 @@ public slots:
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
void clearTimeline() { events.clearTimeline(); }
QString roomName() const;
QString roomTopic() const;
QString roomAvatarUrl() const;
private slots:
void addPendingMessage(mtx::events::collections::TimelineEvents event);
@ -270,6 +278,10 @@ signals:
void newMessageToSend(mtx::events::collections::TimelineEvents event);
void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
void roomNameChanged();
void roomTopicChanged();
void roomAvatarUrlChanged();
private:
void sendEncryptedMessageEvent(const std::string &txn_id,
nlohmann::json content,

View file

@ -12,6 +12,7 @@
#include "ColorImageProvider.h"
#include "DelegateChooser.h"
#include "Logging.h"
#include "MainWindow.h"
#include "MatrixClient.h"
#include "MxcImageProvider.h"
#include "UserSettingsPage.h"
@ -76,7 +77,7 @@ TimelineViewManager::userStatus(QString id) const
TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettings,
CallManager *callManager,
QWidget *parent)
ChatPage *parent)
: imgProvider(new MxcImageProvider())
, colorImgProvider(new ColorImageProvider())
, blurhashProvider(new BlurhashProvider())
@ -131,15 +132,12 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
view->engine()->addImageProvider("blurhash", blurhashProvider);
view->setSource(QUrl("qrc:///qml/TimelineView.qml"));
connect(dynamic_cast<ChatPage *>(parent),
&ChatPage::themeChanged,
this,
&TimelineViewManager::updateColorPalette);
connect(dynamic_cast<ChatPage *>(parent),
connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette);
connect(parent,
&ChatPage::decryptSidebarChanged,
this,
&TimelineViewManager::updateEncryptedDescriptions);
connect(dynamic_cast<ChatPage *>(parent), &ChatPage::loggedOut, this, [this]() {
connect(parent, &ChatPage::loggedOut, this, [this]() {
isInitialSync_ = true;
emit initialSyncChanged(true);
});
@ -157,6 +155,7 @@ TimelineViewManager::sync(const mtx::responses::Rooms &rooms)
&TimelineModel::newCallEvent,
callManager_,
&CallManager::syncEvent);
room_model->syncState(room.state);
room_model->addEvents(room.timeline);
if (!isInitialSync_)
disconnect(room_model.data(),
@ -245,6 +244,28 @@ TimelineViewManager::openLink(QString link) const
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
TimelineViewManager::updateReadReceipts(const QString &room_id,
const std::vector<QString> &event_ids)

View file

@ -21,6 +21,7 @@ class BlurhashProvider;
class CallManager;
class ColorImageProvider;
class UserSettings;
class ChatPage;
class TimelineViewManager : public QObject
{
@ -30,11 +31,13 @@ class TimelineViewManager : public QObject
TimelineModel *timeline MEMBER timeline_ READ activeTimeline NOTIFY activeTimelineChanged)
Q_PROPERTY(
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
Q_PROPERTY(
bool isNarrowView MEMBER isNarrowView_ READ isNarrowView NOTIFY narrowViewChanged)
public:
TimelineViewManager(QSharedPointer<UserSettings> userSettings,
CallManager *callManager,
QWidget *parent = nullptr);
ChatPage *parent = nullptr);
QWidget *getWidget() const { return container; }
void sync(const mtx::responses::Rooms &rooms);
@ -44,6 +47,7 @@ public:
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
bool isNarrowView() const { return isNarrowView_; }
Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const;
Q_INVOKABLE QColor userColor(QString id, QColor background);
@ -52,6 +56,11 @@ public:
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:
void clearRoomMessageCount(QString roomid);
void updateRoomsLastMessage(QString roomid, const DescInfo &info);
@ -59,6 +68,9 @@ signals:
void initialSyncChanged(bool isInitialSync);
void replyingEventChanged(QString replyingEvent);
void replyClosed();
void inviteUsers(QStringList users);
void showRoomList();
void narrowViewChanged();
public slots:
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
@ -108,6 +120,23 @@ public slots:
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:
#ifdef USE_QUICK_VIEW
QQuickView *view;
@ -125,6 +154,7 @@ private:
CallManager *callManager_ = nullptr;
bool isInitialSync_ = true;
bool isNarrowView_ = false;
QSharedPointer<UserSettings> settings;
QHash<QString, QColor> userColors;