summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeepBlueV7.X <nicolas.werner@hotmail.de>2021-09-17 10:19:58 +0000
committerGitHub <noreply@github.com>2021-09-17 10:19:58 +0000
commite118f3882d54a6f84885ab492704104848e5d346 (patch)
treed65763df4d31d87fa030f9d40992ab9f5ced09ef
parentAdded a text field that allows choosing custom homeserver in "Room directory"... (diff)
parentImprovements for linking to events (diff)
downloadnheko-e118f3882d54a6f84885ab492704104848e5d346.tar.xz
Merge pull request #728 from Thulinma/goto
Improvements for linking to events
-rw-r--r--resources/qml/MessageView.qml5
-rw-r--r--src/ChatPage.cpp71
-rw-r--r--src/ChatPage.h4
-rw-r--r--src/timeline/InputBar.cpp17
-rw-r--r--src/timeline/TimelineModel.cpp16
-rw-r--r--src/ui/NhekoGlobalObject.cpp44
6 files changed, 101 insertions, 56 deletions
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index e6ac9662..60c04098 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -20,6 +20,9 @@ ScrollView {
 
     ListView {
         id: chat
+        
+        displayMarginBeginning: height/2
+        displayMarginEnd: height/2
 
         property int delegateMaxWidth: ((Settings.timelineMaxWidth > 100 && Settings.timelineMaxWidth < parent.availableWidth) ? Settings.timelineMaxWidth : parent.availableWidth) - parent.padding * 2
 
@@ -276,7 +279,7 @@ ScrollView {
                         }
 
                         function onScrollToIndex(index) {
-                            chat.positionViewAtIndex(index, ListView.Visible);
+                            chat.positionViewAtIndex(index, ListView.Center);
                         }
 
                         target: chat.model
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index a07a9654..3887f8b8 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -1233,14 +1233,58 @@ mxidFromSegments(QStringRef sigil, QStringRef mxid)
         }
 }
 
