diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 80f162d6..d3cc7aee 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -543,8 +543,7 @@ Page { id: closeUnverifiedBubble Layout.rightMargin: Nheko.paddingMedium - Layout.topMargin: Nheko.paddingMedium - Layout.alignment: Qt.AlignRight | Qt.AlignCenter + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter hoverEnabled: true width: fontMetrics.font.pixelSize height: fontMetrics.font.pixelSize diff --git a/resources/qml/dialogs/InputDialog.qml b/resources/qml/dialogs/InputDialog.qml index 12211c60..b040068a 100644 --- a/resources/qml/dialogs/InputDialog.qml +++ b/resources/qml/dialogs/InputDialog.qml @@ -21,6 +21,11 @@ ApplicationWindow { width: 350 height: fontMetrics.lineSpacing * 7 + Shortcut { + sequence: StandardKey.Cancel + onActivated: dbb.rejected() + } + ColumnLayout { spacing: Nheko.paddingMedium anchors.margins: Nheko.paddingMedium @@ -36,11 +41,15 @@ ApplicationWindow { id: statusInput Layout.fillWidth: true + onAccepted: dbb.accepted() + focus: true } } footer: DialogButtonBox { + id: dbb + standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel onAccepted: { if (inputDialog.onAccepted) diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml index 86c176be..9ddf8ed0 100644 --- a/resources/qml/dialogs/InviteDialog.qml +++ b/resources/qml/dialogs/InviteDialog.qml @@ -99,38 +99,64 @@ ApplicationWindow { Layout.fillHeight: true model: invitees - delegate: RowLayout { - spacing: Nheko.paddingMedium + delegate: ItemDelegate { + id: del - Avatar { - width: Nheko.avatarSize - height: Nheko.avatarSize - userid: model.mxid - url: model.avatarUrl.replace("mxc://", "image://MxcImage/") - displayName: model.displayName - onClicked: TimelineManager.openGlobalUserProfile(model.mxid) + hoverEnabled: true + width: ListView.view.width + height: layout.implicitHeight + Nheko.paddingSmall * 2 + onClicked: TimelineManager.openGlobalUserProfile(model.mxid) + background: Rectangle { + color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color } - ColumnLayout { - spacing: Nheko.paddingSmall + RowLayout { + id: layout - Label { - text: model.displayName - color: TimelineManager.userColor(model ? model.mxid : "", Nheko.colors.window) - font.pointSize: fontMetrics.font.pointSize + spacing: Nheko.paddingMedium + anchors.centerIn: parent + width: del.width - Nheko.paddingSmall * 2 + + Avatar { + width: Nheko.avatarSize + height: Nheko.avatarSize + userid: model.mxid + url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + displayName: model.displayName + enabled: false } - Label { - text: model.mxid - color: Nheko.colors.buttonText - font.pointSize: fontMetrics.font.pointSize * 0.9 + ColumnLayout { + spacing: Nheko.paddingSmall + + Label { + text: model.displayName + color: TimelineManager.userColor(model ? model.mxid : "", del.background.color) + font.pointSize: fontMetrics.font.pointSize + } + + Label { + text: model.mxid + color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText + font.pointSize: fontMetrics.font.pointSize * 0.9 + } + } Item { - Layout.fillHeight: true Layout.fillWidth: true } + ImageButton { + image: ":/icons/icons/ui/dismiss.svg" + onClicked: invitees.removeUser(model.mxid) + } + + } + + CursorShape { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor } } diff --git a/resources/qml/dialogs/ReadReceipts.qml b/resources/qml/dialogs/ReadReceipts.qml index 1bfdae84..52e4512b 100644 --- a/resources/qml/dialogs/ReadReceipts.qml +++ b/resources/qml/dialogs/ReadReceipts.qml @@ -54,23 +54,29 @@ ApplicationWindow { id: readReceiptsList clip: true - spacing: Nheko.paddingMedium boundsBehavior: Flickable.StopAtBounds model: readReceipts delegate: ItemDelegate { + id: del + onClicked: room.openUserProfile(model.mxid) padding: Nheko.paddingMedium - width: receiptLayout.implicitWidth - height: receiptLayout.implicitHeight + width: ListView.view.width + height: receiptLayout.implicitHeight + Nheko.paddingSmall * 2 hoverEnabled: true ToolTip.visible: hovered ToolTip.text: model.mxid + background: Rectangle { + color: del.hovered ? Nheko.colors.dark : readReceiptsRoot.color + } RowLayout { id: receiptLayout spacing: Nheko.paddingMedium + anchors.fill: parent + anchors.margins: Nheko.paddingSmall Avatar { width: Nheko.avatarSize @@ -96,11 +102,10 @@ ApplicationWindow { font.pointSize: fontMetrics.font.pointSize * 0.9 } - Item { - Layout.fillHeight: true - Layout.fillWidth: true - } + } + Item { + Layout.fillWidth: true } } @@ -110,10 +115,6 @@ ApplicationWindow { cursorShape: Qt.PointingHandCursor } - background: Rectangle { - color: readReceiptsRoot.color - } - } } diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml index 6c8d1383..37ab6a80 100644 --- a/resources/qml/dialogs/RoomMembers.qml +++ b/resources/qml/dialogs/RoomMembers.qml @@ -75,7 +75,6 @@ ApplicationWindow { id: memberList clip: true - spacing: Nheko.paddingMedium boundsBehavior: Flickable.StopAtBounds model: members @@ -85,67 +84,86 @@ ApplicationWindow { enabled: !Settings.mobileMode } - delegate: RowLayout { + delegate: ItemDelegate { id: del + onClicked: Rooms.currentRoom.openUserProfile(model.mxid) + padding: Nheko.paddingMedium width: ListView.view.width - spacing: Nheko.paddingMedium - - Avatar { - id: avatar - - width: Nheko.avatarSize - height: Nheko.avatarSize - userid: model.mxid - url: model.avatarUrl.replace("mxc://", "image://MxcImage/") - displayName: model.displayName - onClicked: Rooms.currentRoom.openUserProfile(model.mxid) + height: memberLayout.implicitHeight + Nheko.paddingSmall * 2 + hoverEnabled: true + background: Rectangle { + color: del.hovered ? Nheko.colors.dark : roomMembersRoot.color } - ColumnLayout { - spacing: Nheko.paddingSmall + RowLayout { + id: memberLayout - ElidedLabel { - fullText: model.displayName - color: TimelineManager.userColor(model ? model.mxid : "", Nheko.colors.window) - font.pixelSize: fontMetrics.font.pixelSize - elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width + spacing: Nheko.paddingMedium + anchors.centerIn: parent + width: parent.width - Nheko.paddingSmall * 2 + + Avatar { + id: avatar + + width: Nheko.avatarSize + height: Nheko.avatarSize + userid: model.mxid + url: model.avatarUrl.replace("mxc://", "image://MxcImage/") + displayName: model.displayName + enabled: false } - ElidedLabel { - fullText: model.mxid - color: Nheko.colors.buttonText - font.pixelSize: Math.ceil(fontMetrics.font.pixelSize * 0.9) - elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width + ColumnLayout { + spacing: Nheko.paddingSmall + + ElidedLabel { + fullText: model.displayName + color: TimelineManager.userColor(model ? model.mxid : "", del.background.color) + font.pixelSize: fontMetrics.font.pixelSize + elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width + } + + ElidedLabel { + fullText: model.mxid + color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText + font.pixelSize: Math.ceil(fontMetrics.font.pixelSize * 0.9) + elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width + } + } Item { - Layout.fillHeight: true Layout.fillWidth: true } + EncryptionIndicator { + id: encryptInd + + Layout.alignment: Qt.AlignRight + visible: room.isEncrypted + encrypted: room.isEncrypted + trust: encrypted ? model.trustlevel : Crypto.Unverified + ToolTip.text: { + if (!encrypted) + return qsTr("This room is not encrypted!"); + + switch (trust) { + case Crypto.Verified: + return qsTr("This user is verified."); + case Crypto.TOFU: + return qsTr("This user isn't verified, but is still using the same master key from the first time you met."); + default: + return qsTr("This user has unverified devices!"); + } + } + } + } - EncryptionIndicator { - id: encryptInd - - Layout.alignment: Qt.AlignRight - visible: room.isEncrypted - encrypted: room.isEncrypted - trust: encrypted ? model.trustlevel : Crypto.Unverified - ToolTip.text: { - if (!encrypted) - return qsTr("This room is not encrypted!"); - - switch (trust) { - case Crypto.Verified: - return qsTr("This user is verified."); - case Crypto.TOFU: - return qsTr("This user isn't verified, but is still using the same master key from the first time you met."); - default: - return qsTr("This user has unverified devices!"); - } - } + CursorShape { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor } } diff --git a/src/InviteesModel.cpp b/src/InviteesModel.cpp index e045581a..ad99c847 100644 --- a/src/InviteesModel.cpp +++ b/src/InviteesModel.cpp @@ -16,6 +16,10 @@ InviteesModel::InviteesModel(QObject *parent) void InviteesModel::addUser(QString mxid) { + for (const auto &invitee : invitees_) + if (invitee->mxid_ == mxid) + return; + beginInsertRows(QModelIndex(), invitees_.count(), invitees_.count()); auto invitee = new Invitee{mxid, this}; @@ -30,6 +34,20 @@ InviteesModel::addUser(QString mxid) emit countChanged(); } +void +InviteesModel::removeUser(QString mxid) +{ + for (int i = 0; i < invitees_.length(); ++i) { + if (invitees_[i]->mxid_ == mxid) { + beginRemoveRows(QModelIndex(), i, i); + invitees_.removeAt(i); + endRemoveRows(); + emit countChanged(); + break; + } + } +} + QHash InviteesModel::roleNames() const { diff --git a/src/InviteesModel.h b/src/InviteesModel.h index fd64116b..65fb78d6 100644 --- a/src/InviteesModel.h +++ b/src/InviteesModel.h @@ -43,6 +43,7 @@ public: InviteesModel(QObject *parent = nullptr); Q_INVOKABLE void addUser(QString mxid); + Q_INVOKABLE void removeUser(QString mxid); QHash roleNames() const override; int rowCount(const QModelIndex & = QModelIndex()) const override diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 84aa2c90..c5fe6b4b 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -116,9 +116,10 @@ TimelineViewManager::updateColorPalette() QColor TimelineViewManager::userColor(QString id, QColor background) { - if (!userColors.contains(id)) - userColors.insert(id, QColor(utils::generateContrastingHexColor(id, background))); - return userColors.value(id); + QPair idx{id, background.rgba64()}; + if (!userColors.contains(idx)) + userColors.insert(idx, QColor(utils::generateContrastingHexColor(id, background))); + return userColors.value(idx); } QString diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 6696b1c4..3e3952a8 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -147,7 +147,7 @@ private: CallManager *callManager_ = nullptr; VerificationManager *verificationManager_ = nullptr; - QHash userColors; + QHash, QColor> userColors; }; Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationAccept) Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationCancel)