diff --git a/resources/qml/EncryptionIndicator.qml b/resources/qml/EncryptionIndicator.qml index 9fe40dea..5338b6be 100644 --- a/resources/qml/EncryptionIndicator.qml +++ b/resources/qml/EncryptionIndicator.qml @@ -14,10 +14,12 @@ Image { property int trust: Crypto.Unverified property string unencryptedIcon: ":/icons/icons/ui/shield-filled-cross.svg" property color unencryptedColor: Nheko.theme.error + property color unencryptedHoverColor: unencryptedColor + property bool hovered: ma.hovered property string sourceUrl: { if (!encrypted) - return "image://colorimage/"+unencryptedIcon+"?"; + return "image://colorimage/" + unencryptedIcon + "?"; switch (trust) { case Crypto.Verified: @@ -46,10 +48,10 @@ Image { return sourceUrl + Nheko.theme.error; } } else { - return sourceUrl + unencryptedColor; + return sourceUrl + (stateImg.hovered ? unencryptedHoverColor : unencryptedColor); } } - ToolTip.visible: ma.hovered + ToolTip.visible: stateImg.hovered ToolTip.text: { if (!encrypted) return qsTr("This message is not encrypted!"); diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index f31123e5..6029a31d 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -4,6 +4,7 @@ import "./emoji" import "./voip" +import "./ui" import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 @@ -90,8 +91,9 @@ Rectangle { color: Nheko.colors.window visible: room && room.input.uploading - NhekoBusyIndicator { - anchors.fill: parent + Spinner { + anchors.centerIn: parent + height: parent.height / 2 running: parent.visible } diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index 45b44022..f9aaf9dd 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -206,7 +206,7 @@ Item { Shortcut { sequence: StandardKey.MoveToPreviousPage onActivated: { - chat.contentY = chat.contentY - chat.height / 2; + chat.contentY = chat.contentY - chat.height * 0.9; chat.returnToBounds(); } } @@ -214,7 +214,7 @@ Item { Shortcut { sequence: StandardKey.MoveToNextPage onActivated: { - chat.contentY = chat.contentY + chat.height / 2; + chat.contentY = chat.contentY + chat.height * 0.9; chat.returnToBounds(); } } diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml deleted file mode 100644 index f3d1e8a4..00000000 --- a/resources/qml/NhekoBusyIndicator.qml +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -import QtQuick 2.9 -import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.2 -import im.nheko 1.0 - -BusyIndicator { - id: control - - contentItem: Item { - implicitWidth: 64 - implicitHeight: 64 - - Item { - id: item - - height: Math.min(parent.height, parent.width) - width: height - opacity: control.running ? 1 : 0 - - RotationAnimator { - target: item - running: control.visible && control.running - from: 0 - to: 360 - loops: Animation.Infinite - duration: 2000 - } - - Repeater { - id: repeater - - model: 6 - - Rectangle { - implicitWidth: radius * 2 - implicitHeight: radius * 2 - radius: item.height / 8 - color: Nheko.colors.text - opacity: (index + 2) / (repeater.count + 2) - transform: [ - Translate { - y: item.height / 2 - }, - Rotation { - angle: index / repeater.count * 360 - origin.x: item.height / 2 - origin.y: item.height / 2 - } - ] - } - - } - - Behavior on opacity { - OpacityAnimator { - duration: 250 - } - - } - - } - - } - -} diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml index d0a8f2e8..9584eb8d 100644 --- a/resources/qml/Root.qml +++ b/resources/qml/Root.qml @@ -268,8 +268,6 @@ Pane { var component = Qt.createComponent("qrc:/qml/dialogs/InviteDialog.qml") if (component.status == Component.Ready) { var dialog = component.createObject(timelineRoot, { - "roomId": Rooms.currentRoom.roomId, - "plainRoomName": Rooms.currentRoom.plainRoomName, "invitees": invitees }); dialog.show(); diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index e836f60f..c7b554b8 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -279,6 +279,13 @@ Item { onClicked: Rooms.declineInvite(roomPreview.roomid) } + FlatButton { + visible: !!room + Layout.alignment: Qt.AlignHCenter + text: qsTr("leave") + onClicked: TimelineManager.openLeaveRoomDialog(room.roomId) + } + ScrollView { id: reasonField property bool showReason: false diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml index b7adf21f..20e82ad6 100644 --- a/resources/qml/ToggleButton.qml +++ b/resources/qml/ToggleButton.qml @@ -25,7 +25,7 @@ Switch { width: parent.width - height x: radius y: parent.height / 2 - height / 2 - color: toggleButton.checked ? "skyblue" : "grey" + color: toggleButton.checked ? Nheko.colors.highlight : "grey" border.color: "#cccccc" } diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 0e4ca4e7..f23645a7 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -242,26 +242,26 @@ Pane { enabled: false unencryptedIcon: ":/icons/icons/ui/people.svg" unencryptedColor: Nheko.colors.buttonText - } - - background: null - - ToolTip.delay: Nheko.tooltipDelay - ToolTip.text: { - if (!isEncrypted) - return qsTr("Show room members."); - - switch (trustlevel) { - case Crypto.Verified: - return qsTr("This room contains only verified devices."); - case Crypto.TOFU: - return qsTr("This room contains verified devices and devices which have never changed their master key."); - default: - return qsTr("This room contains unverified devices!"); + unencryptedHoverColor: Nheko.colors.highlight + hovered: parent.hovered + + ToolTip.delay: Nheko.tooltipDelay + ToolTip.text: { + if (!isEncrypted) + return qsTr("Show room members."); + + switch (trustlevel) { + case Crypto.Verified: + return qsTr("This room contains only verified devices."); + case Crypto.TOFU: + return qsTr("This room contains verified devices and devices which have never changed their master key."); + default: + return qsTr("This room contains unverified devices!"); + } } } - ToolTip.visible: hovered + background: null onClicked: TimelineManager.openRoomMembers(room) } diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml index ee555795..b142818d 100644 --- a/resources/qml/dialogs/InviteDialog.qml +++ b/resources/qml/dialogs/InviteDialog.qml @@ -12,8 +12,6 @@ import im.nheko 1.0 ApplicationWindow { id: inviteDialogRoot - property string roomId - property string plainRoomName property InviteesModel invitees property var friendsCompleter property var profile @@ -39,7 +37,7 @@ ApplicationWindow { close(); } - title: qsTr("Invite users to %1").arg(plainRoomName) + title: qsTr("Invite users to %1").arg(invitees.room.plainRoomName) height: 380 width: 340 palette: Nheko.colors diff --git a/resources/qml/dialogs/ReadReceipts.qml b/resources/qml/dialogs/ReadReceipts.qml index f90da997..3d23a5fc 100644 --- a/resources/qml/dialogs/ReadReceipts.qml +++ b/resources/qml/dialogs/ReadReceipts.qml @@ -78,6 +78,8 @@ ApplicationWindow { anchors.margins: Nheko.paddingSmall Avatar { + id: avatar + width: Nheko.avatarSize height: Nheko.avatarSize userid: model.mxid @@ -88,25 +90,26 @@ ApplicationWindow { ColumnLayout { spacing: Nheko.paddingSmall + Layout.fillWidth: true - Label { + ElidedLabel { text: model.displayName color: TimelineManager.userColor(model ? model.mxid : "", Nheko.colors.window) font.pointSize: fontMetrics.font.pointSize + elideWidth: del.width - Nheko.paddingMedium - avatar.width + Layout.fillWidth: true } - Label { + ElidedLabel { text: model.timestamp color: Nheko.colors.buttonText font.pointSize: fontMetrics.font.pointSize * 0.9 + elideWidth: del.width - Nheko.paddingMedium - avatar.width + Layout.fillWidth: true } } - Item { - Layout.fillWidth: true - } - } CursorShape { diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml index ea4451bb..1cfbe077 100644 --- a/resources/qml/dialogs/RoomMembers.qml +++ b/resources/qml/dialogs/RoomMembers.qml @@ -146,12 +146,14 @@ ApplicationWindow { ColumnLayout { spacing: Nheko.paddingSmall + Layout.fillWidth: true 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 + Layout.fillWidth: true } ElidedLabel { @@ -159,14 +161,11 @@ ApplicationWindow { 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 + Layout.fillWidth: true } } - Item { - Layout.fillWidth: true - } - Image { property bool isAdmin: room.permissions.changeLevel(MtxEvent.PowerLevels) <= model.powerlevel property bool isModerator: room.permissions.redactLevel() <= model.powerlevel diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml index 5544841f..845f4d7a 100644 --- a/resources/qml/dialogs/RoomSettings.qml +++ b/resources/qml/dialogs/RoomSettings.qml @@ -395,7 +395,8 @@ ApplicationWindow { checked = true; return ; } - confirmEncryptionDialog.open(); + if (checked === true) + confirmEncryptionDialog.open(); } Layout.alignment: Qt.AlignRight } diff --git a/resources/res.qrc b/resources/res.qrc index 88159d40..9c7d0c87 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -111,7 +111,6 @@ qml/UploadBox.qml qml/MessageInput.qml qml/MessageView.qml - qml/NhekoBusyIndicator.qml qml/PrivacyScreen.qml qml/Reactions.qml qml/ReplyPopup.qml diff --git a/src/InviteesModel.cpp b/src/InviteesModel.cpp index 2b95a36f..7b49c234 100644 --- a/src/InviteesModel.cpp +++ b/src/InviteesModel.cpp @@ -9,8 +9,9 @@ #include "MatrixClient.h" #include "mtx/responses/profile.hpp" -InviteesModel::InviteesModel(QObject *parent) +InviteesModel::InviteesModel(TimelineModel *room, QObject *parent) : QAbstractListModel{parent} + , room_{room} { } diff --git a/src/InviteesModel.h b/src/InviteesModel.h index 8fe8fc22..ab8fbdb4 100644 --- a/src/InviteesModel.h +++ b/src/InviteesModel.h @@ -8,6 +8,8 @@ #include #include +class TimelineModel; + class Invitee final : public QObject { Q_OBJECT @@ -34,6 +36,7 @@ class InviteesModel final : public QAbstractListModel Q_OBJECT Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + Q_PROPERTY(TimelineModel *room READ room CONSTANT) public: enum Roles @@ -43,7 +46,9 @@ public: AvatarUrl, }; - InviteesModel(QObject *parent = nullptr); + InviteesModel(TimelineModel *room, QObject *parent = nullptr); + + TimelineModel *room() const { return room_; } Q_INVOKABLE void addUser(QString mxid, QString displayName = "", QString avatarUrl = ""); Q_INVOKABLE void removeUser(QString mxid); @@ -63,6 +68,7 @@ signals: private: QVector invitees_; + TimelineModel *room_; }; #endif // INVITEESMODEL_H diff --git a/src/Utils.cpp b/src/Utils.cpp index b753cfdb..63dcdd00 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -141,7 +141,9 @@ utils::replaceEmoji(const QString &body) if (!insideTag && utils::codepointIsEmoji(code)) { if (!insideFontBlock) { fmtBody += QStringLiteral("emojiFont() % - QStringLiteral("\">"); + (UserSettings::instance()->enlargeEmojiOnlyMessages() + ? QStringLiteral("\" size=\"4\">") + : QStringLiteral("\">")); insideFontBlock = true; } else if (code == 0xfe0f) { // BUG(Nico): diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index cdcc689d..c19d0c3f 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -180,7 +180,7 @@ TimelineViewManager::openRoomSettings(QString room_id) void TimelineViewManager::openInviteUsers(QString roomId) { - InviteesModel *model = new InviteesModel{}; + InviteesModel *model = new InviteesModel{rooms_->getRoomById(roomId).data()}; connect(model, &InviteesModel::accept, this, [this, model, roomId]() { emit inviteUsers(roomId, model->mxids()); });