diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index b20a1d88..541d20db 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -232,13 +232,7 @@ Item { } } - Connections { - function onFocusChanged() { - readTimer.running = TimelineManager.isWindowFocused; - } - - target: TimelineManager - } + Window.onActiveChanged: readTimer.running = Window.active Timer { id: readTimer diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 078baede..d33c562e 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -64,6 +64,41 @@ Page { target: Rooms } + Component { + id: roomWindowComponent + + ApplicationWindow { + id: roomWindowW + + property var room: null + property var roomPreview: null + + onActiveChanged: if (active) {MainWindow.activeRoom = (room.roomId || roomPreview.roomid)} + + height: 650 + width: 420 + minimumWidth: 150 + minimumHeight: 150 + palette: Nheko.colors + color: Nheko.colors.window + title: room.roomName + modality: Qt.NonModal + flags: Qt.Window | Qt.WindowCloseButtonHint | Qt.WindowTitleHint + + Shortcut { + sequence: StandardKey.Cancel + onActivated: roomWindowW.close() + } + + TimelineView { + anchors.fill: parent + room: roomWindowW.room + roomPreview: roomWindowW.roomPreview.roomid ? roomWindowW.roomPreview : null + } + } + + } + Platform.Menu { id: roomContextMenu @@ -86,6 +121,18 @@ Page { } } + Platform.MenuItem { + text: qsTr("Open separately") + onTriggered: { + var roomWindow = roomWindowComponent.createObject(null, { + "room": Rooms.getRoomById(roomContextMenu.roomid), + "roomPreview": Rooms.getRoomPreviewById(roomContextMenu.roomid) + }); + roomWindow.showNormal(); + destroyOnClose(roomWindow); + } + } + Platform.MenuItem { text: qsTr("Leave room") onTriggered: TimelineManager.openLeaveRoomDialog(roomContextMenu.roomid) @@ -97,7 +144,7 @@ Page { Instantiator { model: Communities.tagsWithDefault - onObjectAdded: roomContextMenu.insertItem(index + 2, object) + onObjectAdded: roomContextMenu.insertItem(index + 3, object) onObjectRemoved: roomContextMenu.removeItem(object) delegate: Platform.MenuItem { diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml index 72f30b7a..92bff0e0 100644 --- a/resources/qml/Root.qml +++ b/resources/qml/Root.qml @@ -25,6 +25,8 @@ Pane { background: null padding: 0 + Window.onActiveChanged: if (Window.active) {MainWindow.activeRoom = Qt.binding(function() { return Rooms.currentRoom.roomId || Rooms.currentRoomPreview.roomid })} + FontMetrics { id: fontMetrics } diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index ccaf2926..4c64c25c 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -813,7 +813,7 @@ ChatPage::changeRoom(const QString &room_id) void ChatPage::inviteUser(QString userid, QString reason) { - auto room = currentRoom(); + auto room = MainWindow::instance()->activeRoom(); if (QMessageBox::question(nullptr, tr("Confirm invite"), @@ -839,7 +839,7 @@ ChatPage::inviteUser(QString userid, QString reason) void ChatPage::kickUser(QString userid, QString reason) { - auto room = currentRoom(); + auto room = MainWindow::instance()->activeRoom(); bool confirmed; reason = @@ -870,7 +870,7 @@ ChatPage::kickUser(QString userid, QString reason) void ChatPage::banUser(QString userid, QString reason) { - auto room = currentRoom(); + auto room = MainWindow::instance()->activeRoom(); bool confirmed; reason = @@ -901,7 +901,7 @@ ChatPage::banUser(QString userid, QString reason) void ChatPage::unbanUser(QString userid, QString reason) { - auto room = currentRoom(); + auto room = MainWindow::instance()->activeRoom(); if (QMessageBox::question(nullptr, tr("Confirm unban"), @@ -1398,9 +1398,11 @@ ChatPage::handleMatrixUri(QString uri) if (sigil1 == u"u") { if (action.isEmpty()) { - auto t = view_manager_->rooms()->currentRoom(); - if (t && cache::isRoomMember(mxid1.toStdString(), t->roomId().toStdString())) { - t->openUserProfile(mxid1); + auto t = MainWindow::instance()->activeRoom(); + if (!t.isEmpty() && cache::isRoomMember(mxid1.toStdString(), t.toStdString())) { + auto rm = view_manager_->rooms()->getRoomById(t); + if (rm) + rm->openUserProfile(mxid1); return true; } emit view_manager_->openGlobalUserProfile(mxid1); @@ -1466,14 +1468,5 @@ ChatPage::handleMatrixUri(const QUrl &uri) bool ChatPage::isRoomActive(const QString &room_id) { - return MainWindow::instance()->isActive() && currentRoom() == room_id; -} - -QString -ChatPage::currentRoom() const -{ - if (view_manager_->rooms()->currentRoom()) - return view_manager_->rooms()->currentRoom()->roomId(); - else - return QString(); + return QGuiApplication::focusWindow() && MainWindow::instance()->activeRoom() == room_id; } diff --git a/src/ChatPage.h b/src/ChatPage.h index 2673a3de..fa920907 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -72,8 +72,6 @@ public: mtx::presence::PresenceState currentPresence() const; - // TODO(Nico): Get rid of this! - QString currentRoom() const; void startChat(QString userid, std::optional encryptionEnabled); public slots: diff --git a/src/MainWindow.h b/src/MainWindow.h index 3b1ff6f5..523b253d 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -40,6 +40,7 @@ class ReCaptcha; class MainWindow : public QQuickView { Q_OBJECT + Q_PROPERTY(QString activeRoom READ activeRoom WRITE updateActiveRoom NOTIFY activeRoomChanged) public: explicit MainWindow(QWindow *parent = nullptr); @@ -58,6 +59,15 @@ public: bool dbusAvailable() const { return dbusAvailable_; } #endif + QString activeRoom() const { return activeRoom_; } + void updateActiveRoom(QString r) + { + if (activeRoom_ != r) { + activeRoom_ = std::move(r); + emit activeRoomChanged(); + } + } + protected: void closeEvent(QCloseEvent *event); bool event(QEvent *event) override; @@ -78,6 +88,8 @@ signals: void switchToWelcomePage(); void switchToLoginPage(QString error); + void activeRoomChanged(); + private: void showDialog(QWidget *dialog); bool hasActiveUser(); @@ -101,6 +113,8 @@ private: MxcImageProvider *imgProvider = nullptr; + QString activeRoom_; + #ifdef NHEKO_DBUS_SYS bool dbusAvailable_{false}; #endif diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index ea4f6fa8..1e0b4c23 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -692,6 +692,34 @@ RoomlistModel::leave(QString roomid, QString reason) } } +RoomPreview +RoomlistModel::getRoomPreviewById(QString roomid) const +{ + RoomPreview preview{}; + + if (invites.contains(roomid) || previewedRooms.contains(roomid)) { + std::optional i; + if (invites.contains(roomid)) { + i = invites.value(roomid); + preview.isInvite_ = true; + } else { + i = previewedRooms.value(roomid); + preview.isInvite_ = false; + } + + if (i) { + preview.roomid_ = roomid; + preview.roomName_ = QString::fromStdString(i->name); + preview.roomTopic_ = QString::fromStdString(i->topic); + preview.roomAvatarUrl_ = QString::fromStdString(i->avatar_url); + } else { + preview.roomid_ = roomid; + } + } + + return preview; +} + void RoomlistModel::setCurrentRoom(QString roomid) { diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index 9546d434..43713d8b 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -89,6 +89,7 @@ public: else return {}; } + RoomPreview getRoomPreviewById(QString roomid) const; public slots: void initializeRooms(); @@ -185,6 +186,10 @@ public slots: { return roomlistmodel->getRoomById(id).data(); } + RoomPreview getRoomPreviewById(QString roomid) const + { + return roomlistmodel->getRoomPreviewById(roomid); + } void nextRoomWithActivity(); void nextRoom(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 4309fb24..77cf6294 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -1072,7 +1072,7 @@ TimelineModel::setCurrentIndex(int index) if (index != oldIndex) emit currentIndexChanged(index); - if (MainWindow::instance() != QGuiApplication::focusWindow()) + if (MainWindow::instance()->activeRoom() != roomId()) return; if (!currentId.startsWith('m')) { diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 3bccd8f3..b37e24b0 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -138,10 +138,6 @@ TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent) isInitialSync_ = true; emit initialSyncChanged(true); }); - connect(qobject_cast(QApplication::instance()), - &QApplication::focusWindowChanged, - this, - &TimelineViewManager::focusChanged); connect(parent, &ChatPage::connectionLost, this, [this] { isConnected_ = false; emit isConnectedChanged(false); @@ -152,12 +148,6 @@ TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent) }); } -bool -TimelineViewManager::isWindowFocused() const -{ - return MainWindow::instance() == QApplication::focusWindow(); -} - void TimelineViewManager::openRoomMembers(TimelineModel *room) { diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 08943e8c..020bdac5 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -41,7 +41,6 @@ class TimelineViewManager : public QObject Q_PROPERTY( bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) - Q_PROPERTY(bool isWindowFocused READ isWindowFocused NOTIFY focusChanged) Q_PROPERTY(bool isConnected READ isConnected NOTIFY isConnectedChanged) public: @@ -54,7 +53,6 @@ public: void clearAll() { rooms_->clear(); } Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } - bool isWindowFocused() const; bool isConnected() const { return isConnected_; } Q_INVOKABLE void openImageOverlay(TimelineModel *room, QString mxcUrl, QString eventId); Q_INVOKABLE void openImagePackSettings(QString roomid); @@ -82,7 +80,6 @@ signals: void inviteUsers(QString roomId, QStringList users); void showRoomList(); void narrowViewChanged(); - void focusChanged(); void focusInput(); void openRoomMembersDialog(MemberList *members, TimelineModel *room); void openRoomSettingsDialog(RoomSettings *settings);