diff --git a/resources/qml/dialogs/UserProfile.qml b/resources/qml/dialogs/UserProfile.qml
index 30052168..4c7095b2 100644
--- a/resources/qml/dialogs/UserProfile.qml
+++ b/resources/qml/dialogs/UserProfile.qml
@@ -281,6 +281,8 @@ ApplicationWindow {
required property int verificationStatus
required property string deviceId
required property string deviceName
+ required property string lastIp
+ required property var lastTs
width: devicelist.width
spacing: 4
@@ -288,21 +290,90 @@ ApplicationWindow {
ColumnLayout {
spacing: 0
- Text {
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignLeft
- elide: Text.ElideRight
- font.bold: true
- color: Nheko.colors.text
- text: deviceId
+ RowLayout {
+ Text {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignLeft
+ elide: Text.ElideRight
+ font.bold: true
+ color: Nheko.colors.text
+ text: deviceId
+ }
+
+ Image {
+ Layout.preferredHeight: 16
+ Layout.preferredWidth: 16
+ visible: profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
+ source: {
+ switch (verificationStatus) {
+ case VerificationStatus.VERIFIED:
+ return "image://colorimage/:/icons/icons/ui/lock.png?green";
+ case VerificationStatus.UNVERIFIED:
+ return "image://colorimage/:/icons/icons/ui/unlock.png?yellow";
+ case VerificationStatus.SELF:
+ return "image://colorimage/:/icons/icons/ui/checkmark.png?green";
+ default:
+ return "image://colorimage/:/icons/icons/ui/unlock.png?red";
+ }
+ }
+ }
+
+ ImageButton {
+ Layout.alignment: Qt.AlignTop
+ 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
+ }
+ }
+
+ RowLayout {
+ id: deviceNameRow
+ property bool isEditingAllowed
+
+ TextInput {
+ id: deviceNameField
+ readOnly: !deviceNameRow.isEditingAllowed
+ text: deviceName
+ color: Nheko.colors.text
+ Layout.alignment: Qt.AlignLeft
+ Layout.fillWidth: true
+ selectByMouse: true
+ onAccepted: {
+ profile.changeDeviceName(deviceId, deviceNameField.text);
+ deviceNameRow.isEditingAllowed = false;
+ }
+ }
+
+ ImageButton {
+ visible: profile.isSelf
+ hoverEnabled: true
+ ToolTip.visible: hovered
+ ToolTip.text: qsTr("Change device name.")
+ image: deviceNameRow.isEditingAllowed ? ":/icons/icons/ui/checkmark.png" : ":/icons/icons/ui/edit.png"
+ onClicked: {
+ if (deviceNameRow.isEditingAllowed) {
+ profile.changeDeviceName(deviceId, deviceNameField.text);
+ deviceNameRow.isEditingAllowed = false;
+ } else {
+ deviceNameRow.isEditingAllowed = true;
+ deviceNameField.focus = true;
+ deviceNameField.selectAll();
+ }
+ }
+ }
+
}
Text {
+ visible: profile.isSelf
Layout.fillWidth: true
- Layout.alignment: Qt.AlignRight
+ Layout.alignment: Qt.AlignLeft
elide: Text.ElideRight
color: Nheko.colors.text
- text: deviceName
+ text: qsTr("Last seen %1 from %2").arg(new Date(lastTs).toLocaleString(Locale.ShortFormat)).arg(lastIp?lastIp:"???")
}
}
@@ -310,7 +381,7 @@ ApplicationWindow {
Image {
Layout.preferredHeight: 16
Layout.preferredWidth: 16
- visible: verificationStatus != VerificationStatus.NOT_APPLICABLE
+ visible: !profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
source: {
switch (verificationStatus) {
case VerificationStatus.VERIFIED:
@@ -338,14 +409,7 @@ 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
- }
+
}
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 0e3fd39f..b5a16f43 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -62,6 +62,8 @@ DeviceInfoModel::roleNames() const
{DeviceId, "deviceId"},
{DeviceName, "deviceName"},
{VerificationStatus, "verificationStatus"},
+ {LastIp, "lastIp"},
+ {LastTs, "lastTs"},
};
}
@@ -78,6 +80,10 @@ DeviceInfoModel::data(const QModelIndex &index, int role) const
return deviceList_[index.row()].display_name;
case VerificationStatus:
return QVariant::fromValue(deviceList_[index.row()].verification_status);
+ case LastIp:
+ return deviceList_[index.row()].lastIp;
+ case LastTs:
+ return deviceList_[index.row()].lastTs;
default:
return {};
}
@@ -335,6 +341,19 @@ UserProfile::changeUsername(QString username)
}
void
+UserProfile::changeDeviceName(QString deviceID, QString deviceName)
+{
+ http::client()->set_device_name(
+ deviceID.toStdString(), deviceName.toStdString(), [this](mtx::http::RequestErr err) {
+ if (err) {
+ nhlog::net()->warn("could not change device name");
+ return;
+ }
+ refreshDevices();
+ });
+}
+
+void
UserProfile::verify(QString device)
{
if (!device.isEmpty())
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index e8bff6ba..cd2f4740 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -62,7 +62,7 @@ public:
verification::Status verification_status;
QString lastIp;
- size_t lastTs;
+ qlonglong lastTs;
};
class DeviceInfoModel : public QAbstractListModel
@@ -74,6 +74,8 @@ public:
DeviceId,
DeviceName,
VerificationStatus,
+ LastIp,
+ LastTs,
};
explicit DeviceInfoModel(QObject *parent = nullptr)
@@ -141,6 +143,7 @@ public:
Q_INVOKABLE void kickUser();
Q_INVOKABLE void startChat();
Q_INVOKABLE void changeUsername(QString username);
+ Q_INVOKABLE void changeDeviceName(QString deviceID, QString deviceName);
Q_INVOKABLE void changeAvatar();
Q_INVOKABLE void openGlobalProfile();
|