Add button to view pinned messages in a room

BUG: 497427
This commit is contained in:
Joshua Goins
2024-12-24 20:48:07 -05:00
parent c315e817b2
commit 1b0c6c2847
5 changed files with 215 additions and 0 deletions

View File

@@ -194,6 +194,8 @@ add_library(neochat STATIC
models/messagemodel.h
models/messagecontentfiltermodel.cpp
models/messagecontentfiltermodel.h
models/pinnedmessagemodel.cpp
models/pinnedmessagemodel.h
)
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
@@ -249,6 +251,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
qml/MessageSourceSheet.qml
qml/ConfirmEncryptionDialog.qml
qml/RoomSearchPage.qml
qml/RoomPinnedMessagesPage.qml
qml/LocationChooser.qml
qml/TimelineView.qml
qml/InvitationView.qml
@@ -534,6 +537,7 @@ if(ANDROID)
"list-remove-symbolic"
"edit-delete"
"user-home-symbolic"
"pin-symbolic"
)
ecm_add_android_apk(neochat-app ANDROID_DIR ${CMAKE_SOURCE_DIR}/android)
else()

View File

@@ -0,0 +1,67 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
#include "pinnedmessagemodel.h"
#include "enums/delegatetype.h"
#include "eventhandler.h"
#include "models/messagecontentmodel.h"
#include "neochatroom.h"
#include <QGuiApplication>
#include <KLocalizedString>
using namespace Quotient;
PinnedMessageModel::PinnedMessageModel(QObject *parent)
: MessageModel(parent)
{
connect(this, &MessageModel::roomChanged, this, &PinnedMessageModel::fill);
}
bool PinnedMessageModel::loading() const
{
return m_loading;
}
int PinnedMessageModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_pinnedEvents.size();
}
std::optional<std::reference_wrapper<const Quotient::RoomEvent>> PinnedMessageModel::getEventForIndex(const QModelIndex index) const
{
if (static_cast<size_t>(index.row()) >= m_pinnedEvents.size() || index.row() < 0) {
return std::nullopt;
}
return std::reference_wrapper{*m_pinnedEvents[index.row()].get()};
}
void PinnedMessageModel::setLoading(bool loading)
{
m_loading = loading;
Q_EMIT loadingChanged();
}
void PinnedMessageModel::fill()
{
if (!m_room) {
return;
}
const auto events = m_room->pinnedEventIds();
for (const auto &event : std::as_const(events)) {
auto job = m_room->connection()->callApi<GetOneRoomEventJob>(m_room->id(), event);
connect(job, &BaseJob::success, this, [this, job] {
beginInsertRows({}, m_pinnedEvents.size(), m_pinnedEvents.size());
m_pinnedEvents.push_back(std::move(fromJson<event_ptr_tt<RoomEvent>>(job->jsonData())));
Q_EMIT newEventAdded(m_pinnedEvents.back().get(), false);
endInsertRows();
});
}
}
#include "moc_pinnedmessagemodel.cpp"

View File

@@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
#pragma once
#include <QAbstractListModel>
#include <QQmlEngine>
#include <QString>
#include <Quotient/csapi/rooms.h>
#include "messagemodel.h"
#include "neochatroommember.h"
namespace Quotient
{
class Connection;
}
class NeoChatRoom;
/**
* @class PinnedMessageModel
*
* This class defines the model for visualising a room's pinned messages.
*/
class PinnedMessageModel : public MessageModel
{
Q_OBJECT
QML_ELEMENT
/**
* @brief Whether the model is currently loading.
*/
Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
public:
explicit PinnedMessageModel(QObject *parent = nullptr);
/**
* @brief Number of rows in the model.
*
* @sa QAbstractItemModel::rowCount
*/
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool loading() const;
Q_SIGNALS:
void loadingChanged();
protected:
std::optional<std::reference_wrapper<const Quotient::RoomEvent>> getEventForIndex(QModelIndex index) const override;
private:
void setLoading(bool loading);
void fill();
bool m_loading = false;
std::vector<Quotient::event_ptr_tt<Quotient::RoomEvent>> m_pinnedEvents;
};

View File

@@ -130,6 +130,24 @@ QQC2.ScrollView {
Layout.fillWidth: true
}
Delegates.RoundedItemDelegate {
id: pinnedMessagesButton
visible: !root.room.isSpace
icon.name: "pin-symbolic"
text: i18nc("@action:button", "Pinned messages")
activeFocusOnTab: true
Layout.fillWidth: true
onClicked: {
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomPinnedMessagesPage'), {
room: root.room
}, {
title: i18nc("@title", "Pinned Messages")
});
}
}
Delegates.RoundedItemDelegate {
id: leaveButton
icon.name: "arrow-left-symbolic"

View File

@@ -0,0 +1,64 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.neochat
import org.kde.neochat.timeline
/**
* @brief Component for showing the pinned messages in a room.
*/
Kirigami.ScrollablePage {
id: root
/**
* @brief The room to show the pinned messages for.
*/
required property NeoChatRoom room
title: i18nc("@title", "Pinned Messages")
Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false
ListView {
id: listView
spacing: 0
model: PinnedMessageModel {
id: pinModel
room: root.room
}
delegate: EventDelegate {
room: root.room
}
section.property: "section"
Kirigami.PlaceholderMessage {
icon.name: "pin-symbolic"
anchors.centerIn: parent
text: i18nc("@info:placeholder", "No Pinned Messages")
visible: listView.count === 0
}
Kirigami.LoadingPlaceholder {
anchors.centerIn: parent
visible: listView.count === 0 && pinModel.loading
}
Keys.onUpPressed: {
if (listView.currentIndex > 0) {
listView.decrementCurrentIndex();
} else {
listView.currentIndex = -1; // This is so the list view doesn't appear to have two selected items
listView.headerItem.forceActiveFocus(Qt.TabFocusReason);
}
}
}
}