summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--io.github.NhekoReborn.Nheko.yaml2
-rw-r--r--resources/qml/dialogs/UserProfile.qml10
-rw-r--r--src/ui/UserProfile.cpp63
-rw-r--r--src/ui/UserProfile.h18
5 files changed, 92 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ff3ca26..439a4971 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -385,7 +385,7 @@ if(USE_BUNDLED_MTXCLIENT)
 	FetchContent_Declare(
 		MatrixClient
 		GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
-		GIT_TAG        8b56b466dbacde501ed9087d53bb4f51b297eca8
+		GIT_TAG        e5284ccc9d902117bbe782b0be76fa272b7f0a90
 		)
 	set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
 	set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml
index ce272ea7..1ad5a0db 100644
--- a/io.github.NhekoReborn.Nheko.yaml
+++ b/io.github.NhekoReborn.Nheko.yaml
@@ -163,7 +163,7 @@ modules:
     buildsystem: cmake-ninja
     name: mtxclient
     sources:
-      - commit: 8b56b466dbacde501ed9087d53bb4f51b297eca8
+      - commit: e5284ccc9d902117bbe782b0be76fa272b7f0a90
         type: git
         url: https://github.com/Nheko-Reborn/mtxclient.git
   - config-opts:
diff --git a/resources/qml/dialogs/UserProfile.qml b/resources/qml/dialogs/UserProfile.qml
index c921278e..30052168 100644
--- a/resources/qml/dialogs/UserProfile.qml
+++ b/resources/qml/dialogs/UserProfile.qml
@@ -310,6 +310,7 @@ ApplicationWindow {
             Image {
                 Layout.preferredHeight: 16
                 Layout.preferredWidth: 16
+                visible: verificationStatus != VerificationStatus.NOT_APPLICABLE
                 source: {
                     switch (verificationStatus) {
                     case VerificationStatus.VERIFIED:
@@ -337,6 +338,15 @@ ApplicationWindow {
                 }
             }
 
+            ImageButton {
+              image: ":/icons/icons/ui/power-button-off.png"
+              hoverEnabled: true
+              ToolTip.visible: hovered
+              ToolTip.text: qsTr("Sign out this device.")
+              onClicked: profile.signOutDevice(deviceId)
+              visible: profile.isSelf
+            }
+
         }
 
         footer: DialogButtonBox {
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 31ae9f8b..591110af 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -16,6 +16,7 @@
 #include "mtx/responses/crypto.hpp"
 #include "timeline/TimelineModel.h"
 #include "timeline/TimelineViewManager.h"
+#include "ui/UIA.h"
 
 UserProfile::UserProfile(QString roomid,
                          QString userid,
@@ -138,6 +139,27 @@ UserProfile::isSelf() const
 }
 
 void
+UserProfile::signOutDevice(const QString &deviceID)
+{
+    http::client()->delete_device(
+      deviceID.toStdString(),
+      UIA::instance()->genericHandler(tr("Sign out device %1").arg(deviceID)),
+      [this, deviceID](mtx::http::RequestErr e) {
+          if (e) {
+              nhlog::ui()->critical("Failure when attempting to sign out device {}",
+                                    deviceID.toStdString());
+              return;
+          }
+          nhlog::ui()->info("Device {} successfully signed out!", deviceID.toStdString());
+          // This is us. Let's update the interface accordingly
+          if (isSelf() && deviceID.toStdString() == ::http::client()->device_id()) {
+              ChatPage::instance()->dropToLoginPageCb(tr("You signed out this device."));
+          }
+          refreshDevices();
+      });
+}
+
+void
 UserProfile::refreshDevices()
 {
     cache::client()->markUserKeysOutOfDate({this->userid_.toStdString()});
@@ -221,6 +243,47 @@ UserProfile::updateVerificationStatus()
                               verified});
     }
 
+    // For self, also query devices without keys
+    if (isSelf()) {
+        http::client()->query_devices(
+          [this, deviceInfo](const mtx::responses::QueryDevices &allDevs,
+                             mtx::http::RequestErr err) mutable {
+              if (err) {
+                  nhlog::net()->warn("failed to query devices: {} {}",
+                                     err->matrix_error.error,
+                                     static_cast<int>(err->status_code));
+                  this->deviceList_.queueReset(std::move(deviceInfo));
+                  emit devicesChanged();
+                  return;
+              }
+              for (const auto &d : allDevs.devices) {
+                  // First, check if we already have an entry for this device
+                  bool found = false;
+                  for (auto &e : deviceInfo) {
+                      if (e.device_id.toStdString() == d.device_id) {
+                          found = true;
+                          // Gottem! Let's fill in the blanks
+                          e.lastIp = QString::fromStdString(d.last_seen_ip);
+                          e.lastTs = d.last_seen_ts;
+                          break;
+                      }
+                  }
+                  // No entry? Let's add one.
+                  if (!found) {
+                      deviceInfo.push_back({QString::fromStdString(d.device_id),
+                                            QString::fromStdString(d.display_name),
+                                            verification::NOT_APPLICABLE,
+                                            QString::fromStdString(d.last_seen_ip),
+                                            d.last_seen_ts});
+                  }
+              }
+
+              this->deviceList_.queueReset(std::move(deviceInfo));
+              emit devicesChanged();
+          });
+        return;
+    }
+
     this->deviceList_.queueReset(std::move(deviceInfo));
     emit devicesChanged();
 }
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index 68f9c21b..e8bff6ba 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -21,7 +21,8 @@ enum Status
     SELF,
     VERIFIED,
     UNVERIFIED,
-    BLOCKED
+    BLOCKED,
+    NOT_APPLICABLE
 };
 Q_ENUM_NS(Status)
 }
@@ -35,10 +36,22 @@ class DeviceInfo
 public:
     DeviceInfo(const QString deviceID,
                const QString displayName,
+               verification::Status verification_status_,
+               const QString lastIp_,
+               const size_t lastTs_)
+      : device_id(deviceID)
+      , display_name(displayName)
+      , verification_status(verification_status_)
+      , lastIp(lastIp_)
+      , lastTs(lastTs_)
+    {}
+    DeviceInfo(const QString deviceID,
+               const QString displayName,
                verification::Status verification_status_)
       : device_id(deviceID)
       , display_name(displayName)
       , verification_status(verification_status_)
+      , lastTs(0)
     {}
     DeviceInfo()
       : verification_status(verification::UNVERIFIED)
@@ -48,6 +61,8 @@ public:
     QString display_name;
 
     verification::Status verification_status;
+    QString lastIp;
+    size_t lastTs;
 };
 
 class DeviceInfoModel : public QAbstractListModel
@@ -121,6 +136,7 @@ public:
     Q_INVOKABLE void fetchDeviceList(const QString &userID);
     Q_INVOKABLE void refreshDevices();
     Q_INVOKABLE void banUser();
+    Q_INVOKABLE void signOutDevice(const QString &deviceID);
     // Q_INVOKABLE void ignoreUser();
     Q_INVOKABLE void kickUser();
     Q_INVOKABLE void startChat();