-void
+bool
 ChatPage::handleMatrixUri(const QByteArray &uri)
 {
         nhlog::ui()->info("Received uri! {}", uri.toStdString());
         QUrl uri_{QString::fromUtf8(uri)};
 
+        // Convert matrix.to URIs to proper format
+        if (uri_.scheme() == "https" && uri_.host() == "matrix.to") {
+                QString p = uri_.fragment(QUrl::FullyEncoded);
+                if (p.startsWith("/"))
+                        p.remove(0, 1);
+
+                auto temp = p.split("?");
+                QString query;
+                if (temp.size() >= 2)
+                        query = QUrl::fromPercentEncoding(temp.takeAt(1).toUtf8());
+
+                temp            = temp.first().split("/");
+                auto identifier = QUrl::fromPercentEncoding(temp.takeFirst().toUtf8());
+                QString eventId = QUrl::fromPercentEncoding(temp.join('/').toUtf8());
+                if (!identifier.isEmpty()) {
+                        if (identifier.startsWith("@")) {
+                                QByteArray newUri =
+                                  "matrix:u/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
+                                if (!query.isEmpty())
+                                        newUri.append("?" + query.toUtf8());
+                                return handleMatrixUri(QUrl::fromEncoded(newUri));
+                        } else if (identifier.startsWith("#")) {
+                                QByteArray newUri =
+                                  "matrix:r/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
+                                if (!eventId.isEmpty())
+                                        newUri.append(
+                                          "/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
+                                if (!query.isEmpty())
+                                        newUri.append("?" + query.toUtf8());
+                                return handleMatrixUri(QUrl::fromEncoded(newUri));
+                        } else if (identifier.startsWith("!")) {
+                                QByteArray newUri = "matrix:roomid/" + QUrl::toPercentEncoding(
+                                                                         identifier.remove(0, 1));
+                                if (!eventId.isEmpty())
+                                        newUri.append(
+                                          "/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
+                                if (!query.isEmpty())
+                                        newUri.append("?" + query.toUtf8());
+                                return handleMatrixUri(QUrl::fromEncoded(newUri));
+                        }
+                }
+        }
+
+        // non-matrix URIs are not handled by us, return false
         if (uri_.scheme() != "matrix")
-                return;
+                return false;
 
         auto tempPath = uri_.path(QUrl::ComponentFormattingOption::FullyEncoded);
         if (tempPath.startsWith('/'))
@@ -1248,17 +1292,17 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
         auto segments = tempPath.splitRef('/');
 
         if (segments.size() != 2 && segments.size() != 4)
-                return;
+                return false;
 
         auto sigil1 = segments[0];
         auto mxid1  = mxidFromSegments(sigil1, segments[1]);
         if (mxid1.isEmpty())
-                return;
+                return false;
 
         QString mxid2;
         if (segments.size() == 4 && segments[2] == "e") {
                 if (segments[3].isEmpty())
-                        return;
+                        return false;
                 else
                         mxid2 = "$" + QUrl::fromPercentEncoding(segments[3].toUtf8());
         }
@@ -1283,12 +1327,13 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
                         if (t &&
                             cache::isRoomMember(mxid1.toStdString(), t->roomId().toStdString())) {
                                 t->openUserProfile(mxid1);
-                                return;
+                                return true;
                         }
                         emit view_manager_->openGlobalUserProfile(mxid1);
                 } else if (action == "chat") {
                         this->startChat(mxid1);
                 }
+                return true;
         } else if (sigil1 == "roomid") {
                 auto joined_rooms = cache::joinedRooms();
                 auto targetRoomId = mxid1.toStdString();
@@ -1298,13 +1343,15 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
                                 view_manager_->rooms()->setCurrentRoom(mxid1);
                                 if (!mxid2.isEmpty())
                                         view_manager_->showEvent(mxid1, mxid2);
-                                return;
+                                return true;
                         }
                 }
 
                 if (action == "join" || action.isEmpty()) {
                         joinRoomVia(targetRoomId, vias);
+                        return true;
                 }
+                return false;
         } else if (sigil1 == "r") {
                 auto joined_rooms    = cache::joinedRooms();
                 auto targetRoomAlias = mxid1.toStdString();
@@ -1318,21 +1365,25 @@ ChatPage::handleMatrixUri(const QByteArray &uri)
                                         if (!mxid2.isEmpty())
                                                 view_manager_->showEvent(
                                                   QString::fromStdString(roomid), mxid2);
-                                        return;
+                                        return true;
                                 }
                         }
                 }
 
                 if (action == "join" || action.isEmpty()) {
                         joinRoomVia(mxid1.toStdString(), vias);
+                        return true;
                 }
+                return false;
         }
+        return false;
 }
 
-void
+bool
 ChatPage::handleMatrixUri(const QUrl &uri)
 {
-        handleMatrixUri(uri.toString(QUrl::ComponentFormattingOption::FullyEncoded).toUtf8());
+        return handleMatrixUri(
+          uri.toString(QUrl::ComponentFormattingOption::FullyEncoded).toUtf8());
 }
 
 bool
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 9cbf2a03..66e4c6ab 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -78,8 +78,8 @@ public:
         QString currentRoom() const;
 
 public slots:
