From f626de04470de57d5443737804739cff27416d04 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Thu, 29 Apr 2021 21:46:49 +0200 Subject: [PATCH] Copy link to message fixes #499 --- CMakeLists.txt | 2 ++ resources/qml/TimelineView.qml | 7 +++++ src/Clipboard.cpp | 23 +++++++++++++++ src/Clipboard.h | 18 ++++++++++++ src/timeline/TimelineModel.cpp | 44 ++++++++++++++++++++++++++++ src/timeline/TimelineModel.h | 1 + src/timeline/TimelineViewManager.cpp | 5 ++++ 7 files changed, 100 insertions(+) create mode 100644 src/Clipboard.cpp create mode 100644 src/Clipboard.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 468480d8..70b74602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -306,6 +306,7 @@ set(SRC_FILES src/CallDevices.cpp src/CallManager.cpp src/ChatPage.cpp + src/Clipboard.cpp src/ColorImageProvider.cpp src/CommunitiesList.cpp src/CommunitiesListItem.cpp @@ -526,6 +527,7 @@ qt5_wrap_cpp(MOC_HEADERS src/CallDevices.h src/CallManager.h src/ChatPage.h + src/Clipboard.h src/CommunitiesList.h src/CommunitiesListItem.h src/CompletionProxyModel.h diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 81ca7705..59a98bdb 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -177,6 +177,13 @@ Page { enabled: visible text: qsTr("Open in external program") onTriggered: TimelineManager.timeline.openMedia(messageContextMenu.eventId) + } + + Platform.MenuItem { + visible: messageContextMenu.eventId + enabled: visible + text: qsTr("Copy link to event") + onTriggered: TimelineManager.timeline.copyLinkToEvent(messageContextMenu.eventId) } } diff --git a/src/Clipboard.cpp b/src/Clipboard.cpp new file mode 100644 index 00000000..720f30fd --- /dev/null +++ b/src/Clipboard.cpp @@ -0,0 +1,23 @@ +#include "Clipboard.h" + +#include +#include + +Clipboard::Clipboard(QObject *parent) + : QObject(parent) +{ + connect( + QGuiApplication::clipboard(), &QClipboard::dataChanged, this, &Clipboard::textChanged); +} + +void +Clipboard::setText(QString text) +{ + QGuiApplication::clipboard()->setText(text); +} + +QString +Clipboard::text() const +{ + return QGuiApplication::clipboard()->text(); +} diff --git a/src/Clipboard.h b/src/Clipboard.h new file mode 100644 index 00000000..6d0dc2f0 --- /dev/null +++ b/src/Clipboard.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +class Clipboard : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + +public: + Clipboard(QObject *parent = nullptr); + + QString text() const; + void setText(QString text_); +signals: + void textChanged(); +}; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 5a0f9bad..2f7bfdd2 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -9,13 +9,16 @@ #include #include +#include #include #include +#include #include #include #include #include +#include "Cache_p.h" #include "ChatPage.h" #include "Config.h" #include "EventAccessors.h" @@ -1336,6 +1339,47 @@ TimelineModel::scrollTimerEvent() } } +void +TimelineModel::copyLinkToEvent(QString eventId) const +{ + QStringList vias; + + auto alias = cache::client()->getRoomAliases(room_id_.toStdString()); + QString room; + if (alias) { + room = QString::fromStdString(alias->alias); + if (room.isEmpty() && !alias->alt_aliases.empty()) { + room = QString::fromStdString(alias->alt_aliases.front()); + } + } + + if (room.isEmpty()) + room = room_id_; + + vias.push_back(QString("via=%1").arg(QString( + QUrl::toPercentEncoding(QString::fromStdString(http::client()->user_id().hostname()))))); + auto members = cache::getMembers(room_id_.toStdString(), 0, 100); + for (const auto &m : members) { + if (vias.size() >= 4) + break; + + auto user_id = + mtx::identifiers::parse(m.user_id.toStdString()); + QString server = QString("via=%1").arg( + QString(QUrl::toPercentEncoding(QString::fromStdString(user_id.hostname())))); + + if (!vias.contains(server)) + vias.push_back(server); + } + + auto link = QString("https://matrix.to/#/%1/%2?%3") + .arg(QString(QUrl::toPercentEncoding(room)), + QString(QUrl::toPercentEncoding(eventId)), + vias.join('&')); + + QGuiApplication::clipboard()->setText(link); +} + QString TimelineModel::formatTypingUsers(const std::vector &users, QColor bg) { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index f46409b3..4dbb1c08 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -235,6 +235,7 @@ public: Q_INVOKABLE void cacheMedia(QString eventId); Q_INVOKABLE bool saveMedia(QString eventId) const; Q_INVOKABLE void showEvent(QString eventId); + Q_INVOKABLE void copyLinkToEvent(QString eventId) const; void cacheMedia(QString eventId, std::function callback); std::vector<::Reaction> reactions(const std::string &event_id) diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 99f0b86e..decd245c 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -14,6 +14,7 @@ #include "BlurhashProvider.h" #include "ChatPage.h" +#include "Clipboard.h" #include "ColorImageProvider.h" #include "CompletionProxyModel.h" #include "DelegateChooser.h" @@ -214,6 +215,10 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership); return ptr; }); + qmlRegisterSingletonType( + "im.nheko", 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) -> QObject * { + return new Clipboard(); + }); qRegisterMetaType(); qRegisterMetaType>();