Make it so that the menus for individual thread messages can be accessed

This is mostly just for text type messages at the moment but give the framework so that when other message types can be sent in threads they can be added easily
This commit is contained in:
James Graham
2025-03-15 16:03:27 +00:00
parent 4a800f99e1
commit 24235174fd
11 changed files with 137 additions and 50 deletions

View File

@@ -82,6 +82,38 @@ void MessageAttached::setMaxContentWidth(qreal maxContentWidth)
Q_EMIT maxContentWidthChanged(); Q_EMIT maxContentWidthChanged();
} }
QString MessageAttached::selectedText() const
{
return m_selectedText;
}
void MessageAttached::setSelectedText(const QString &selectedTest)
{
m_explicitSelectedText = true;
if (m_selectedText == selectedTest) {
return;
}
m_selectedText = selectedTest;
propagateMessage(this);
Q_EMIT selectedTextChanged();
}
QString MessageAttached::hoveredLink() const
{
return m_hoveredLink;
}
void MessageAttached::setHoveredLink(const QString &hoveredLink)
{
m_explicitHoveredLink = true;
if (m_hoveredLink == hoveredLink) {
return;
}
m_hoveredLink = hoveredLink;
propagateMessage(this);
Q_EMIT hoveredLinkChanged();
}
void MessageAttached::propagateMessage(MessageAttached *message) void MessageAttached::propagateMessage(MessageAttached *message)
{ {
if (m_explicitRoom || m_room != message->room()) { if (m_explicitRoom || m_room != message->room()) {
@@ -104,6 +136,16 @@ void MessageAttached::propagateMessage(MessageAttached *message)
Q_EMIT maxContentWidthChanged(); Q_EMIT maxContentWidthChanged();
} }
if (m_explicitSelectedText || m_selectedText != message->selectedText()) {
m_selectedText = message->selectedText();
Q_EMIT selectedTextChanged();
}
if (m_explicitHoveredLink || m_hoveredLink != message->hoveredLink()) {
m_hoveredLink = message->hoveredLink();
Q_EMIT hoveredLinkChanged();
}
const auto styles = attachedChildren(); const auto styles = attachedChildren();
for (auto *child : attachedChildren()) { for (auto *child : attachedChildren()) {
MessageAttached *message = qobject_cast<MessageAttached *>(child); MessageAttached *message = qobject_cast<MessageAttached *>(child);

View File

@@ -36,6 +36,16 @@ class MessageAttached : public QQuickAttachedPropertyPropagator
*/ */
Q_PROPERTY(qreal maxContentWidth READ maxContentWidth WRITE setMaxContentWidth NOTIFY maxContentWidthChanged FINAL) Q_PROPERTY(qreal maxContentWidth READ maxContentWidth WRITE setMaxContentWidth NOTIFY maxContentWidthChanged FINAL)
/**
* @brief The current selected message text.
*/
Q_PROPERTY(QString selectedText READ selectedText WRITE setSelectedText NOTIFY selectedTextChanged FINAL)
/**
* @brief The text of a hovered link if any.
*/
Q_PROPERTY(QString hoveredLink READ hoveredLink WRITE setHoveredLink NOTIFY hoveredLinkChanged FINAL)
public: public:
explicit MessageAttached(QObject *parent = nullptr); explicit MessageAttached(QObject *parent = nullptr);
@@ -53,11 +63,19 @@ public:
qreal maxContentWidth() const; qreal maxContentWidth() const;
void setMaxContentWidth(qreal maxContentWidth); void setMaxContentWidth(qreal maxContentWidth);
QString selectedText() const;
void setSelectedText(const QString &selectedTest);
QString hoveredLink() const;
void setHoveredLink(const QString &hoveredLink);
Q_SIGNALS: Q_SIGNALS:
void roomChanged(); void roomChanged();
void timelineChanged(); void timelineChanged();
void indexChanged(); void indexChanged();
void maxContentWidthChanged(); void maxContentWidthChanged();
void selectedTextChanged();
void hoveredLinkChanged();
protected: protected:
void propagateMessage(MessageAttached *message); void propagateMessage(MessageAttached *message);
@@ -70,9 +88,15 @@ private:
QPointer<QQuickItem> m_timeline; QPointer<QQuickItem> m_timeline;
bool m_explicitTimeline = false; bool m_explicitTimeline = false;
int m_index; int m_index = -1;
bool m_explicitIndex = false; bool m_explicitIndex = false;
qreal m_maxContentWidth = -1; qreal m_maxContentWidth = -1;
bool m_explicitMaxContentWidth = false; bool m_explicitMaxContentWidth = false;
QString m_selectedText = {};
bool m_explicitSelectedText = false;
QString m_hoveredLink = {};
bool m_explicitHoveredLink = false;
}; };

View File

@@ -12,6 +12,11 @@ import org.kde.neochat
RowLayout { RowLayout {
id: root id: root
/**
* @brief The matrix ID of the message event.
*/
required property string eventId
/** /**
* @brief The message author. * @brief The message author.
* *
@@ -68,4 +73,16 @@ RowLayout {
id: timeHoverHandler id: timeHoverHandler
} }
} }
TapHandler {
acceptedButtons: Qt.LeftButton
acceptedDevices: PointerDevice.TouchScreen
onLongPressed: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
}
TapHandler {
acceptedButtons: Qt.RightButton
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
gesturePolicy: TapHandler.WithinBounds
onTapped: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
}
} }

View File

@@ -25,11 +25,6 @@ DelegateChooser {
*/ */
signal hoveredLinkChanged(string hoveredLink) signal hoveredLinkChanged(string hoveredLink)
/**
* @brief Request a context menu be show for the message.
*/
signal showMessageMenu
signal removeLinkPreview(int index) signal removeLinkPreview(int index)
/** /**
@@ -49,7 +44,6 @@ DelegateChooser {
delegate: TextComponent { delegate: TextComponent {
onSelectedTextChanged: root.selectedTextChanged(selectedText) onSelectedTextChanged: root.selectedTextChanged(selectedText)
onHoveredLinkChanged: root.hoveredLinkChanged(hoveredLink) onHoveredLinkChanged: root.hoveredLinkChanged(hoveredLink)
onShowMessageMenu: root.showMessageMenu()
} }
} }
@@ -69,7 +63,6 @@ DelegateChooser {
onSelectedTextChanged: selectedText => { onSelectedTextChanged: selectedText => {
root.selectedTextChanged(selectedText); root.selectedTextChanged(selectedText);
} }
onShowMessageMenu: root.showMessageMenu()
} }
} }
@@ -79,7 +72,6 @@ DelegateChooser {
onSelectedTextChanged: selectedText => { onSelectedTextChanged: selectedText => {
root.selectedTextChanged(selectedText); root.selectedTextChanged(selectedText);
} }
onShowMessageMenu: root.showMessageMenu()
} }
} }

View File

@@ -97,7 +97,6 @@ QQC2.Control {
onHoveredLinkChanged: hoveredLink => { onHoveredLinkChanged: hoveredLink => {
root.hoveredLinkChanged(hoveredLink); root.hoveredLinkChanged(hoveredLink);
} }
onShowMessageMenu: root.showMessageMenu()
onRemoveLinkPreview: index => root.contentModel.closeLinkPreview(index) onRemoveLinkPreview: index => root.contentModel.closeLinkPreview(index)
} }
} }

View File

@@ -13,6 +13,11 @@ import org.kde.neochat
QQC2.Control { QQC2.Control {
id: root id: root
/**
* @brief The matrix ID of the message event.
*/
required property string eventId
/** /**
* @brief The message author. * @brief The message author.
* *
@@ -42,11 +47,6 @@ QQC2.Control {
*/ */
signal selectedTextChanged(string selectedText) signal selectedTextChanged(string selectedText)
/**
* @brief Request a context menu be show for the message.
*/
signal showMessageMenu
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.maximumWidth: Message.maxContentWidth Layout.maximumWidth: Message.maxContentWidth
@@ -129,7 +129,7 @@ QQC2.Control {
TapHandler { TapHandler {
acceptedDevices: PointerDevice.TouchScreen acceptedDevices: PointerDevice.TouchScreen
onLongPressed: root.showMessageMenu() onLongPressed: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
} }
background: null background: null

View File

@@ -14,6 +14,13 @@ BaseMessageComponentChooser {
DelegateChoice { DelegateChoice {
roleValue: MessageComponentType.ThreadBody roleValue: MessageComponentType.ThreadBody
delegate: ThreadBodyComponent {} delegate: ThreadBodyComponent {
onSelectedTextChanged: selectedText => {
root.selectedTextChanged(selectedText);
}
onHoveredLinkChanged: hoveredLink => {
root.hoveredLinkChanged(hoveredLink);
}
}
} }
} }

View File

@@ -166,16 +166,6 @@ TimelineDelegate {
*/ */
property bool isTemporaryHighlighted: false property bool isTemporaryHighlighted: false
/**
* @brief The user selected text.
*/
property string selectedText: ""
/**
* @brief The user hovered link.
*/
property string hoveredLink: ""
onIsTemporaryHighlightedChanged: if (isTemporaryHighlighted) { onIsTemporaryHighlightedChanged: if (isTemporaryHighlighted) {
temporaryHighlightTimer.start(); temporaryHighlightTimer.start();
} }
@@ -293,12 +283,11 @@ TimelineDelegate {
isPending: root.isPending isPending: root.isPending
onSelectedTextChanged: selectedText => { onSelectedTextChanged: selectedText => {
root.selectedText = selectedText; root.Message.selectedText = selectedText;
} }
onHoveredLinkChanged: hoveredLink => { onHoveredLinkChanged: hoveredLink => {
root.hoveredLink = hoveredLink; root.Message.hoveredLink = hoveredLink;
} }
onShowMessageMenu: _private.showMessageMenu()
showBackground: root.cardBackground && !NeoChatConfig.compactLayout showBackground: root.cardBackground && !NeoChatConfig.compactLayout
} }
@@ -358,7 +347,7 @@ TimelineDelegate {
property bool showUserMessageOnRight: NeoChatConfig.showLocalMessagesOnRight && root.author.isLocalMember && !NeoChatConfig.compactLayout && !root.alwaysFillWidth && !root.isThreaded property bool showUserMessageOnRight: NeoChatConfig.showLocalMessagesOnRight && root.author.isLocalMember && !NeoChatConfig.compactLayout && !root.alwaysFillWidth && !root.isThreaded
function showMessageMenu() { function showMessageMenu() {
RoomManager.viewEventMenu(root.eventId, root.room, root.author, root.selectedText, root.hoveredLink); RoomManager.viewEventMenu(root.eventId, root.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
} }
} }
} }

View File

@@ -12,6 +12,20 @@ import org.kde.neochat
QQC2.Control { QQC2.Control {
id: root id: root
/**
* @brief The matrix ID of the message event.
*/
required property string eventId
/**
* @brief The message author.
*
* A Quotient::RoomMember object.
*
* @sa Quotient::RoomMember
*/
required property NeochatRoomMember author
/** /**
* @brief The display text of the message. * @brief The display text of the message.
*/ */
@@ -22,11 +36,6 @@ QQC2.Control {
*/ */
signal selectedTextChanged(string selectedText) signal selectedTextChanged(string selectedText)
/**
* @brief Request a context menu be show for the message.
*/
signal showMessageMenu
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.maximumWidth: Message.maxContentWidth Layout.maximumWidth: Message.maxContentWidth
@@ -54,7 +63,7 @@ QQC2.Control {
enabled: !quoteText.hoveredLink enabled: !quoteText.hoveredLink
acceptedDevices: PointerDevice.TouchScreen acceptedDevices: PointerDevice.TouchScreen
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
onLongPressed: root.showMessageMenu() onLongPressed: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
} }
} }

View File

@@ -15,6 +15,20 @@ import org.kde.neochat
TextEdit { TextEdit {
id: root id: root
/**
* @brief The matrix ID of the message event.
*/
required property string eventId
/**
* @brief The message author.
*
* A Quotient::RoomMember object.
*
* @sa Quotient::RoomMember
*/
required property NeochatRoomMember author
/** /**
* @brief The display text of the message. * @brief The display text of the message.
*/ */
@@ -35,11 +49,6 @@ TextEdit {
*/ */
property bool spoilerRevealed: !hasSpoiler.test(display) property bool spoilerRevealed: !hasSpoiler.test(display)
/**
* @brief Request a context menu be show for the message.
*/
signal showMessageMenu
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.maximumWidth: Message.maxContentWidth Layout.maximumWidth: Message.maxContentWidth
@@ -119,7 +128,6 @@ a{
HoverHandler { HoverHandler {
cursorShape: (root.hoveredLink || !spoilerRevealed) ? Qt.PointingHandCursor : Qt.IBeamCursor cursorShape: (root.hoveredLink || !spoilerRevealed) ? Qt.PointingHandCursor : Qt.IBeamCursor
} }
TapHandler { TapHandler {
enabled: !root.hoveredLink && !spoilerRevealed enabled: !root.hoveredLink && !spoilerRevealed
onTapped: spoilerRevealed = true onTapped: spoilerRevealed = true
@@ -128,6 +136,12 @@ a{
enabled: !root.hoveredLink enabled: !root.hoveredLink
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
acceptedDevices: PointerDevice.TouchScreen acceptedDevices: PointerDevice.TouchScreen
onLongPressed: root.showMessageMenu() onLongPressed: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
}
TapHandler {
acceptedButtons: Qt.RightButton
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
gesturePolicy: TapHandler.WithinBounds
onTapped: RoomManager.viewEventMenu(root.eventId, root.Message.room, root.author, root.Message.selectedText, root.Message.hoveredLink);
} }
} }

View File

@@ -31,11 +31,6 @@ ColumnLayout {
*/ */
signal hoveredLinkChanged(string hoveredLink) signal hoveredLinkChanged(string hoveredLink)
/**
* @brief Request a context menu be show for the message.
*/
signal showMessageMenu
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.maximumWidth: Message.maxContentWidth Layout.maximumWidth: Message.maxContentWidth
@@ -52,7 +47,6 @@ ColumnLayout {
onHoveredLinkChanged: hoveredLink => { onHoveredLinkChanged: hoveredLink => {
root.hoveredLinkChanged(hoveredLink); root.hoveredLinkChanged(hoveredLink);
} }
onShowMessageMenu: root.showMessageMenu()
onRemoveLinkPreview: index => threadRepeater.model.closeLinkPreview(index) onRemoveLinkPreview: index => threadRepeater.model.closeLinkPreview(index)
onFetchMoreEvents: threadRepeater.model.fetchMoreEvents(5) onFetchMoreEvents: threadRepeater.model.fetchMoreEvents(5)
} }