-        void handleMatrixUri(const QByteArray &uri);
-        void handleMatrixUri(const QUrl &uri);
+        bool handleMatrixUri(const QByteArray &uri);
+        bool handleMatrixUri(const QUrl &uri);
 
         void startChat(QString userid);
         void leaveRoom(const QString &room_id);
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index ece9db62..a6fbab78 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -630,6 +630,23 @@ InputBar::command(QString command, QString args)
                 notice(args, false);
         } else if (command == "rainbownotice") {
                 notice(args, true);
+        } else if (command == "goto") {
+                // Goto has three different modes:
+                // 1 - Going directly to a given event ID
+                if (args[0] == '$') {
+                        room->showEvent(args);
+                        return;
+                }
+                // 2 - Going directly to a given message index
+                if (args[0] >= '0' && args[0] <= '9') {
+                        room->showEvent(args);
+                        return;
+                }
+                // 3 - Matrix URI handler, as if you clicked the URI
+                if (ChatPage::instance()->handleMatrixUri(args)) {
+                        return;
+                }
+                nhlog::net()->error("Could not resolve goto: {}", args.toStdString());
         }
 }
 
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index e03c32a7..00f6d9df 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -1534,11 +1534,25 @@ void
 TimelineModel::showEvent(QString eventId)
 {
         using namespace std::chrono_literals;
-        if (idToIndex(eventId) != -1) {
+        // Direct to eventId
+        if (eventId[0] == '$') {
+                int idx = idToIndex(eventId);
+                if (idx == -1) {
+                        nhlog::ui()->warn("Scrolling to event id {}, failed - no known index",
+                                          eventId.toStdString());
+                        return;
+                }
                 eventIdToShow = eventId;
                 emit scrollTargetChanged();
                 showEventTimer.start(50ms);
+                return;
         }
+        // to message index
+        eventId       = indexToId(eventId.toInt());
+        eventIdToShow = eventId;
+        emit scrollTargetChanged();
+        showEventTimer.start(50ms);
+        return;
 }
 
 void
diff --git a/src/ui/NhekoGlobalObject.cpp b/src/ui/NhekoGlobalObject.cpp
index 9e0d706b..355f187b 100644
--- a/src/ui/NhekoGlobalObject.cpp
+++ b/src/ui/NhekoGlobalObject.cpp
@@ -57,48 +57,8 @@ void
 Nheko::openLink(QString link) const
 {
         QUrl url(link);
-        if (url.scheme() == "https" && url.host() == "matrix.to") {
-                // handle matrix.to links internally
-                QString p = url.fragment(QUrl::FullyEncoded);
-                if (p.startsWith("/"))
-                        p.remove(0, 1);
-
-                auto temp = p.split("?");
-                QString query;
-                if (temp.size() >= 2)
-                        query = QUrl::fromPercentEncoding(temp.takeAt(1).toUtf8());
-
-                temp            = temp.first().split("/");
-                auto identifier = QUrl::fromPercentEncoding(temp.takeFirst().toUtf8());
-                QString eventId = QUrl::fromPercentEncoding(temp.join('/').toUtf8());
-                if (!identifier.isEmpty()) {
-                        if (identifier.startsWith("@")) {
-                                QByteArray uri =
-                                  "matrix:u/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
-                                if (!query.isEmpty())
-                                        uri.append("?" + query.toUtf8());
-                                ChatPage::instance()->handleMatrixUri(QUrl::fromEncoded(uri));
-                        } else if (identifier.startsWith("#")) {
-                                QByteArray uri =
-                                  "matrix:r/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
-                                if (!eventId.isEmpty())
-                                        uri.append("/e/" +
-                                                   QUrl::toPercentEncoding(eventId.remove(0, 1)));
-                                if (!query.isEmpty())
-                                        uri.append("?" + query.toUtf8());
-                                ChatPage::instance()->handleMatrixUri(QUrl::fromEncoded(uri));
-                        } else if (identifier.startsWith("!")) {
-                                QByteArray uri = "matrix:roomid/" +
-                                                 QUrl::toPercentEncoding(identifier.remove(0, 1));
-                                if (!eventId.isEmpty())
-                                        uri.append("/e/" +
-                                                   QUrl::toPercentEncoding(eventId.remove(0, 1)));
-                                if (!query.isEmpty())
-                                        uri.append("?" + query.toUtf8());
-                                ChatPage::instance()->handleMatrixUri(QUrl::fromEncoded(uri));
-                        }
-                }
-        } else {
+        // Open externally if we couldn't handle it internally
+        if (!ChatPage::instance()->handleMatrixUri(url)) {
                 QDesktopServices::openUrl(url);
         }
 }