From 5bed3684ec2da3490a7a6390340327246d95f0c3 Mon Sep 17 00:00:00 2001 From: Loren Burkholder Date: Tue, 25 Jan 2022 20:16:06 -0500 Subject: [PATCH] Add offline indicator (#472) --- resources/qml/ChatPage.qml | 165 ++++++++++---------- resources/qml/components/AdaptiveLayout.qml | 1 - src/timeline/TimelineViewManager.cpp | 8 + src/timeline/TimelineViewManager.h | 4 + 4 files changed, 98 insertions(+), 80 deletions(-) diff --git a/resources/qml/ChatPage.qml b/resources/qml/ChatPage.qml index e3aa3e48..bd60bdab 100644 --- a/resources/qml/ChatPage.qml +++ b/resources/qml/ChatPage.qml @@ -17,111 +17,118 @@ Rectangle { color: Nheko.colors.window - AdaptiveLayout { - id: adaptiveView - + ColumnLayout { + spacing: 0 anchors.fill: parent - singlePageMode: communityListC.preferredWidth + roomListC.preferredWidth + timlineViewC.minimumWidth > width - pageIndex: 1 - Component.onCompleted: initializePageIndex() - onSinglePageModeChanged: initializePageIndex() + Rectangle { + id: offlineIndicator - function initializePageIndex() { - if (!singlePageMode) - adaptiveView.pageIndex = 0; - else if (Rooms.currentRoom || Rooms.currentRoomPreview.roomid) - adaptiveView.pageIndex = 2; - else - adaptiveView.pageIndex = 1; - } + color: Nheko.theme.error + visible: !TimelineManager.isConnected + Layout.preferredHeight: fontMetrics.height + Nheko.paddingMedium + Layout.fillWidth: true - Connections { - target: Rooms - function onCurrentRoomChanged() { - adaptiveView.initializePageIndex(); + Label { + anchors.centerIn: parent + text: qsTr("No network connection") } } - Connections { - target: Communities - function onCurrentTagIdChanged() { - adaptiveView.initializePageIndex(); - } - } + AdaptiveLayout { + id: adaptiveView - onPageIndexChanged: { - if (adaptiveView.pageIndex == 1 && (Rooms.currentRoom || Rooms.currentRoomPreview.roomid)) { - Rooms.resetCurrentRoom(); - } - } + Layout.fillWidth: true + Layout.fillHeight: true + singlePageMode: communityListC.preferredWidth + roomListC.preferredWidth + timlineViewC.minimumWidth > width + pageIndex: 1 - AdaptiveLayoutElement { - id: communityListC + Component.onCompleted: initializePageIndex() + onSinglePageModeChanged: initializePageIndex() - visible: Settings.groupView - minimumWidth: communitiesList.avatarSize * 4 + Nheko.paddingMedium * 2 - collapsedWidth: communitiesList.avatarSize + 2 * Nheko.paddingMedium - preferredWidth: Settings.communityListWidth >= minimumWidth ? Settings.communityListWidth : collapsedWidth - maximumWidth: communitiesList.avatarSize * 10 + 2 * Nheko.paddingMedium - - CommunitiesList { - id: communitiesList - - collapsed: parent.collapsed + function initializePageIndex() { + if (!singlePageMode) + adaptiveView.pageIndex = 0; + else if (Rooms.currentRoom || Rooms.currentRoomPreview.roomid) + adaptiveView.pageIndex = 2; + else + adaptiveView.pageIndex = 1; } - Binding { - target: Settings - property: 'communityListWidth' - value: communityListC.preferredWidth - when: !adaptiveView.singlePageMode - delayed: true - restoreMode: Binding.RestoreBindingOrValue + Connections { + target: Rooms + function onCurrentRoomChanged() { + adaptiveView.initializePageIndex(); + } } - } + AdaptiveLayoutElement { + id: communityListC - AdaptiveLayoutElement { - id: roomListC + visible: Settings.groupView + minimumWidth: communitiesList.avatarSize * 4 + Nheko.paddingMedium * 2 + collapsedWidth: communitiesList.avatarSize + 2 * Nheko.paddingMedium + preferredWidth: Settings.communityListWidth >= minimumWidth ? Settings.communityListWidth : collapsedWidth + maximumWidth: communitiesList.avatarSize * 10 + 2 * Nheko.paddingMedium - minimumWidth: roomlist.avatarSize * 4 + Nheko.paddingSmall * 2 - preferredWidth: (Settings.roomListWidth == - 1) - ? (roomlist.avatarSize * 5 + Nheko.paddingSmall * 2) - : (Settings.roomListWidth >= minimumWidth ? Settings.roomListWidth : collapsedWidth) - maximumWidth: roomlist.avatarSize * 10 + Nheko.paddingSmall * 2 - collapsedWidth: roomlist.avatarSize + 2 * Nheko.paddingMedium + CommunitiesList { + id: communitiesList - RoomList { - id: roomlist + collapsed: parent.collapsed + } + + Binding { + target: Settings + property: 'communityListWidth' + value: communityListC.preferredWidth + when: !adaptiveView.singlePageMode + delayed: true + restoreMode: Binding.RestoreBindingOrValue + } - implicitHeight: chatPage.height - collapsed: parent.collapsed - anchors.fill: parent } - Binding { - target: Settings - property: 'roomListWidth' - value: roomListC.preferredWidth - when: !adaptiveView.singlePageMode - delayed: true - restoreMode: Binding.RestoreBindingOrValue + AdaptiveLayoutElement { + id: roomListC + + minimumWidth: roomlist.avatarSize * 4 + Nheko.paddingSmall * 2 + preferredWidth: (Settings.roomListWidth == - 1) + ? (roomlist.avatarSize * 5 + Nheko.paddingSmall * 2) + : (Settings.roomListWidth >= minimumWidth ? Settings.roomListWidth : collapsedWidth) + maximumWidth: roomlist.avatarSize * 10 + Nheko.paddingSmall * 2 + collapsedWidth: roomlist.avatarSize + 2 * Nheko.paddingMedium + + RoomList { + id: roomlist + + height: adaptiveView.height + collapsed: parent.collapsed + } + + Binding { + target: Settings + property: 'roomListWidth' + value: roomListC.preferredWidth + when: !adaptiveView.singlePageMode + delayed: true + restoreMode: Binding.RestoreBindingOrValue + } + } - } + AdaptiveLayoutElement { + id: timlineViewC - AdaptiveLayoutElement { - id: timlineViewC + minimumWidth: fontMetrics.averageCharacterWidth * 40 + Nheko.avatarSize + 2 * Nheko.paddingMedium - minimumWidth: fontMetrics.averageCharacterWidth * 40 + Nheko.avatarSize + 2 * Nheko.paddingMedium + TimelineView { + id: timeline - TimelineView { - id: timeline + showBackButton: adaptiveView.singlePageMode + room: Rooms.currentRoom + roomPreview: Rooms.currentRoomPreview.roomid ? Rooms.currentRoomPreview : null + } - showBackButton: adaptiveView.singlePageMode - room: Rooms.currentRoom - roomPreview: Rooms.currentRoomPreview.roomid ? Rooms.currentRoomPreview : null } } diff --git a/resources/qml/components/AdaptiveLayout.qml b/resources/qml/components/AdaptiveLayout.qml index 414b4d53..28befe91 100644 --- a/resources/qml/components/AdaptiveLayout.qml +++ b/resources/qml/components/AdaptiveLayout.qml @@ -23,7 +23,6 @@ Container { onSinglePageModeChanged: if (!singlePageMode) pageIndex = 0 - anchors.fill: parent Component.onCompleted: { for (var i = 0; i < count - 1; i++) { let handle_ = handle.createObject(contentChildren[i]); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 0abd102b..0851724a 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -162,6 +162,14 @@ TimelineViewManager::TimelineViewManager(CallManager *, ChatPage *parent) &QApplication::focusWindowChanged, this, &TimelineViewManager::focusChanged); + connect(parent, &ChatPage::connectionLost, this, [this] { + isConnected_ = false; + emit isConnectedChanged(false); + }); + connect(parent, &ChatPage::connectionRestored, this, [this] { + isConnected_ = true; + emit isConnectedChanged(true); + }); } bool diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 13ab5dbb..393b1479 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -42,6 +42,7 @@ 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: TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr); @@ -54,6 +55,7 @@ public: 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); Q_INVOKABLE void saveMedia(QString mxcUrl); @@ -73,6 +75,7 @@ public: signals: void activeTimelineChanged(TimelineModel *timeline); void initialSyncChanged(bool isInitialSync); + void isConnectedChanged(bool state); void replyingEventChanged(QString replyingEvent); void replyClosed(); void inviteUsers(QString roomId, QStringList users); @@ -111,6 +114,7 @@ public slots: private: bool isInitialSync_ = true; + bool isConnected_ = true; RoomlistModel *rooms_ = nullptr; CommunitiesModel *communities_ = nullptr;