Some basic room list

This commit is contained in:
Nicolas Werner 2021-05-19 19:34:10 +02:00
parent 567fe81ad7
commit 10fd2752f9
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
9 changed files with 439 additions and 164 deletions

View File

@ -272,6 +272,7 @@ set(SRC_FILES
src/timeline/TimelineModel.cpp src/timeline/TimelineModel.cpp
src/timeline/DelegateChooser.cpp src/timeline/DelegateChooser.cpp
src/timeline/Permissions.cpp src/timeline/Permissions.cpp
src/timeline/RoomlistModel.cpp
# UI components # UI components
src/ui/Avatar.cpp src/ui/Avatar.cpp
@ -497,6 +498,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/timeline/TimelineModel.h src/timeline/TimelineModel.h
src/timeline/DelegateChooser.h src/timeline/DelegateChooser.h
src/timeline/Permissions.h src/timeline/Permissions.h
src/timeline/RoomlistModel.h
# UI components # UI components
src/ui/Avatar.h src/ui/Avatar.h

View File

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2021 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.9
import QtQuick.Controls 2.13
import im.nheko 1.0
Label {
id: root
property alias fullText: metrics.text
property alias elideWidth: metrics.elideWidth
color: Nheko.colors.text
text: metrics.elidedText
maximumLineCount: 1
elide: Text.ElideRight
textFormat: Text.PlainText
TextMetrics {
id: metrics
font.pointSize: root.font.pointSize
elide: Text.ElideRight
}
}

View File

@ -21,7 +21,7 @@ Popup {
modal: true modal: true
palette: Nheko.colors palette: Nheko.colors
parent: Overlay.overlay parent: Overlay.overlay
width: implicitWidth >= (timelineView.width * 0.8) ? implicitWidth : (timelineView.width * 0.8) width: implicitWidth >= (timelineRoot.width * 0.8) ? implicitWidth : (timelineRoot.width * 0.8)
height: implicitHeight + completerPopup.height + padding * 2 height: implicitHeight + completerPopup.height + padding * 2
leftPadding: 10 leftPadding: 10
rightPadding: 10 rightPadding: 10

View File

@ -8,6 +8,132 @@ import QtQuick.Layouts 1.3
import im.nheko 1.0 import im.nheko 1.0
Page { Page {
ListView {
anchors.left: parent.left
anchors.right: parent.right
height: parent.height
model: Rooms
ScrollHelper {
flickable: parent
anchors.fill: parent
enabled: !Settings.mobileMode
}
delegate: Rectangle {
color: Nheko.colors.window
height: fontMetrics.lineSpacing * 2.5 + Nheko.paddingMedium * 2
width: ListView.view.width
RowLayout {
//id: userInfoGrid
spacing: Nheko.paddingMedium
anchors.fill: parent
anchors.margins: Nheko.paddingMedium
Avatar {
//userid: Nheko.currentUser.userid
id: avatar
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: fontMetrics.lineSpacing * 2.5
Layout.preferredHeight: fontMetrics.lineSpacing * 2.5
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
displayName: model.roomName
}
ColumnLayout {
id: textContent
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.minimumWidth: 100
width: parent.width - avatar.width
Layout.preferredWidth: parent.width - avatar.width
spacing: 0
RowLayout {
Layout.fillWidth: true
spacing: 0
ElidedLabel {
Layout.alignment: Qt.AlignBottom
color: Nheko.colors.text
elideWidth: textContent.width - timestamp.width - Nheko.paddingMedium
fullText: model.roomName + ": " + model.notificationCount
}
Item {
Layout.fillWidth: true
}
Label {
id: timestamp
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
font.pixelSize: fontMetrics.font.pixelSize * 0.9
color: Nheko.colors.buttonText
text: "14:32"
}
}
RowLayout {
Layout.fillWidth: true
spacing: 0
ElidedLabel {
color: Nheko.colors.buttonText
font.weight: Font.Thin
font.pixelSize: fontMetrics.font.pixelSize * 0.9
elideWidth: textContent.width - notificationBubble.width
fullText: model.lastMessage
}
Item {
Layout.fillWidth: true
}
Rectangle {
id: notificationBubble
Layout.alignment: Qt.AlignRight
height: fontMetrics.font.pixelSize * 1.3
width: height
radius: height / 2
color: Nheko.colors.highlight
Label {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
color: Nheko.colors.highlightedText
text: model.notificationCount
}
}
}
}
}
Rectangle {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
height: parent.height - Nheko.paddingSmall * 2
width: 3
color: Nheko.colors.highlight
visible: model.hasUnreadMessages
}
}
}
background: Rectangle { background: Rectangle {
color: Nheko.theme.sidebarBackground color: Nheko.theme.sidebarBackground
@ -34,8 +160,8 @@ Page {
id: avatar id: avatar
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: Nheko.avatarSize Layout.preferredWidth: fontMetrics.lineSpacing * 2
Layout.preferredHeight: Nheko.avatarSize Layout.preferredHeight: fontMetrics.lineSpacing * 2
url: Nheko.currentUser.avatarUrl.replace("mxc://", "image://MxcImage/") url: Nheko.currentUser.avatarUrl.replace("mxc://", "image://MxcImage/")
displayName: Nheko.currentUser.displayName displayName: Nheko.currentUser.displayName
userid: Nheko.currentUser.userid userid: Nheko.currentUser.userid
@ -46,50 +172,25 @@ Page {
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumWidth: 100 width: parent.width - avatar.width - logoutButton.width - Nheko.paddingMedium * 2
width: parent.width - avatar.width - logoutButton.width Layout.preferredWidth: parent.width - avatar.width - logoutButton.width - Nheko.paddingMedium * 2
Layout.preferredWidth: parent.width - avatar.width - logoutButton.width
spacing: 0 spacing: 0
Label { ElidedLabel {
Layout.alignment: Qt.AlignBottom Layout.alignment: Qt.AlignBottom
color: Nheko.colors.text
font.pointSize: fontMetrics.font.pointSize * 1.1 font.pointSize: fontMetrics.font.pointSize * 1.1
font.weight: Font.DemiBold font.weight: Font.DemiBold
text: userNameText.elidedText fullText: Nheko.currentUser.displayName
maximumLineCount: 1 elideWidth: col.width
elide: Text.ElideRight
textFormat: Text.PlainText
TextMetrics {
id: userNameText
font.pointSize: fontMetrics.font.pointSize * 1.1
elide: Text.ElideRight
elideWidth: col.width
text: Nheko.currentUser.displayName
}
} }
Label { ElidedLabel {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
color: Nheko.colors.buttonText color: Nheko.colors.buttonText
font.weight: Font.Thin font.weight: Font.Thin
text: userIdText.elidedText
maximumLineCount: 1
textFormat: Text.PlainText
font.pointSize: fontMetrics.font.pointSize * 0.9 font.pointSize: fontMetrics.font.pointSize * 0.9
elideWidth: col.width
TextMetrics { fullText: Nheko.currentUser.userid
id: userIdText
font.pointSize: fontMetrics.font.pointSize * 0.9
elide: Text.ElideRight
elideWidth: col.width
text: Nheko.currentUser.userid
}
} }
} }

View File

@ -131,6 +131,7 @@
<file>qml/Completer.qml</file> <file>qml/Completer.qml</file>
<file>qml/EncryptionIndicator.qml</file> <file>qml/EncryptionIndicator.qml</file>
<file>qml/ImageButton.qml</file> <file>qml/ImageButton.qml</file>
<file>qml/ElidedLabel.qml</file>
<file>qml/MatrixText.qml</file> <file>qml/MatrixText.qml</file>
<file>qml/MatrixTextField.qml</file> <file>qml/MatrixTextField.qml</file>
<file>qml/ToggleButton.qml</file> <file>qml/ToggleButton.qml</file>

View File

@ -0,0 +1,146 @@
// SPDX-FileCopyrightText: 2021 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "RoomlistModel.h"
#include "ChatPage.h"
#include "MatrixClient.h"
#include "MxcImageProvider.h"
#include "TimelineModel.h"
#include "TimelineViewManager.h"
#include "UserSettingsPage.h"
RoomlistModel::RoomlistModel(TimelineViewManager *parent)
: manager(parent)
{
connect(ChatPage::instance(), &ChatPage::decryptSidebarChanged, this, [this]() {
auto decrypt = ChatPage::instance()->userSettings()->decryptSidebar();
QHash<QString, QSharedPointer<TimelineModel>>::iterator i;
for (i = models.begin(); i != models.end(); ++i) {
auto ptr = i.value();
if (!ptr.isNull()) {
ptr->setDecryptDescription(decrypt);
ptr->updateLastMessage();
}
}
});
}
QHash<int, QByteArray>
RoomlistModel::roleNames() const
{
return {
{AvatarUrl, "avatarUrl"},
{RoomName, "roomName"},
{LastMessage, "lastMessage"},
{HasUnreadMessages, "hasUnreadMessages"},
{NotificationCount, "notificationCount"},
};
}
QVariant
RoomlistModel::data(const QModelIndex &index, int role) const
{
if (index.row() >= 0 && static_cast<size_t>(index.row()) < roomids.size()) {
auto room = models.value(roomids.at(index.row()));
switch (role) {
case Roles::AvatarUrl:
return room->roomAvatarUrl();
case Roles::RoomName:
return room->roomName();
case Roles::LastMessage:
return QString("Nico: Hahaha, this is funny!");
case Roles::HasUnreadMessages:
return true;
case Roles::NotificationCount:
return 5;
default:
return {};
}
} else {
return {};
}
}
void
RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification)
{
if (!models.contains(room_id)) {
QSharedPointer<TimelineModel> newRoom(new TimelineModel(manager, room_id));
newRoom->setDecryptDescription(
ChatPage::instance()->userSettings()->decryptSidebar());
connect(newRoom.data(),
&TimelineModel::newEncryptedImage,
manager->imageProvider(),
&MxcImageProvider::addEncryptionInfo);
connect(newRoom.data(),
&TimelineModel::forwardToRoom,
manager,
&TimelineViewManager::forwardMessageToRoom);
if (!suppressInsertNotification)
beginInsertRows(QModelIndex(), (int)roomids.size(), (int)roomids.size());
models.insert(room_id, std::move(newRoom));
roomids.push_back(room_id);
if (!suppressInsertNotification)
endInsertRows();
}
}
void
RoomlistModel::sync(const mtx::responses::Rooms &rooms)
{
for (const auto &[room_id, room] : rooms.join) {
// addRoom will only add the room, if it doesn't exist
addRoom(QString::fromStdString(room_id));
const auto &room_model = models.value(QString::fromStdString(room_id));
room_model->syncState(room.state);
room_model->addEvents(room.timeline);
connect(room_model.data(),
&TimelineModel::newCallEvent,
manager->callManager(),
&CallManager::syncEvent,
Qt::UniqueConnection);
if (ChatPage::instance()->userSettings()->typingNotifications()) {
for (const auto &ev : room.ephemeral.events) {
if (auto t = std::get_if<
mtx::events::EphemeralEvent<mtx::events::ephemeral::Typing>>(
&ev)) {
std::vector<QString> typing;
typing.reserve(t->content.user_ids.size());
for (const auto &user : t->content.user_ids) {
if (user != http::client()->user_id().to_string())
typing.push_back(
QString::fromStdString(user));
}
room_model->updateTypingUsers(typing);
}
}
}
}
}
void
RoomlistModel::initializeRooms(const std::vector<QString> &roomIds_)
{
beginResetModel();
models.clear();
roomids.clear();
roomids = roomIds_;
for (const auto &id : roomIds_)
addRoom(id, true);
endResetModel();
}
void
RoomlistModel::clear()
{
beginResetModel();
models.clear();
roomids.clear();
endResetModel();
}

View File

@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: 2021 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QAbstractListModel>
#include <QHash>
#include <QSharedPointer>
#include <QString>
#include <mtx/responses/sync.hpp>
class TimelineModel;
class TimelineViewManager;
class RoomlistModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles
{
AvatarUrl = Qt::UserRole,
RoomName,
LastMessage,
HasUnreadMessages,
NotificationCount,
};
RoomlistModel(TimelineViewManager *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
(void)parent;
return (int)roomids.size();
}
QVariant data(const QModelIndex &index, int role) const override;
QSharedPointer<TimelineModel> getRoomById(QString id) const
{
if (models.contains(id))
return models.value(id);
else
return {};
}
public slots:
void initializeRooms(const std::vector<QString> &roomids);
void sync(const mtx::responses::Rooms &rooms);
void clear();
private:
void addRoom(const QString &room_id, bool suppressInsertNotification = false);
TimelineViewManager *manager = nullptr;
std::vector<QString> roomids;
QHash<QString, QSharedPointer<TimelineModel>> models;
};

View File

@ -86,21 +86,6 @@ removeReplyFallback(mtx::events::Event<T> &e)
} }
} }
void
TimelineViewManager::updateEncryptedDescriptions()
{
auto decrypt = ChatPage::instance()->userSettings()->decryptSidebar();
QHash<QString, QSharedPointer<TimelineModel>>::iterator i;
for (i = models.begin(); i != models.end(); ++i) {
auto ptr = i.value();
if (!ptr.isNull()) {
ptr->setDecryptDescription(decrypt);
ptr->updateLastMessage();
}
}
}
void void
TimelineViewManager::updateColorPalette() TimelineViewManager::updateColorPalette()
{ {
@ -148,6 +133,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
, colorImgProvider(new ColorImageProvider()) , colorImgProvider(new ColorImageProvider())
, blurhashProvider(new BlurhashProvider()) , blurhashProvider(new BlurhashProvider())
, callManager_(callManager) , callManager_(callManager)
, rooms(new RoomlistModel(this))
{ {
qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>(); qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>();
qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>(); qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>();
@ -205,6 +191,12 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
return ptr; return ptr;
}); });
qmlRegisterSingletonType<RoomlistModel>(
"im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * {
auto ptr = self->rooms;
QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
return ptr;
});
qmlRegisterSingletonType<UserSettings>( qmlRegisterSingletonType<UserSettings>(
"im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * { "im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * {
auto ptr = ChatPage::instance()->userSettings().data(); auto ptr = ChatPage::instance()->userSettings().data();
@ -260,10 +252,6 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
view->setSource(QUrl("qrc:///qml/Root.qml")); view->setSource(QUrl("qrc:///qml/Root.qml"));
connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette); connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette);
connect(parent,
&ChatPage::decryptSidebarChanged,
this,
&TimelineViewManager::updateEncryptedDescriptions);
connect( connect(
dynamic_cast<ChatPage *>(parent), dynamic_cast<ChatPage *>(parent),
&ChatPage::receivedRoomDeviceVerificationRequest, &ChatPage::receivedRoomDeviceVerificationRequest,
@ -334,64 +322,13 @@ TimelineViewManager::setVideoCallItem()
} }
void void
TimelineViewManager::sync(const mtx::responses::Rooms &rooms) TimelineViewManager::sync(const mtx::responses::Rooms &rooms_)
{ {
for (const auto &[room_id, room] : rooms.join) { this->rooms->sync(rooms_);
// addRoom will only add the room, if it doesn't exist
addRoom(QString::fromStdString(room_id));
const auto &room_model = models.value(QString::fromStdString(room_id));
if (!isInitialSync_)
connect(room_model.data(),
&TimelineModel::newCallEvent,
callManager_,
&CallManager::syncEvent);
room_model->syncState(room.state);
room_model->addEvents(room.timeline);
if (!isInitialSync_)
disconnect(room_model.data(),
&TimelineModel::newCallEvent,
callManager_,
&CallManager::syncEvent);
if (ChatPage::instance()->userSettings()->typingNotifications()) { if (isInitialSync_) {
for (const auto &ev : room.ephemeral.events) { this->isInitialSync_ = false;
if (auto t = std::get_if< emit initialSyncChanged(false);
mtx::events::EphemeralEvent<mtx::events::ephemeral::Typing>>(
&ev)) {
std::vector<QString> typing;
typing.reserve(t->content.user_ids.size());
for (const auto &user : t->content.user_ids) {
if (user != http::client()->user_id().to_string())
typing.push_back(
QString::fromStdString(user));
}
room_model->updateTypingUsers(typing);
}
}
}
}
this->isInitialSync_ = false;
emit initialSyncChanged(false);
}
void
TimelineViewManager::addRoom(const QString &room_id)
{
if (!models.contains(room_id)) {
QSharedPointer<TimelineModel> newRoom(new TimelineModel(this, room_id));
newRoom->setDecryptDescription(
ChatPage::instance()->userSettings()->decryptSidebar());
connect(newRoom.data(),
&TimelineModel::newEncryptedImage,
imgProvider,
&MxcImageProvider::addEncryptionInfo);
connect(newRoom.data(),
&TimelineModel::forwardToRoom,
this,
&TimelineViewManager::forwardMessageToRoom);
models.insert(room_id, std::move(newRoom));
} }
} }
@ -400,9 +337,8 @@ TimelineViewManager::setHistoryView(const QString &room_id)
{ {
nhlog::ui()->info("Trying to activate room {}", room_id.toStdString()); nhlog::ui()->info("Trying to activate room {}", room_id.toStdString());
auto room = models.find(room_id); if (auto room = rooms->getRoomById(room_id)) {
if (room != models.end()) { timeline_ = room.get();
timeline_ = room.value().data();
emit activeTimelineChanged(timeline_); emit activeTimelineChanged(timeline_);
container->setFocus(); container->setFocus();
nhlog::ui()->info("Activated room {}", room_id.toStdString()); nhlog::ui()->info("Activated room {}", room_id.toStdString());
@ -418,10 +354,9 @@ TimelineViewManager::highlightRoom(const QString &room_id)
void void
TimelineViewManager::showEvent(const QString &room_id, const QString &event_id) TimelineViewManager::showEvent(const QString &room_id, const QString &event_id)
{ {
auto room = models.find(room_id); if (auto room = rooms->getRoomById(room_id)) {
if (room != models.end()) { if (timeline_ != room) {
if (timeline_ != room.value().data()) { timeline_ = room.get();
timeline_ = room.value().data();
emit activeTimelineChanged(timeline_); emit activeTimelineChanged(timeline_);
container->setFocus(); container->setFocus();
nhlog::ui()->info("Activated room {}", room_id.toStdString()); nhlog::ui()->info("Activated room {}", room_id.toStdString());
@ -505,17 +440,21 @@ TimelineViewManager::verifyUser(QString userid)
if (std::find(room_members.begin(), if (std::find(room_members.begin(),
room_members.end(), room_members.end(),
(userid).toStdString()) != room_members.end()) { (userid).toStdString()) != room_members.end()) {
auto model = models.value(QString::fromStdString(room_id)); if (auto model =
auto flow = DeviceVerificationFlow::InitiateUserVerification( rooms->getRoomById(QString::fromStdString(room_id))) {
this, model.data(), userid); auto flow =
connect(model.data(), DeviceVerificationFlow::InitiateUserVerification(
&TimelineModel::updateFlowEventId, this, model.data(), userid);
this, connect(model.data(),
[this, flow](std::string eventId) { &TimelineModel::updateFlowEventId,
dvList[QString::fromStdString(eventId)] = flow; this,
}); [this, flow](std::string eventId) {
emit newDeviceVerificationRequest(flow.data()); dvList[QString::fromStdString(eventId)] =
return; flow;
});
emit newDeviceVerificationRequest(flow.data());
return;
}
} }
} }
} }
@ -548,26 +487,23 @@ 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)
{ {
auto room = models.find(room_id); if (auto room = rooms->getRoomById(room_id)) {
if (room != models.end()) { room->markEventsAsRead(event_ids);
room.value()->markEventsAsRead(event_ids);
} }
} }
void void
TimelineViewManager::receivedSessionKey(const std::string &room_id, const std::string &session_id) TimelineViewManager::receivedSessionKey(const std::string &room_id, const std::string &session_id)
{ {
auto room = models.find(QString::fromStdString(room_id)); if (auto room = rooms->getRoomById(QString::fromStdString(room_id))) {
if (room != models.end()) { room->receivedSessionKey(session_id);
room.value()->receivedSessionKey(session_id);
} }
} }
void void
TimelineViewManager::initWithMessages(const std::vector<QString> &roomIds) TimelineViewManager::initWithMessages(const std::vector<QString> &roomIds)
{ {
for (const auto &roomId : roomIds) rooms->initializeRooms(roomIds);
addRoom(roomId);
} }
void void
@ -575,10 +511,9 @@ TimelineViewManager::queueReply(const QString &roomid,
const QString &repliedToEvent, const QString &repliedToEvent,
const QString &replyBody) const QString &replyBody)
{ {
auto room = models.find(roomid); if (auto room = rooms->getRoomById(roomid)) {
if (room != models.end()) { room->setReply(repliedToEvent);
room.value()->setReply(repliedToEvent); room->input()->message(replyBody);
room.value()->input()->message(replyBody);
} }
} }
@ -620,29 +555,32 @@ void
TimelineViewManager::queueCallMessage(const QString &roomid, TimelineViewManager::queueCallMessage(const QString &roomid,
const mtx::events::msg::CallInvite &callInvite) const mtx::events::msg::CallInvite &callInvite)
{ {
models.value(roomid)->sendMessageEvent(callInvite, mtx::events::EventType::CallInvite); if (auto room = rooms->getRoomById(roomid))
room->sendMessageEvent(callInvite, mtx::events::EventType::CallInvite);
} }
void void
TimelineViewManager::queueCallMessage(const QString &roomid, TimelineViewManager::queueCallMessage(const QString &roomid,
const mtx::events::msg::CallCandidates &callCandidates) const mtx::events::msg::CallCandidates &callCandidates)
{ {
models.value(roomid)->sendMessageEvent(callCandidates, if (auto room = rooms->getRoomById(roomid))
mtx::events::EventType::CallCandidates); room->sendMessageEvent(callCandidates, mtx::events::EventType::CallCandidates);
} }
void void
TimelineViewManager::queueCallMessage(const QString &roomid, TimelineViewManager::queueCallMessage(const QString &roomid,
const mtx::events::msg::CallAnswer &callAnswer) const mtx::events::msg::CallAnswer &callAnswer)
{ {
models.value(roomid)->sendMessageEvent(callAnswer, mtx::events::EventType::CallAnswer); if (auto room = rooms->getRoomById(roomid))
room->sendMessageEvent(callAnswer, mtx::events::EventType::CallAnswer);
} }
void void
TimelineViewManager::queueCallMessage(const QString &roomid, TimelineViewManager::queueCallMessage(const QString &roomid,
const mtx::events::msg::CallHangUp &callHangUp) const mtx::events::msg::CallHangUp &callHangUp)
{ {
models.value(roomid)->sendMessageEvent(callHangUp, mtx::events::EventType::CallHangUp); if (auto room = rooms->getRoomById(roomid))
room->sendMessageEvent(callHangUp, mtx::events::EventType::CallHangUp);
} }
void void
@ -693,7 +631,7 @@ void
TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e,
QString roomId) QString roomId)
{ {
auto room = models.find(roomId); auto room = rooms->getRoomById(roomId);
auto content = mtx::accessors::url(*e); auto content = mtx::accessors::url(*e);
std::optional<mtx::crypto::EncryptedFile> encryptionInfo = mtx::accessors::file(*e); std::optional<mtx::crypto::EncryptedFile> encryptionInfo = mtx::accessors::file(*e);
@ -736,12 +674,15 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven
ev.content.url = url; ev.content.url = url;
} }
auto room = models.find(roomId); if (auto room = rooms->getRoomById(roomId)) {
removeReplyFallback(ev); removeReplyFallback(ev);
ev.content.relations.relations.clear(); ev.content.relations.relations
room.value()->sendMessageEvent( .clear();
ev.content, room->sendMessageEvent(
mtx::events::EventType::RoomMessage); ev.content,
mtx::events::EventType::
RoomMessage);
}
} }
}, },
*e); *e);
@ -759,8 +700,7 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven
mtx::events::EventType::RoomMessage) { mtx::events::EventType::RoomMessage) {
e.content.relations.relations.clear(); e.content.relations.relations.clear();
removeReplyFallback(e); removeReplyFallback(e);
room.value()->sendMessageEvent(e.content, room->sendMessageEvent(e.content, mtx::events::EventType::RoomMessage);
mtx::events::EventType::RoomMessage);
} }
}, },
*e); *e);

