summary refs log tree commit diff
diff options
context:
space:
mode:
authorDeepBlueV7.X <nicolas.werner@hotmail.de>2021-02-01 19:14:57 +0100
committerGitHub <noreply@github.com>2021-02-01 19:14:57 +0100
commit2b7bd09ad330988301576161d629bca40117bb33 (patch)
treef9a5bf3f0a4f3ea2b4afd4f2491702735871a04b
parentTranslated using Weblate (Hungarian) (diff)
parentfocus and select text on clicking edit button (diff)
downloadnheko-2b7bd09ad330988301576161d629bca40117bb33.tar.xz
Merge pull request #431 from Jedi18/avatar_username_feature
Username editing (room specific and global)
-rw-r--r--resources/qml/UserProfile.qml34
-rw-r--r--src/ChatPage.cpp6
-rw-r--r--src/UserInfoWidget.cpp4
-rw-r--r--src/UserInfoWidget.h3
-rw-r--r--src/timeline/TimelineModel.cpp4
-rw-r--r--src/timeline/TimelineModel.h2
-rw-r--r--src/ui/UserProfile.cpp68
-rw-r--r--src/ui/UserProfile.h11
8 files changed, 124 insertions, 8 deletions
diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml
index a1fbfa41..4cb9eb10 100644
--- a/resources/qml/UserProfile.qml
+++ b/resources/qml/UserProfile.qml
@@ -17,6 +17,7 @@ ApplicationWindow {
     minimumHeight: 420
     palette: colors
     color: colors.window
+    title: profile.isGlobalUserProfile ? "Global User Profile" : "Room User Profile"
 
     Shortcut {
         sequence: StandardKey.Cancel
@@ -40,13 +41,42 @@ ApplicationWindow {
             onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id)
         }
 
-        Label {
+        TextInput {
+            id: displayUsername
+
+            property bool isUsernameEditingAllowed
+
+            readOnly: !isUsernameEditingAllowed
             text: profile.displayName
-            fontSizeMode: Text.HorizontalFit
             font.pixelSize: 20
             color: TimelineManager.userColor(profile.userid, colors.window)
             font.bold: true
             Layout.alignment: Qt.AlignHCenter
+            selectByMouse: true
+
+            onAccepted: {
+                profile.changeUsername(displayUsername.text)
+                displayUsername.isUsernameEditingAllowed = false
+            }
+
+            ImageButton {
+                visible: profile.isSelf
+                anchors.leftMargin: 5
+                anchors.left: displayUsername.right
+                anchors.verticalCenter: displayUsername.verticalCenter
+                image: displayUsername.isUsernameEditingAllowed ? ":/icons/icons/ui/checkmark.png" : ":/icons/icons/ui/edit.png"
+
+                onClicked: {
+                    if (displayUsername.isUsernameEditingAllowed) {
+                        profile.changeUsername(displayUsername.text)
+                        displayUsername.isUsernameEditingAllowed = false
+                    } else {
+                        displayUsername.isUsernameEditingAllowed = true
+                        displayUsername.focus = true
+                        displayUsername.selectAll()
+                    }
+                }
+            }
         }
 
         MatrixText {
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 4e472a3a..07ed3941 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -111,7 +111,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
         connect(sidebarActions_, &SideBarActions::joinRoom, this, &ChatPage::joinRoom);
         connect(sidebarActions_, &SideBarActions::createRoom, this, &ChatPage::createRoom);
 
-        user_info_widget_    = new UserInfoWidget(sideBar_);
+        user_info_widget_ = new UserInfoWidget(sideBar_);
+        connect(user_info_widget_, &UserInfoWidget::openGlobalUserProfile, this, [this]() {
+                view_manager_->activeTimeline()->openUserProfile(utils::localUser(), true);
+        });
+
         user_mentions_popup_ = new popups::UserMentions();
         room_list_           = new RoomList(userSettings, sideBar_);
         connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom);
diff --git a/src/UserInfoWidget.cpp b/src/UserInfoWidget.cpp
index f8e94431..5bcb44a9 100644
--- a/src/UserInfoWidget.cpp
+++ b/src/UserInfoWidget.cpp
@@ -125,6 +125,10 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
                         ChatPage::instance()->setStatus(text);
         });
 
