diff --git a/imports/NeoChat/Page/AccountsPage.qml b/imports/NeoChat/Page/AccountsPage.qml index 6ee23a770..97fe51b53 100644 --- a/imports/NeoChat/Page/AccountsPage.qml +++ b/imports/NeoChat/Page/AccountsPage.qml @@ -7,10 +7,12 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 as Controls import QtQuick.Layouts 1.14 +import Qt.labs.platform 1.1 -import org.kde.kirigami 2.12 as Kirigami +import org.kde.kirigami 2.13 as Kirigami import org.kde.neochat 1.0 +import NeoChat.Dialog 1.0 Kirigami.ScrollablePage { title: i18n("Accounts") @@ -29,7 +31,7 @@ Kirigami.ScrollablePage { text: model.user.displayName subtitle: model.user.id - icon: model.connection.user.avatarMediaId ? "image://mxc/" + model.connection.user.avatarMediaId : "im-user" + icon: model.user.avatarMediaId ? ("image://mxc/" + model.user.avatarMediaId) : "im-user" onClicked: { Controller.activeConnection = model.connection @@ -80,6 +82,14 @@ Kirigami.ScrollablePage { onTriggered: pageStack.layers.push("qrc:/imports/NeoChat/Page/WelcomePage.qml") } + Component { + id: openFileDialog + + OpenFileDialog { + folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation) + } + } + Kirigami.OverlaySheet { id: userEditSheet @@ -91,6 +101,32 @@ Kirigami.ScrollablePage { Kirigami.FormLayout { anchors.top: passwordsMessage.bottom + RowLayout { + Kirigami.Avatar { + id: avatar + source: userEditSheet.connection.localUser.avatarMediaId ? ("image://mxc/" + userEditSheet.connection.localUser.avatarMediaId) : "" + + MouseArea { + anchors.fill: parent + onClicked: { + const fileDialog = openFileDialog.createObject(Controls.ApplicationWindow.Overlay) + + fileDialog.chosen.connect(function(receivedSource) { + if (!receivedSource) return + parent.source = receivedSource + }) + fileDialog.open() + } + } + } + Controls.Button { + visible: avatar.source.length !== 0 + icon.name: "edit-clear" + + onClicked: avatar.source = "" + } + Kirigami.FormData.label: i18n("Avatar:") + } Controls.TextField { id: name text: userEditSheet.connection.localUser.displayName @@ -113,23 +149,37 @@ Kirigami.ScrollablePage { echoMode: TextInput.Password } - Controls.Button { - text: i18n("Save") - onClicked: { - if(userEditSheet.connection.localUser.displayName !== name.text) - userEditSheet.connection.localUser.rename(name.text) - if(currentPassword.text !== "" && newPassword.text !== "" && confirmPassword.text !== "") { - if(newPassword.text === confirmPassword.text) { - Controller.changePassword(userEditSheet.connection, currentPassword.text, newPassword.text) - } else { - showPassiveNotification(i18n("Passwords do not match")) - return + RowLayout { + Controls.Button { + text: i18n("Save") + onClicked: { + if(!Controller.setAvatar(userEditSheet.connection, avatar.source)) + showPassiveNotification("The Avatar could not be set") + if(userEditSheet.connection.localUser.displayName !== name.text) + userEditSheet.connection.localUser.rename(name.text) + if(currentPassword.text !== "" && newPassword.text !== "" && confirmPassword.text !== "") { + if(newPassword.text === confirmPassword.text) { + Controller.changePassword(userEditSheet.connection, currentPassword.text, newPassword.text) + } else { + showPassiveNotification(i18n("Passwords do not match")) + return + } } + userEditSheet.close() + currentPassword.text = "" + newPassword.text = "" + confirmPassword.text = "" + } + } + Controls.Button { + text: i18n("Cancel") + onClicked: { + userEditSheet.close() + avatar.source = userEditSheet.connection.localUser.avatarMediaId ? ("image://mxc/" + userEditSheet.connection.localUser.avatarMediaId) : "" + currentPassword.text = "" + newPassword.text = "" + confirmPassword.text = "" } - userEditSheet.close() - currentPassword.text = "" - newPassword.text = "" - confirmPassword.text = "" } } } diff --git a/src/controller.cpp b/src/controller.cpp index d1f5c7f9a..63df1b056 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -441,6 +441,22 @@ void Controller::changePassword(Connection *connection, const QString ¤tPa }); } +bool Controller::setAvatar(Connection *connection, const QUrl &avatarSource) +{ + User *localUser = connection->user(); + QString decoded = avatarSource.path(); + if (decoded.isEmpty()) { + connection->callApi(localUser->id(), ""); + return true; + } + if (QImageReader(decoded).read().isNull()) { + return false; + } + else { + return localUser->setAvatar(decoded); + } +} + NeochatChangePasswordJob::NeochatChangePasswordJob(const QString &newPassword, bool logoutDevices, const Omittable &auth) : BaseJob(HttpVerb::Post, QStringLiteral("ChangePasswordJob"), QStringLiteral("/_matrix/client/r0") % "/account/password") { diff --git a/src/controller.h b/src/controller.h index 471b42723..5880b741d 100644 --- a/src/controller.h +++ b/src/controller.h @@ -50,6 +50,8 @@ public: Q_INVOKABLE void changePassword(Quotient::Connection *connection, const QString ¤tPassword, const QString &newPassword); + Q_INVOKABLE bool setAvatar(Quotient::Connection *connection, const QUrl &avatarSource); + [[nodiscard]] int accountCount() const; [[nodiscard]] static bool quitOnLastWindowClosed();