From cd67046f6011f0838b5ed4621fb3ee9b846e63a0 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 21 May 2021 21:19:03 +0200 Subject: Make roomlist look nice --- src/timeline/TimelineModel.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'src/timeline/TimelineModel.cpp') diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8df17457..19c3fb30 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -723,6 +723,20 @@ TimelineModel::fetchMore(const QModelIndex &) events.fetchMore(); } +void +TimelineModel::sync(const mtx::responses::JoinedRoom &room) +{ + this->syncState(room.state); + this->addEvents(room.timeline); + + if (room.unread_notifications.highlight_count != highlight_count || + room.unread_notifications.notification_count != notification_count) { + notification_count = room.unread_notifications.notification_count; + highlight_count = room.unread_notifications.highlight_count; + emit notificationsChanged(); + } +} + void TimelineModel::syncState(const mtx::responses::State &s) { @@ -866,14 +880,18 @@ TimelineModel::updateLastMessage() if (std::visit([](const auto &e) -> bool { return isYourJoin(e); }, *event)) { auto time = mtx::accessors::origin_server_ts(*event); uint64_t ts = time.toMSecsSinceEpoch(); - emit manager_->updateRoomsLastMessage( - room_id_, + auto description = DescInfo{QString::fromStdString(mtx::accessors::event_id(*event)), QString::fromStdString(http::client()->user_id().to_string()), tr("You joined this room."), utils::descriptiveTime(time), ts, - time}); + time}; + if (description != lastMessage_) { + lastMessage_ = description; + emit manager_->updateRoomsLastMessage(room_id_, lastMessage_); + emit lastMessageChanged(); + } return; } if (!std::visit([](const auto &e) -> bool { return isMessage(e); }, *event)) @@ -884,7 +902,11 @@ TimelineModel::updateLastMessage() QString::fromStdString(http::client()->user_id().to_string()), cache::displayName(room_id_, QString::fromStdString(mtx::accessors::sender(*event)))); - emit manager_->updateRoomsLastMessage(room_id_, description); + if (description != lastMessage_) { + lastMessage_ = description; + emit manager_->updateRoomsLastMessage(room_id_, description); + emit lastMessageChanged(); + } return; } } -- cgit 1.5.1 From beeb60e4a12b47ae619e52629040aff5a8f43db2 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 22 May 2021 00:57:14 +0200 Subject: Sort the room list --- resources/qml/RoomList.qml | 2 +- src/timeline/RoomlistModel.cpp | 93 ++++++++++++++++++++++++++++++++++-- src/timeline/RoomlistModel.h | 26 ++++++++++ src/timeline/TimelineModel.cpp | 2 + src/timeline/TimelineModel.h | 2 +- src/timeline/TimelineViewManager.cpp | 4 +- 6 files changed, 120 insertions(+), 9 deletions(-) (limited to 'src/timeline/TimelineModel.cpp') diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index bb8deda6..f2a957c9 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -131,7 +131,7 @@ Page { Layout.alignment: Qt.AlignRight | Qt.AlignBottom font.pixelSize: fontMetrics.font.pixelSize * 0.9 color: roomItem.unimportantText - text: model.timestamp + text: model.time } } diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index 5fc4dc65..afe9679a 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -42,10 +42,13 @@ RoomlistModel::roleNames() const {RoomName, "roomName"}, {RoomId, "roomId"}, {LastMessage, "lastMessage"}, + {Time, "time"}, {Timestamp, "timestamp"}, {HasUnreadMessages, "hasUnreadMessages"}, {HasLoudNotification, "hasLoudNotification"}, {NotificationCount, "notificationCount"}, + {IsInvite, "isInvite"}, + {IsSpace, "isSpace"}, }; } @@ -64,8 +67,10 @@ RoomlistModel::data(const QModelIndex &index, int role) const return room->roomId(); case Roles::LastMessage: return room->lastMessage().body; - case Roles::Timestamp: + case Roles::Time: return room->lastMessage().descriptiveTime; + case Roles::Timestamp: + return QVariant(static_cast(room->lastMessage().timestamp)); case Roles::HasUnreadMessages: return this->roomReadStatus.count(roomid) && this->roomReadStatus.at(roomid); @@ -73,6 +78,9 @@ RoomlistModel::data(const QModelIndex &index, int role) const return room->hasMentions(); case Roles::NotificationCount: return room->notificationCount(); + case Roles::IsInvite: + case Roles::IsSpace: + return false; default: return {}; } @@ -90,9 +98,9 @@ RoomlistModel::updateReadStatus(const std::map roomReadStatus_) if (roomUnread != roomReadStatus[roomid]) { roomsToUpdate.push_back(this->roomidToIndex(roomid)); } - } - this->roomReadStatus = roomReadStatus_; + this->roomReadStatus[roomid] = roomUnread; + } for (auto idx : roomsToUpdate) { emit dataChanged(index(idx), @@ -135,6 +143,7 @@ RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification) Roles::LastMessage, Roles::Timestamp, Roles::NotificationCount, + Qt::DisplayRole, }); }); connect( @@ -162,6 +171,7 @@ RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification) { Roles::HasLoudNotification, Roles::NotificationCount, + Qt::DisplayRole, }); int total_unread_msgs = 0; @@ -225,7 +235,6 @@ RoomlistModel::initializeRooms(const std::vector &roomIds_) beginResetModel(); models.clear(); roomids.clear(); - roomids = roomIds_; for (const auto &id : roomIds_) addRoom(id, true); endResetModel(); @@ -239,3 +248,79 @@ RoomlistModel::clear() roomids.clear(); endResetModel(); } + +namespace { +enum NotificationImportance : short +{ + ImportanceDisabled = -1, + AllEventsRead = 0, + NewMessage = 1, + NewMentions = 2, + Invite = 3 +}; +} + +short int +FilteredRoomlistModel::calculateImportance(const QModelIndex &idx) const +{ + // Returns the degree of importance of the unread messages in the room. + // If sorting by importance is disabled in settings, this only ever + // returns ImportanceDisabled or Invite + if (sourceModel()->data(idx, RoomlistModel::IsInvite).toBool()) { + return Invite; + } else if (!this->sortByImportance) { + return ImportanceDisabled; + } else if (sourceModel()->data(idx, RoomlistModel::HasLoudNotification).toBool()) { + return NewMentions; + } else if (sourceModel()->data(idx, RoomlistModel::NotificationCount).toInt() > 0) { + return NewMessage; + } else { + return AllEventsRead; + } +} +bool +FilteredRoomlistModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + QModelIndex const left_idx = sourceModel()->index(left.row(), 0, QModelIndex()); + QModelIndex const right_idx = sourceModel()->index(right.row(), 0, QModelIndex()); + + // Sort by "importance" (i.e. invites before mentions before + // notifs before new events before old events), then secondly + // by recency. + + // Checking importance first + const auto a_importance = calculateImportance(left_idx); + const auto b_importance = calculateImportance(right_idx); + if (a_importance != b_importance) { + return a_importance > b_importance; + } + + // Now sort by recency + // Zero if empty, otherwise the time that the event occured + uint64_t a_recency = sourceModel()->data(left_idx, RoomlistModel::Timestamp).toULongLong(); + uint64_t b_recency = sourceModel()->data(right_idx, RoomlistModel::Timestamp).toULongLong(); + + if (a_recency != b_recency) + return a_recency > b_recency; + else + return left.row() < right.row(); +} + +FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *parent) + : QSortFilterProxyModel(parent) + , roomlistmodel(model) +{ + this->sortByImportance = UserSettings::instance()->sortByImportance(); + setSourceModel(model); + setDynamicSortFilter(true); + + QObject::connect(UserSettings::instance().get(), + &UserSettings::roomSortingChanged, + this, + [this](bool sortByImportance_) { + this->sortByImportance = sortByImportance_; + invalidate(); + }); + + sort(0); +} diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index c4c9d9ba..c3374bd2 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -24,10 +25,13 @@ public: RoomName, RoomId, LastMessage, + Time, Timestamp, HasUnreadMessages, HasLoudNotification, NotificationCount, + IsInvite, + IsSpace, }; RoomlistModel(TimelineViewManager *parent = nullptr); @@ -73,4 +77,26 @@ private: std::vector roomids; QHash> models; std::map roomReadStatus; + + friend class FilteredRoomlistModel; +}; + +class FilteredRoomlistModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + FilteredRoomlistModel(RoomlistModel *model, QObject *parent = nullptr); + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + +public slots: + int roomidToIndex(QString roomid) + { + return mapFromSource(roomlistmodel->index(roomlistmodel->roomidToIndex(roomid))) + .row(); + } + +private: + short int calculateImportance(const QModelIndex &idx) const; + RoomlistModel *roomlistmodel; + bool sortByImportance = true; }; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 19c3fb30..2625127c 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -318,6 +318,8 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj , room_id_(room_id) , manager_(manager) { + lastMessage_.timestamp = 0; + connect( this, &TimelineModel::redactionFailed, diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 5c1065cb..b3d3b663 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -382,7 +382,7 @@ private: QString eventIdToShow; int showEventTimerCounter = 0; - DescInfo lastMessage_; + DescInfo lastMessage_{}; friend struct SendMessageVisitor; diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index b0c13b03..c84e0df8 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -193,9 +193,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par }); qmlRegisterSingletonType( "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * { - auto ptr = self->rooms; - QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); - return ptr; + return new FilteredRoomlistModel(self->rooms); }); qmlRegisterSingletonType( "im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * { -- cgit 1.5.1 From f3d956aebcd34ecf8c4e2c44acd39d5de380233f Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 22 May 2021 10:16:42 +0200 Subject: Fix emoji in new RoomList --- resources/qml/ElidedLabel.qml | 2 +- resources/qml/RoomList.qml | 2 ++ src/timeline/RoomlistModel.cpp | 2 +- src/timeline/TimelineModel.cpp | 11 +++++++++++ src/timeline/TimelineModel.h | 1 + src/timeline/TimelineViewManager.h | 1 + 6 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/timeline/TimelineModel.cpp') diff --git a/resources/qml/ElidedLabel.qml b/resources/qml/ElidedLabel.qml index 5ae99de7..1f4aeeea 100644 --- a/resources/qml/ElidedLabel.qml +++ b/resources/qml/ElidedLabel.qml @@ -13,7 +13,7 @@ Label { property alias elideWidth: metrics.elideWidth color: Nheko.colors.text - text: metrics.elidedText + text: (textFormat == Text.PlainText) ? metrics.elidedText : TimelineManager.escapeEmoji(TimelineManager.htmlEscape(metrics.elidedText)) maximumLineCount: 1 elide: Text.ElideRight textFormat: Text.PlainText diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index f2a957c9..89af78a5 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -119,6 +119,7 @@ Page { color: roomItem.importantText elideWidth: textContent.width - timestamp.width - Nheko.paddingMedium fullText: model.roomName + textFormat: Text.RichText } Item { @@ -146,6 +147,7 @@ Page { font.pixelSize: fontMetrics.font.pixelSize * 0.9 elideWidth: textContent.width - (notificationBubble.visible ? notificationBubble.width : 0) - Nheko.paddingSmall fullText: model.lastMessage + textFormat: Text.RichText } Item { diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp index afe9679a..6d741322 100644 --- a/src/timeline/RoomlistModel.cpp +++ b/src/timeline/RoomlistModel.cpp @@ -62,7 +62,7 @@ RoomlistModel::data(const QModelIndex &index, int role) const case Roles::AvatarUrl: return room->roomAvatarUrl(); case Roles::RoomName: - return room->roomName(); + return room->plainRoomName(); case Roles::RoomId: return room->roomId(); case Roles::LastMessage: diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 2625127c..8f4a8564 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -1890,6 +1890,17 @@ TimelineModel::roomName() const QString::fromStdString(info[room_id_].name).toHtmlEscaped()); } +QString +TimelineModel::plainRoomName() const +{ + auto info = cache::getRoomInfo({room_id_.toStdString()}); + + if (!info.count(room_id_)) + return ""; + else + return QString::fromStdString(info[room_id_].name); +} + QString TimelineModel::roomAvatarUrl() const { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index b3d3b663..3ebbe120 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -307,6 +307,7 @@ public slots: } QString roomName() const; + QString plainRoomName() const; QString roomTopic() const; InputBar *input() { return &input_; } Permissions *permissions() { return &permissions_; } diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index f4297243..609f5a4a 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -67,6 +67,7 @@ public: Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId); Q_INVOKABLE QColor userColor(QString id, QColor background); Q_INVOKABLE QString escapeEmoji(QString str) const; + Q_INVOKABLE QString htmlEscape(QString str) const { return str.toHtmlEscaped(); } Q_INVOKABLE QString userPresence(QString id) const; Q_INVOKABLE QString userStatus(QString id) const; -- cgit 1.5.1 From 567078d39f3c85f260efd68aeb5c99f8e4ffe348 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 30 May 2021 01:09:16 +0200 Subject: Try to get rid of an allocation --- src/timeline/EventStore.cpp | 14 ++++++-------- src/timeline/EventStore.h | 2 +- src/timeline/TimelineModel.cpp | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src/timeline/TimelineModel.cpp') diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp index 883d384c..4a9f0fff 100644 --- a/src/timeline/EventStore.cpp +++ b/src/timeline/EventStore.cpp @@ -770,7 +770,7 @@ EventStore::decryptEvent(const IdIndex &idx, } mtx::events::collections::TimelineEvents * -EventStore::get(std::string_view id, std::string_view related_to, bool decrypt, bool resolve_edits) +EventStore::get(std::string id, std::string_view related_to, bool decrypt, bool resolve_edits) { if (this->thread() != QThread::currentThread()) nhlog::db()->warn("{} called from a different thread!", __func__); @@ -778,7 +778,7 @@ EventStore::get(std::string_view id, std::string_view related_to, bool decrypt, if (id.empty()) return nullptr; - IdIndex index{room_id_, std::string(id)}; + IdIndex index{room_id_, std::move(id)}; if (resolve_edits) { auto edits_ = edits(index.id); if (!edits_.empty()) { @@ -796,14 +796,12 @@ EventStore::get(std::string_view id, std::string_view related_to, bool decrypt, http::client()->get_event( room_id_, index.id, - [this, - relatedTo = std::string(related_to.data(), related_to.size()), - id = index.id](const mtx::events::collections::TimelineEvents &timeline, - mtx::http::RequestErr err) { + [this, relatedTo = std::string(related_to), id = index.id]( + const mtx::events::collections::TimelineEvents &timeline, + mtx::http::RequestErr err) { if (err) { nhlog::net()->error( - "Failed to retrieve event with id {}, which " - "was " + "Failed to retrieve event with id {}, which was " "requested to show the replyTo for event {}", relatedTo, id); diff --git a/src/timeline/EventStore.h b/src/timeline/EventStore.h index c7a7588b..d9bb86cb 100644 --- a/src/timeline/EventStore.h +++ b/src/timeline/EventStore.h @@ -70,7 +70,7 @@ public: // optionally returns the event or nullptr and fetches it, after which it emits a // relatedFetched event - mtx::events::collections::TimelineEvents *get(std::string_view id, + mtx::events::collections::TimelineEvents *get(std::string id, std::string_view related_to, bool decrypt = true, bool resolve_edits = true); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8f4a8564..cd3febd5 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -574,7 +574,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r !event_id(event).empty() && event_id(event).front() == '$'); case IsEncrypted: { auto id = event_id(event); - auto encrypted_event = events.get(id, id, false); + auto encrypted_event = events.get(id, "", false); return encrypted_event && std::holds_alternative< mtx::events::EncryptedEvent>( @@ -583,7 +583,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r case Trustlevel: { auto id = event_id(event); - auto encrypted_event = events.get(id, id, false); + auto encrypted_event = events.get(id, "", false); if (encrypted_event) { if (auto encrypted = std::get_if>( -- cgit 1.5.1 From d364c29c43dca128f516c5f7d4e925b27347f558 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 8 Jun 2021 22:18:51 +0200 Subject: Implement switching in narrow mode --- resources/qml/ChatPage.qml | 9 +++- resources/qml/RoomList.qml | 56 ++++++++++++++++++--- resources/qml/TimelineView.qml | 2 + resources/qml/TopBar.qml | 6 ++- resources/qml/components/AdaptiveLayout.qml | 75 ++++++++++++++--------------- src/timeline/RoomlistModel.h | 12 ++++- src/timeline/TimelineModel.cpp | 2 - src/timeline/TimelineViewManager.h | 24 --------- 8 files changed, 109 insertions(+), 77 deletions(-) (limited to 'src/timeline/TimelineModel.cpp') diff --git a/resources/qml/ChatPage.qml b/resources/qml/ChatPage.qml index e5b53738..0f884d75 100644 --- a/resources/qml/ChatPage.qml +++ b/resources/qml/ChatPage.qml @@ -14,8 +14,11 @@ Rectangle { color: Nheko.colors.window AdaptiveLayout { + id: adaptiveView + anchors.fill: parent singlePageMode: width < communityListC.maximumWidth + roomListC.maximumWidth + timlineViewC.minimumWidth + pageIndex: Rooms.currentRoom ? 2 : 1 AdaptiveLayoutElement { id: communityListC @@ -37,9 +40,12 @@ Rectangle { minimumWidth: Nheko.avatarSize * 5 + Nheko.paddingSmall * 2 preferredWidth: Nheko.avatarSize * 5 + Nheko.paddingSmall * 2 maximumWidth: Nheko.avatarSize * 10 + Nheko.paddingSmall * 2 - collapsedWidth: Nheko.avatarSize + Nheko.paddingSmall * 2 + collapsedWidth: roomlist.avatarSize + 2 * Nheko.paddingMedium RoomList { + id: roomlist + + collapsed: parent.collapsed } } @@ -52,6 +58,7 @@ Rectangle { TimelineView { id: timeline + showBackButton: adaptiveView.singlePageMode room: Rooms.currentRoom } diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index ce991dec..21973b77 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -13,6 +13,8 @@ import im.nheko 1.0 Page { //leftPadding: Nheko.paddingSmall //rightPadding: Nheko.paddingSmall + property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3) + property bool collapsed: false ListView { id: roomlist @@ -113,9 +115,11 @@ Page { property color bubbleText: Nheko.colors.highlightedText color: background - height: Math.ceil(fontMetrics.lineSpacing * 2.3 + Nheko.paddingMedium * 2) + height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width state: "normal" + ToolTip.visible: hovered.hovered && collapsed + ToolTip.text: model.roomName states: [ State { name: "highlight" @@ -148,7 +152,7 @@ Page { ] TapHandler { - margin: -2 + margin: -Nheko.paddingSmall acceptedButtons: Qt.RightButton onSingleTapped: { if (!TimelineManager.isInvite) @@ -159,7 +163,7 @@ Page { } TapHandler { - margin: -2 + margin: -Nheko.paddingSmall onSingleTapped: Rooms.setCurrentRoom(model.roomId) onLongPressed: { if (!TimelineManager.isInvite) @@ -169,8 +173,9 @@ Page { } HoverHandler { - margin: -2 id: hovered + + margin: -Nheko.paddingSmall } RowLayout { @@ -186,15 +191,46 @@ Page { enabled: false Layout.alignment: Qt.AlignVCenter - height: Math.ceil(fontMetrics.lineSpacing * 2.3) - width: Math.ceil(fontMetrics.lineSpacing * 2.3) + height: avatarSize + width: avatarSize url: model.avatarUrl.replace("mxc://", "image://MxcImage/") displayName: model.roomName + + Rectangle { + id: collapsedNotificationBubble + + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: -Nheko.paddingSmall + visible: collapsed && model.notificationCount > 0 + enabled: false + Layout.alignment: Qt.AlignRight + height: fontMetrics.averageCharacterWidth * 3 + width: height + radius: height / 2 + color: model.hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground + + Label { + anchors.centerIn: parent + width: parent.width * 0.8 + height: parent.height * 0.8 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: fontMetrics.font.pixelSize * 0.8 + color: model.hasLoudNotification ? "white" : roomItem.bubbleText + text: model.notificationCount > 99 ? "99+" : model.notificationCount + } + + } + } ColumnLayout { id: textContent + visible: !collapsed Layout.alignment: Qt.AlignLeft Layout.fillWidth: true Layout.minimumWidth: 100 @@ -396,7 +432,7 @@ Page { } TapHandler { - margin: -2 + margin: -Nheko.paddingSmall acceptedButtons: Qt.LeftButton onSingleTapped: userInfoPanel.openUserProfile() onLongPressed: userInfoMenu.open() @@ -404,7 +440,7 @@ Page { } TapHandler { - margin: -2 + margin: -Nheko.paddingSmall acceptedButtons: Qt.RightButton onSingleTapped: userInfoMenu.open() gesturePolicy: TapHandler.ReleaseWithinBounds @@ -431,6 +467,7 @@ Page { ColumnLayout { id: col + visible: !collapsed Layout.alignment: Qt.AlignLeft Layout.fillWidth: true width: parent.width - avatar.width - logoutButton.width - Nheko.paddingMedium * 2 @@ -462,6 +499,7 @@ Page { ImageButton { id: logoutButton + visible: !collapsed Layout.alignment: Qt.AlignVCenter image: ":/icons/icons/ui/power-button-off.png" ToolTip.visible: hovered @@ -533,6 +571,7 @@ Page { } ImageButton { + visible: !collapsed Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter hoverEnabled: true width: 22 @@ -544,6 +583,7 @@ Page { } ImageButton { + visible: !collapsed Layout.alignment: Qt.AlignBottom | Qt.AlignRight hoverEnabled: true width: 22 diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 747be61e..095103fa 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -19,6 +19,7 @@ Item { id: timelineView property var room: null + property bool showBackButton: false Label { visible: !room && !TimelineManager.isInitialSync @@ -45,6 +46,7 @@ Item { spacing: 0 TopBar { + showBackButton: timelineView.showBackButton } Rectangle { diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 65e27939..30ab2e7c 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -11,6 +11,8 @@ import im.nheko 1.0 Rectangle { id: topBar + property bool showBackButton: false + Layout.fillWidth: true implicitHeight: topLayout.height + Nheko.paddingMedium * 2 z: 3 @@ -43,11 +45,11 @@ Rectangle { Layout.alignment: Qt.AlignVCenter width: Nheko.avatarSize height: Nheko.avatarSize - visible: TimelineManager.isNarrowView + visible: showBackButton image: ":/icons/icons/ui/angle-pointing-to-left.png" ToolTip.visible: hovered ToolTip.text: qsTr("Back to room list") - onClicked: TimelineManager.backToRooms() + onClicked: Rooms.resetCurrentRoom() } Avatar { diff --git a/resources/qml/components/AdaptiveLayout.qml b/resources/qml/components/AdaptiveLayout.qml index e6416414..eea85e38 100644 --- a/resources/qml/components/AdaptiveLayout.qml +++ b/resources/qml/components/AdaptiveLayout.qml @@ -18,6 +18,43 @@ Container { property int splitterGrabMargin: Nheko.paddingSmall property int pageIndex: 0 property Component handle + property Component handleToucharea + + anchors.fill: parent + Component.onCompleted: { + for (var i = 0; i < count - 1; i++) { + let handle_ = handle.createObject(contentChildren[i]); + let split_ = handleToucharea.createObject(contentChildren[i]); + contentChildren[i].width = Qt.binding(function() { + return split_.calculatedWidth; + }); + contentChildren[i].splitterWidth = Qt.binding(function() { + return handle_.width; + }); + } + contentChildren[count - 1].width = Qt.binding(function() { + if (container.singlePageMode) { + return container.width; + } else { + var w = container.width; + for (var i = 0; i < count - 1; i++) { + if (contentChildren[i].width) + w = w - contentChildren[i].width; + + } + return w; + } + }); + contentChildren[count - 1].splitterWidth = 0; + for (var i = 0; i < count; i++) { + contentChildren[i].height = Qt.binding(function() { + return container.height; + }); + contentChildren[i].children[0].height = Qt.binding(function() { + return container.height; + }); + } + } handle: Rectangle { z: 3 @@ -27,8 +64,6 @@ Container { anchors.right: parent.right } - property Component handleToucharea - handleToucharea: Item { id: splitter @@ -79,42 +114,6 @@ Container { } - anchors.fill: parent - Component.onCompleted: { - for (var i = 0; i < count - 1; i++) { - let handle_ = handle.createObject(contentChildren[i]); - let split_ = handleToucharea.createObject(contentChildren[i]); - contentChildren[i].width = Qt.binding(function() { - return split_.calculatedWidth; - }); - contentChildren[i].splitterWidth = Qt.binding(function() { - return handle_.width; - }); - } - contentChildren[count - 1].width = Qt.binding(function() { - if (container.singlePageMode) { - return container.width; - } else { - var w = container.width; - for (var i = 0; i < count - 1; i++) { - if (contentChildren[i].width) - w = w - contentChildren[i].width; - - } - return w; - } - }); - contentChildren[count - 1].splitterWidth = 0; - for (var i = 0; i < count; i++) { - contentChildren[i].height = Qt.binding(function() { - return container.height; - }); - contentChildren[i].children[0].height = Qt.binding(function() { - return container.height; - }); - } - } - contentItem: ListView { id: view diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h index d3e1e1f9..fa991f6b 100644 --- a/src/timeline/RoomlistModel.h +++ b/src/timeline/RoomlistModel.h @@ -21,7 +21,8 @@ class TimelineViewManager; class RoomlistModel : public QAbstractListModel { Q_OBJECT - Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged) + Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET + resetCurrentRoom) public: enum Roles { @@ -73,6 +74,11 @@ public slots: void leave(QString roomid); TimelineModel *currentRoom() const { return currentRoom_.get(); } void setCurrentRoom(QString roomid); + void resetCurrentRoom() + { + currentRoom_ = nullptr; + emit currentRoomChanged(); + } private slots: void updateReadStatus(const std::map roomReadStatus_); @@ -98,7 +104,8 @@ private: class FilteredRoomlistModel : public QSortFilterProxyModel { Q_OBJECT - Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged) + Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET + resetCurrentRoom) public: FilteredRoomlistModel(RoomlistModel *model, QObject *parent = nullptr); bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; @@ -117,6 +124,7 @@ public slots: TimelineModel *currentRoom() const { return roomlistmodel->currentRoom(); } void setCurrentRoom(QString roomid) { roomlistmodel->setCurrentRoom(std::move(roomid)); } + void resetCurrentRoom() { roomlistmodel->resetCurrentRoom(); } void nextRoom(); void previousRoom(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index cd3febd5..f29f929e 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -891,7 +891,6 @@ TimelineModel::updateLastMessage() time}; if (description != lastMessage_) { lastMessage_ = description; - emit manager_->updateRoomsLastMessage(room_id_, lastMessage_); emit lastMessageChanged(); } return; @@ -906,7 +905,6 @@ TimelineModel::updateLastMessage() QString::fromStdString(mtx::accessors::sender(*event)))); if (description != lastMessage_) { lastMessage_ = description; - emit manager_->updateRoomsLastMessage(room_id_, description); emit lastMessageChanged(); } return; diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index c4707208..68d9cd1b 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -37,8 +37,6 @@ class TimelineViewManager : public QObject Q_PROPERTY( bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) - Q_PROPERTY( - bool isNarrowView MEMBER isNarrowView_ READ isNarrowView NOTIFY narrowViewChanged) Q_PROPERTY( bool isWindowFocused MEMBER isWindowFocused_ READ isWindowFocused NOTIFY focusChanged) @@ -54,7 +52,6 @@ public: void clearAll() { rooms_->clear(); } Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } - bool isNarrowView() const { return isNarrowView_; } bool isWindowFocused() const { return isWindowFocused_; } Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId); Q_INVOKABLE QColor userColor(QString id, QColor background); @@ -74,16 +71,12 @@ public: void verifyDevice(QString userid, QString deviceid); signals: - void clearRoomMessageCount(QString roomid); - void updateRoomsLastMessage(QString roomid, const DescInfo &info); void activeTimelineChanged(TimelineModel *timeline); void initialSyncChanged(bool isInitialSync); void replyingEventChanged(QString replyingEvent); void replyClosed(); void newDeviceVerificationRequest(DeviceVerificationFlow *flow); void inviteUsers(QStringList users); - void showRoomList(); - void narrowViewChanged(); void focusChanged(); void focusInput(); void openImageOverlayInternalCb(QString eventId, QImage img); @@ -113,22 +106,6 @@ public slots: void setVideoCallItem(); - void enableBackButton() - { - if (isNarrowView_) - return; - isNarrowView_ = true; - emit narrowViewChanged(); - } - void disableBackButton() - { - if (!isNarrowView_) - return; - isNarrowView_ = false; - emit narrowViewChanged(); - } - - void backToRooms() { emit showRoomList(); } QObject *completerFor(QString completerName, QString roomId = ""); void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); @@ -152,7 +129,6 @@ private: CallManager *callManager_ = nullptr; bool isInitialSync_ = true; - bool isNarrowView_ = false; bool isWindowFocused_ = false; RoomlistModel *rooms_ = nullptr; -- cgit 1.5.1