View File

@ -22,6 +22,7 @@
#include "WebRTCSession.h" #include "WebRTCSession.h"
#include "emoji/EmojiModel.h" #include "emoji/EmojiModel.h"
#include "emoji/Provider.h" #include "emoji/Provider.h"
#include "timeline/RoomlistModel.h"
class MxcImageProvider; class MxcImageProvider;
class BlurhashProvider; class BlurhashProvider;
@ -48,13 +49,15 @@ public:
QWidget *getWidget() const { return container; } QWidget *getWidget() const { return container; }
void sync(const mtx::responses::Rooms &rooms); void sync(const mtx::responses::Rooms &rooms);
void addRoom(const QString &room_id);
MxcImageProvider *imageProvider() { return imgProvider; }
CallManager *callManager() { return callManager_; }
void clearAll() void clearAll()
{ {
timeline_ = nullptr; timeline_ = nullptr;
emit activeTimelineChanged(nullptr); emit activeTimelineChanged(nullptr);
models.clear(); rooms->clear();
} }
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; } Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
@ -109,11 +112,7 @@ public slots:
void focusTimeline(); void focusTimeline();
TimelineModel *getHistoryView(const QString &room_id) TimelineModel *getHistoryView(const QString &room_id)
{ {
auto room = models.find(room_id); return rooms->getRoomById(room_id).get();
if (room != models.end())
return room.value().data();
else
return nullptr;
} }
void updateColorPalette(); void updateColorPalette();
@ -126,7 +125,6 @@ public slots:
void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &);
void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &);
void updateEncryptedDescriptions();
void setVideoCallItem(); void setVideoCallItem();
void enableBackButton() void enableBackButton()
@ -163,7 +161,6 @@ private:
ColorImageProvider *colorImgProvider; ColorImageProvider *colorImgProvider;
BlurhashProvider *blurhashProvider; BlurhashProvider *blurhashProvider;
QHash<QString, QSharedPointer<TimelineModel>> models;
TimelineModel *timeline_ = nullptr; TimelineModel *timeline_ = nullptr;
CallManager *callManager_ = nullptr; CallManager *callManager_ = nullptr;
@ -171,6 +168,8 @@ private:
bool isNarrowView_ = false; bool isNarrowView_ = false;
bool isWindowFocused_ = false; bool isWindowFocused_ = false;
RoomlistModel *rooms = nullptr;
QHash<QString, QColor> userColors; QHash<QString, QColor> userColors;
QHash<QString, QSharedPointer<DeviceVerificationFlow>> dvList; QHash<QString, QSharedPointer<DeviceVerificationFlow>> dvList;