+        auto userProfileAction = menu->addAction(tr("User Profile Settings"));
+        connect(
+          userProfileAction, &QAction::triggered, this, [this]() { emit openGlobalUserProfile(); });
+
 #if 0 // disable presence menu until issues in synapse are resolved
         auto setAutoPresence = menu->addAction(tr("Set presence automatically"));
         connect(setAutoPresence, &QAction::triggered, this, []() {
diff --git a/src/UserInfoWidget.h b/src/UserInfoWidget.h
index 03ab2cf0..bfcfbc0b 100644
--- a/src/UserInfoWidget.h
+++ b/src/UserInfoWidget.h
@@ -51,6 +51,9 @@ protected:
         void paintEvent(QPaintEvent *event) override;
         void contextMenuEvent(QContextMenuEvent *) override;
 
+signals:
+        void openGlobalUserProfile();
+
 private:
         Avatar *userAvatar_;
 
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 4346b0b2..79cf5184 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -799,9 +799,9 @@ TimelineModel::viewDecryptedRawMessage(QString id) const
 }
 
 void
-TimelineModel::openUserProfile(QString userid)
+TimelineModel::openUserProfile(QString userid, bool global)
 {
-        emit openProfile(new UserProfile(room_id_, userid, manager_, this));
+        emit openProfile(new UserProfile(global ? "" : room_id_, userid, manager_, this));
 }
 
 void
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 35e62eb4..51b8049e 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -212,7 +212,7 @@ public:
 
         Q_INVOKABLE void viewRawMessage(QString id) const;
         Q_INVOKABLE void viewDecryptedRawMessage(QString id) const;
-        Q_INVOKABLE void openUserProfile(QString userid);
+        Q_INVOKABLE void openUserProfile(QString userid, bool global = false);
         Q_INVOKABLE void replyAction(QString id);
         Q_INVOKABLE void readReceiptsAction(QString id) const;
         Q_INVOKABLE void redactEvent(QString id);
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 08219a38..3872294a 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -7,6 +7,8 @@
 #include "mtx/responses/crypto.hpp"
 #include "timeline/TimelineModel.h"
 #include "timeline/TimelineViewManager.h"
+#include <mtx/responses.hpp>
+#include <mtx/responses/common.hpp>
 
 UserProfile::UserProfile(QString roomid,
                          QString userid,
@@ -44,6 +46,23 @@ UserProfile::UserProfile(QString roomid,
                         }
                         deviceList_.reset(deviceList_.deviceList_);
                 });
+
+        connect(this,
+                &UserProfile::globalUsernameRetrieved,
+                this,
+                &UserProfile::setGlobalUsername,
+                Qt::QueuedConnection);
+
+        http::client()->get_profile(
+          userid_.toStdString(),
+          [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
+                  if (err) {
+                          nhlog::net()->warn("failed to retrieve own profile info");
+                          return;
+                  }
+
+                  emit globalUsernameRetrieved(QString::fromStdString(res.display_name));
+          });
 }
 
 QHash<int, QByteArray>
@@ -97,7 +116,7 @@ UserProfile::userid()
 QString
 UserProfile::displayName()
 {
-        return cache::displayName(roomid_, userid_);
+        return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
 }
 
 QString
@@ -107,6 +126,12 @@ UserProfile::avatarUrl()
 }
 
 bool
+UserProfile::isGlobalUserProfile() const
+{
+        return roomid_ == "";
+}
+
+bool
 UserProfile::getUserStatus()
 {
         return isUserVerified;
@@ -214,6 +239,40 @@ UserProfile::startChat()
 }
 
 void
+UserProfile::changeUsername(QString username)
+{
+        if (isGlobalUserProfile()) {
+                // change global
+                http::client()->set_displayname(
+                  username.toStdString(), [this](mtx::http::RequestErr err) {
+                          if (err) {
+                                  nhlog::net()->warn("could not change username");
+                                  return;
+                          }
+                  });
+        } else {
+                // change room username
+                mtx::events::state::Member member;
+                member.display_name = username.toStdString();
+                member.avatar_url =
+                  cache::avatarUrl(roomid_,
+                                   QString::fromStdString(http::client()->user_id().to_string()))
+                    .toStdString();
+                member.membership = mtx::events::state::Membership::Join;
+
+                http::client()->send_state_event(
+                  roomid_.toStdString(),
+                  http::client()->user_id().to_string(),
+                  member,
+                  [](mtx::responses::EventId, mtx::http::RequestErr err) {
+                          if (err)
+                                  nhlog::net()->error("Failed to set room displayname: {}",
+                                                      err->matrix_error.error);
+                  });
+        }
+}
+
+void
 UserProfile::verify(QString device)
 {
         if (!device.isEmpty())
@@ -228,3 +287,10 @@ UserProfile::unverify(QString device)
 {
         cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
 }
+
+void
+UserProfile::setGlobalUsername(const QString &globalUser)
+{
+        globalUsername = globalUser;
+        emit displayNameChanged();
+}
\ No newline at end of file
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index 19527310..11f588b6 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -79,10 +79,11 @@ private:
 class UserProfile : public QObject
 {
         Q_OBJECT
-        Q_PROPERTY(QString displayName READ displayName CONSTANT)
+        Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
         Q_PROPERTY(QString userid READ userid CONSTANT)
         Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT)
         Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList CONSTANT)
+        Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
         Q_PROPERTY(bool isUserVerified READ getUserStatus NOTIFY userStatusChanged)
         Q_PROPERTY(
           bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
@@ -98,6 +99,7 @@ public:
         QString userid();
         QString displayName();
         QString avatarUrl();
+        bool isGlobalUserProfile() const;
         bool getUserStatus();
         bool userVerificationEnabled() const;
         bool isSelf() const;
@@ -109,12 +111,19 @@ public:
         // Q_INVOKABLE void ignoreUser();
         Q_INVOKABLE void kickUser();
         Q_INVOKABLE void startChat();
+        Q_INVOKABLE void changeUsername(QString username);
 
 signals:
         void userStatusChanged();
+        void displayNameChanged();
+        void globalUsernameRetrieved(const QString &globalUser);
+
+protected slots:
+        void setGlobalUsername(const QString &globalUser);
 
 private:
         QString roomid_, userid_;
+        QString globalUsername;
         DeviceInfoModel deviceList_;
         bool isUserVerified = false;
         bool hasMasterKey   = false;