Merge pull request #431 from Jedi18/avatar_username_feature

Username editing (room specific and global)
This commit is contained in:
DeepBlueV7.X 2021-02-01 19:14:57 +01:00 committed by GitHub
commit 2b7bd09ad3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 124 additions and 8 deletions

View File

@ -17,6 +17,7 @@ ApplicationWindow {
minimumHeight: 420 minimumHeight: 420
palette: colors palette: colors
color: colors.window color: colors.window
title: profile.isGlobalUserProfile ? "Global User Profile" : "Room User Profile"
Shortcut { Shortcut {
sequence: StandardKey.Cancel sequence: StandardKey.Cancel
@ -40,13 +41,42 @@ ApplicationWindow {
onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id) onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id)
} }
Label { TextInput {
id: displayUsername
property bool isUsernameEditingAllowed
readOnly: !isUsernameEditingAllowed
text: profile.displayName text: profile.displayName
fontSizeMode: Text.HorizontalFit
font.pixelSize: 20 font.pixelSize: 20
color: TimelineManager.userColor(profile.userid, colors.window) color: TimelineManager.userColor(profile.userid, colors.window)
font.bold: true font.bold: true
Layout.alignment: Qt.AlignHCenter 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 { MatrixText {

View File

@ -111,7 +111,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
connect(sidebarActions_, &SideBarActions::joinRoom, this, &ChatPage::joinRoom); connect(sidebarActions_, &SideBarActions::joinRoom, this, &ChatPage::joinRoom);
connect(sidebarActions_, &SideBarActions::createRoom, this, &ChatPage::createRoom); 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(); user_mentions_popup_ = new popups::UserMentions();
room_list_ = new RoomList(userSettings, sideBar_); room_list_ = new RoomList(userSettings, sideBar_);
connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom); connect(room_list_, &RoomList::joinRoom, this, &ChatPage::joinRoom);

View File

@ -125,6 +125,10 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
ChatPage::instance()->setStatus(text); 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 #if 0 // disable presence menu until issues in synapse are resolved
auto setAutoPresence = menu->addAction(tr("Set presence automatically")); auto setAutoPresence = menu->addAction(tr("Set presence automatically"));
connect(setAutoPresence, &QAction::triggered, this, []() { connect(setAutoPresence, &QAction::triggered, this, []() {

View File

@ -51,6 +51,9 @@ protected:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void contextMenuEvent(QContextMenuEvent *) override; void contextMenuEvent(QContextMenuEvent *) override;
signals:
void openGlobalUserProfile();
private: private:
Avatar *userAvatar_; Avatar *userAvatar_;

View File

@ -799,9 +799,9 @@ TimelineModel::viewDecryptedRawMessage(QString id) const
} }
void 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 void

View File

@ -212,7 +212,7 @@ public:
Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void viewRawMessage(QString id) const;
Q_INVOKABLE void viewDecryptedRawMessage(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 replyAction(QString id);
Q_INVOKABLE void readReceiptsAction(QString id) const; Q_INVOKABLE void readReceiptsAction(QString id) const;
Q_INVOKABLE void redactEvent(QString id); Q_INVOKABLE void redactEvent(QString id);

View File

@ -7,6 +7,8 @@
#include "mtx/responses/crypto.hpp" #include "mtx/responses/crypto.hpp"
#include "timeline/TimelineModel.h" #include "timeline/TimelineModel.h"
#include "timeline/TimelineViewManager.h" #include "timeline/TimelineViewManager.h"
#include <mtx/responses.hpp>
#include <mtx/responses/common.hpp>
UserProfile::UserProfile(QString roomid, UserProfile::UserProfile(QString roomid,
QString userid, QString userid,
@ -44,6 +46,23 @@ UserProfile::UserProfile(QString roomid,
} }
deviceList_.reset(deviceList_.deviceList_); 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> QHash<int, QByteArray>
@ -97,7 +116,7 @@ UserProfile::userid()
QString QString
UserProfile::displayName() UserProfile::displayName()
{ {
return cache::displayName(roomid_, userid_); return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
} }
QString QString
@ -106,6 +125,12 @@ UserProfile::avatarUrl()
return cache::avatarUrl(roomid_, userid_); return cache::avatarUrl(roomid_, userid_);
} }
bool
UserProfile::isGlobalUserProfile() const
{
return roomid_ == "";
}
bool bool
UserProfile::getUserStatus() UserProfile::getUserStatus()
{ {
@ -213,6 +238,40 @@ UserProfile::startChat()
ChatPage::instance()->startChat(this->userid_); ChatPage::instance()->startChat(this->userid_);
} }
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 void
UserProfile::verify(QString device) UserProfile::verify(QString device)
{ {
@ -228,3 +287,10 @@ UserProfile::unverify(QString device)
{ {
cache::markDeviceUnverified(userid_.toStdString(), device.toStdString()); cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
} }
void
UserProfile::setGlobalUsername(const QString &globalUser)
{
globalUsername = globalUser;
emit displayNameChanged();
}

View File

@ -79,10 +79,11 @@ private:
class UserProfile : public QObject class UserProfile : public QObject
{ {
Q_OBJECT 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 userid READ userid CONSTANT)
Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT) Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT)
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList 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 isUserVerified READ getUserStatus NOTIFY userStatusChanged)
Q_PROPERTY( Q_PROPERTY(
bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged) bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
@ -98,6 +99,7 @@ public:
QString userid(); QString userid();
QString displayName(); QString displayName();
QString avatarUrl(); QString avatarUrl();
bool isGlobalUserProfile() const;
bool getUserStatus(); bool getUserStatus();
bool userVerificationEnabled() const; bool userVerificationEnabled() const;
bool isSelf() const; bool isSelf() const;
@ -109,12 +111,19 @@ public:
// Q_INVOKABLE void ignoreUser(); // Q_INVOKABLE void ignoreUser();
Q_INVOKABLE void kickUser(); Q_INVOKABLE void kickUser();
Q_INVOKABLE void startChat(); Q_INVOKABLE void startChat();
Q_INVOKABLE void changeUsername(QString username);
signals: signals:
void userStatusChanged(); void userStatusChanged();
void displayNameChanged();
void globalUsernameRetrieved(const QString &globalUser);
protected slots:
void setGlobalUsername(const QString &globalUser);
private: private:
QString roomid_, userid_; QString roomid_, userid_;
QString globalUsername;
DeviceInfoModel deviceList_; DeviceInfoModel deviceList_;
bool isUserVerified = false; bool isUserVerified = false;
bool hasMasterKey = false; bool hasMasterKey = false;