From 421b15c05c605c8f4adc63433b00e37d56ac9da8 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 20 Sep 2022 21:26:28 +0200 Subject: [PATCH] Show the community of a room --- resources/qml/TopBar.qml | 61 ++++++++++++++++--- .../dialogs/AllowedRoomsSettingsDialog.qml | 1 - src/timeline/CommunitiesModel.cpp | 14 +++++ src/timeline/CommunitiesModel.h | 1 + src/timeline/TimelineModel.cpp | 25 ++++++++ src/timeline/TimelineModel.h | 7 +++ src/ui/RoomSummary.cpp | 43 +++++++++++++ src/ui/RoomSummary.h | 1 + 8 files changed, 143 insertions(+), 10 deletions(-) diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 2f94cf84..39365cd1 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -49,6 +49,13 @@ Pane { return; } + if (communityLabel.visible && eventPoint.position.y < communityAvatar.height + Nheko.paddingMedium + Nheko.paddingSmall/2) { + if (!Communities.trySwitchToSpace(room.parentSpace.roomid)) + room.parentSpace.promptJoin(); + eventPoint.accepted = true + return; + } + if (room) { let p = topBar.mapToItem(roomTopicC, eventPoint.position.x, eventPoint.position.y); let link = roomTopicC.linkAt(p.x, p.y); @@ -80,11 +87,46 @@ Pane { columnSpacing: Nheko.paddingSmall rowSpacing: Nheko.paddingSmall + + Avatar { + id: communityAvatar + + visible: roomid && room.parentSpace.isLoaded && ("space:"+room.parentSpace.roomid != Communities.currentTagId) + + property string avatarUrl: (Settings.groupView && room && room.parentSpace && room.parentSpace.roomAvatarUrl) || "" + property string communityId: (Settings.groupView && room && room.parentSpace && room.parentSpace.roomid) || "" + property string communityName: (Settings.groupView && room && room.parentSpace && room.parentSpace.roomName) || "" + + Layout.column: 1 + Layout.row: 0 + Layout.alignment: Qt.AlignRight + width: fontMetrics.lineSpacing + height: fontMetrics.lineSpacing + url: avatarUrl.replace("mxc://", "image://MxcImage/") + roomid: communityId + displayName: communityName + enabled: false + } + + Label { + id: communityLabel + visible: communityAvatar.visible + + Layout.column: 2 + Layout.row: 0 + Layout.fillWidth: true + color: Nheko.colors.text + text: qsTr("In %1").arg(communityAvatar.displayName) + maximumLineCount: 1 + elide: Text.ElideRight + textFormat: Text.RichText + } + ImageButton { id: backToRoomsButton Layout.column: 0 - Layout.row: 0 + Layout.row: 1 Layout.rowSpan: 2 Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium @@ -98,7 +140,7 @@ Pane { Avatar { Layout.column: 1 - Layout.row: 0 + Layout.row: 1 Layout.rowSpan: 2 Layout.alignment: Qt.AlignVCenter width: Nheko.avatarSize @@ -113,9 +155,10 @@ Pane { Label { Layout.fillWidth: true Layout.column: 2 - Layout.row: 0 + Layout.row: 1 color: Nheko.colors.text font.pointSize: fontMetrics.font.pointSize * 1.1 + font.bold: true text: roomName maximumLineCount: 1 elide: Text.ElideRight @@ -126,7 +169,7 @@ Pane { id: roomTopicC Layout.fillWidth: true Layout.column: 2 - Layout.row: 1 + Layout.row: 2 Layout.maximumHeight: fontMetrics.lineSpacing * 2 // show 2 lines selectByMouse: false enabled: false @@ -136,7 +179,7 @@ Pane { AbstractButton { Layout.column: 3 - Layout.row: 0 + Layout.row: 1 Layout.rowSpan: 2 Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium @@ -179,7 +222,7 @@ Pane { visible: !!room && room.pinnedMessages.length > 0 Layout.column: 4 - Layout.row: 0 + Layout.row: 1 Layout.rowSpan: 2 Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium @@ -207,7 +250,7 @@ Pane { visible: !!room Layout.column: 5 - Layout.row: 0 + Layout.row: 1 Layout.rowSpan: 2 Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium @@ -248,7 +291,7 @@ Pane { ScrollView { id: pinnedMessages - Layout.row: 2 + Layout.row: 3 Layout.column: 2 Layout.columnSpan: 3 @@ -329,7 +372,7 @@ Pane { ScrollView { id: widgets - Layout.row: 3 + Layout.row: 4 Layout.column: 2 Layout.columnSpan: 1 diff --git a/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml b/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml index 60ac06de..80905039 100644 --- a/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml +++ b/resources/qml/dialogs/AllowedRoomsSettingsDialog.qml @@ -122,7 +122,6 @@ ApplicationWindow { placeholderText: qsTr("Enter additional rooms not in the list yet...") - //font.pixelSize: Math.ceil(quickSwitcher.textHeight * 0.6) color: Nheko.colors.text onTextEdited: { roomCompleter.completer.searchString = text; diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp index 72d0bdfb..a0c73f84 100644 --- a/src/timeline/CommunitiesModel.cpp +++ b/src/timeline/CommunitiesModel.cpp @@ -605,6 +605,20 @@ CommunitiesModel::setCurrentTagId(const QString &tagId) emit currentTagIdChanged(currentTagId_); } +bool +CommunitiesModel::trySwitchToSpace(const QString &tag) +{ + for (const auto &t : spaceOrder_.tree) { + if (t.id == tag) { + this->currentTagId_ = "space:" + tag; + emit currentTagIdChanged(currentTagId_); + return true; + } + } + + return false; +} + void CommunitiesModel::toggleTagId(QString tagId) { diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h index 89f1ed07..3a599476 100644 --- a/src/timeline/CommunitiesModel.h +++ b/src/timeline/CommunitiesModel.h @@ -179,6 +179,7 @@ public slots: void clear(); QString currentTagId() const { return currentTagId_; } void setCurrentTagId(const QString &tagId); + bool trySwitchToSpace(const QString &spaceId); void resetCurrentTagId() { currentTagId_.clear(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index eaf85b2a..1ddef7b7 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -915,6 +915,9 @@ TimelineModel::syncState(const mtx::responses::State &s) } else if (std::holds_alternative>(e)) { this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString()); emit encryptionChanged(); + } else if (std::holds_alternative>(e)) { + this->parentChecked = false; + emit parentSpaceChanged(); } } } @@ -976,6 +979,9 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline) } else if (std::holds_alternative>(e)) { this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString()); emit encryptionChanged(); + } else if (std::holds_alternative>(e)) { + this->parentChecked = false; + emit parentSpaceChanged(); } } @@ -2904,3 +2910,22 @@ TimelineModel::directChatOtherUserId() const } else return {}; } + +RoomSummary * +TimelineModel::parentSpace() +{ + if (!parentChecked) { + auto parents = cache::client()->getStateEventsWithType( + this->room_id_.toStdString()); + + for (const auto &p : parents) { + if (p.content.canonical and p.content.via and not p.content.via->empty()) { + parentSummary.reset(new RoomSummary(p.state_key, *p.content.via, "")); + QQmlEngine::setObjectOwnership(parentSummary.get(), QQmlEngine::CppOwnership); + break; + } + } + } + + return parentSummary.get(); +} diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 295bc69b..ea6daa34 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -22,6 +22,7 @@ #include "MemberList.h" #include "Permissions.h" #include "ReadReceiptsModel.h" +#include "ui/RoomSummary.h" namespace mtx::http { using RequestErr = const std::optional &; @@ -197,6 +198,7 @@ class TimelineModel : public QAbstractListModel QString directChatOtherUserId READ directChatOtherUserId NOTIFY directChatOtherUserIdChanged) Q_PROPERTY(InputBar *input READ input CONSTANT) Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged) + Q_PROPERTY(RoomSummary *parentSpace READ parentSpace NOTIFY parentSpaceChanged) public: explicit TimelineModel(TimelineViewManager *manager, @@ -397,6 +399,7 @@ public slots: Permissions *permissions() { return &permissions_; } QString roomAvatarUrl() const; QString roomId() const { return room_id_; } + RoomSummary *parentSpace(); bool hasMentions() const { return highlight_count > 0; } int notificationCount() const { return notification_count; } @@ -431,6 +434,7 @@ signals: void addPendingMessageToStore(mtx::events::collections::TimelineEvents event); void updateFlowEventId(std::string event_id); + void parentSpaceChanged(); void encryptionChanged(); void fullyReadEventIdChanged(); void trustlevelChanged(); @@ -488,6 +492,9 @@ private: bool isEncrypted_ = false; std::string last_event_id; std::string fullyReadEventId_; + + std::unique_ptr parentSummary = nullptr; + bool parentChecked = false; }; template diff --git a/src/ui/RoomSummary.cpp b/src/ui/RoomSummary.cpp index da2a547c..6623da10 100644 --- a/src/ui/RoomSummary.cpp +++ b/src/ui/RoomSummary.cpp @@ -6,6 +6,7 @@ #include +#include "Cache.h" #include "ChatPage.h" #include "MatrixClient.h" @@ -18,6 +19,38 @@ RoomSummary::RoomSummary(std::string roomIdOrAlias_, , vias(std::move(vias_)) , reason_(std::move(r_)) { + if (roomIdOrAlias.empty()) + return; + + if (roomIdOrAlias[0] == '!') { + auto temp = cache::singleRoomInfo(roomIdOrAlias); + + if (temp.member_count) { + mtx::responses::PublicRoom newInfo{}; + // newInfo.aliases; + // newInfo.canonical_alias = ""; + newInfo.name = temp.name; + newInfo.room_id = roomIdOrAlias; + newInfo.topic = temp.topic; + newInfo.num_joined_members = temp.member_count; + // newInfo.world_readable; + newInfo.guest_can_join = temp.guest_access; + newInfo.avatar_url = temp.avatar_url; + + newInfo.join_rule = temp.join_rule; + newInfo.room_type = temp.is_space ? mtx::events::state::room_type::space : ""; + newInfo.room_version = temp.version; + newInfo.membership = mtx::events::state::Membership::Join; + // newInfo.encryption; + + this->room = std::move(newInfo); + loaded_ = true; + return; + } + + // newInfo.encryption; + } + auto ctx = std::make_shared(); connect(ctx.get(), &RoomSummaryProxy::failed, this, [this]() { @@ -52,3 +85,13 @@ RoomSummary::join() else ChatPage::instance()->joinRoomVia(roomIdOrAlias, vias, false, reason_); } + +void +RoomSummary::promptJoin() +{ + if (isKnockOnly()) + ChatPage::instance()->knockRoom( + QString::fromStdString(roomIdOrAlias), vias, reason_, false, true); + else + ChatPage::instance()->joinRoomVia(roomIdOrAlias, vias, true, reason_); +} diff --git a/src/ui/RoomSummary.h b/src/ui/RoomSummary.h index 416a4867..f5085054 100644 --- a/src/ui/RoomSummary.h +++ b/src/ui/RoomSummary.h @@ -69,6 +69,7 @@ public: bool isLoaded() const { return room.has_value() || loaded_; } Q_INVOKABLE void join(); + Q_INVOKABLE void promptJoin(); signals: void loaded();