summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2022-05-06 00:36:38 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2022-05-06 00:36:53 +0200
commitb75ef07896b83dc50a11a7af525bff381d50b565 (patch)
tree5573ff6b667c3648454266e5716cf33288b68491
parentTranslated using Weblate (Finnish) (diff)
downloadnheko-b75ef07896b83dc50a11a7af525bff381d50b565.tar.xz
Add basic support for multiple windows
-rw-r--r--resources/qml/MessageView.qml8
-rw-r--r--resources/qml/RoomList.qml49
-rw-r--r--resources/qml/Root.qml2
-rw-r--r--src/ChatPage.cpp27
-rw-r--r--src/ChatPage.h2
-rw-r--r--src/MainWindow.h14
-rw-r--r--src/timeline/RoomlistModel.cpp28
-rw-r--r--src/timeline/RoomlistModel.h5
-rw-r--r--src/timeline/TimelineModel.cpp2
-rw-r--r--src/timeline/TimelineViewManager.cpp10
-rw-r--r--src/timeline/TimelineViewManager.h3
11 files changed, 109 insertions, 41 deletions
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
 
@@ -87,6 +122,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<bool> 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<RoomInfo> 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 *>(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);