From 3e6c426397ece5a8671b05bce98857d782a3b04f Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 21 Jul 2023 11:17:48 +0200 Subject: [PATCH] Port Avatar usage in Settings KirigamiAddons --- src/matriximageprovider.cpp | 12 +- src/matriximageprovider.h | 2 +- src/qml/Component/ChatBox/CompletionMenu.qml | 41 ++---- .../Component/NeochatMaximizeComponent.qml | 2 +- src/qml/Page/RoomList/RoomDelegate.qml | 14 +- src/qml/Panel/GroupChatDrawerHeader.qml | 3 + src/qml/RoomSettings/General.qml | 5 +- src/qml/RoomSettings/Permissions.qml | 107 +++++++++------ src/qml/Settings/AccountEditorPage.qml | 122 ++++++++++-------- src/qml/Settings/AccountsPage.qml | 3 +- src/qml/Settings/AppearanceSettingsPage.qml | 9 +- 11 files changed, 175 insertions(+), 145 deletions(-) diff --git a/src/matriximageprovider.cpp b/src/matriximageprovider.cpp index f978cf82a..cbfa2e0b8 100644 --- a/src/matriximageprovider.cpp +++ b/src/matriximageprovider.cpp @@ -32,11 +32,17 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size) requestedSize.setWidth(100); } if (mediaId.count('/') != 1) { - errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId); - Q_EMIT finished(); - return; + if (mediaId.startsWith(QLatin1Char('/'))) { + mediaId = mediaId.mid(1); + } else { + errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId); + Q_EMIT finished(); + return; + } } + mediaId = mediaId.split(QLatin1Char('?'))[0]; + QImage cachedImage; if (cachedImage.load(localFile)) { image = cachedImage; diff --git a/src/matriximageprovider.h b/src/matriximageprovider.h index a3736e1c8..d20c30475 100644 --- a/src/matriximageprovider.h +++ b/src/matriximageprovider.h @@ -34,7 +34,7 @@ private Q_SLOTS: void prepareResult(); private: - const QString mediaId; + QString mediaId; QSize requestedSize; const QString localFile; Quotient::MediaThumbnailJob *job = nullptr; diff --git a/src/qml/Component/ChatBox/CompletionMenu.qml b/src/qml/Component/ChatBox/CompletionMenu.qml index bc1de4a07..22e8eb37e 100644 --- a/src/qml/Component/ChatBox/CompletionMenu.qml +++ b/src/qml/Component/ChatBox/CompletionMenu.qml @@ -8,8 +8,6 @@ import QtQuick.Controls 2.15 as QQC2 import Qt.labs.qmlmodels 1.0 import org.kde.kirigami 2.15 as Kirigami -import org.kde.kirigamiaddons.delegates 1.0 as Delegates -import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 @@ -45,7 +43,6 @@ QQC2.Popup { rightPadding: 0 topPadding: 0 bottomPadding: 0 - implicitHeight: Math.min(completions.contentHeight, Kirigami.Units.gridUnit * 10) contentItem: ListView { @@ -56,35 +53,23 @@ QQC2.Popup { currentIndex: 0 keyNavigationWraps: true highlightMoveDuration: 100 - delegate: Delegates.RoundedItemDelegate { - id: completionDelegate - - required property int index - required property string displayName - required property string subtitle - required property string iconName - - text: displayName - - contentItem: RowLayout { - KirigamiComponents.Avatar { - visible: completionDelegate.iconName !== "invalid" - Layout.preferredWidth: Kirigami.Units.iconSizes.medium - Layout.preferredHeight: Kirigami.Units.iconSizes.medium - source: completionDelegate.iconName === "invalid" ? "" : ("image://" + completionDelegate.iconName) - name: completionDelegate.text - } - Delegates.SubtitleContentItem { - itemDelegate: completionDelegate - labelItem.textFormat: Text.PlainText - subtitle: completionDelegate.subtitle ?? "" - subtitleItem.textFormat: Text.PlainText + delegate: Kirigami.BasicListItem { + text: model.text + subtitle: model.subtitle ?? "" + labelItem.textFormat: Text.PlainText + subtitleItem.textFormat: Text.PlainText + leading: RowLayout { + Kirigami.Avatar { + visible: model.icon !== "invalid" + Layout.preferredWidth: height + Layout.fillHeight: true + source: model.icon === "invalid" ? "" : ("image://mxc/" + model.icon) + name: model.text } } - onClicked: completionMenu.chatDocumentHandler.complete(completionDelegate.index) + onClicked: completionMenu.chatDocumentHandler.complete(model.index) } } - background: Rectangle { color: Kirigami.Theme.backgroundColor } diff --git a/src/qml/Component/NeochatMaximizeComponent.qml b/src/qml/Component/NeochatMaximizeComponent.qml index 7a3cbd56d..604f5644e 100644 --- a/src/qml/Component/NeochatMaximizeComponent.qml +++ b/src/qml/Component/NeochatMaximizeComponent.qml @@ -56,7 +56,7 @@ Components.AlbumMaximizeComponent { } leading: RowLayout { - Kirigami.Avatar { + Components.Avatar { id: userAvatar implicitWidth: Kirigami.Units.iconSizes.medium implicitHeight: Kirigami.Units.iconSizes.medium diff --git a/src/qml/Page/RoomList/RoomDelegate.qml b/src/qml/Page/RoomList/RoomDelegate.qml index 768bcb495..beb204aa5 100644 --- a/src/qml/Page/RoomList/RoomDelegate.qml +++ b/src/qml/Page/RoomList/RoomDelegate.qml @@ -40,19 +40,17 @@ Delegates.RoundedItemDelegate { } contentItem: RowLayout { + spacing: Kirigami.Units.largeSpacing + Components.Avatar { source: root.avatar ? "image://mxc/" + root.avatar : "" name: root.displayName - implicitWidth: visible ? height : 0 - implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing visible: Config.showAvatarInRoomDrawer - sourceSize { - width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing - height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing - } + implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 + implicitWidth: visible ? implicitHeight : 0 - Layout.topMargin: Kirigami.Units.largeSpacing / 2 - Layout.bottomMargin: Kirigami.Units.largeSpacing / 2 + Layout.fillHeight: true + Layout.preferredWidth: height } ColumnLayout { diff --git a/src/qml/Panel/GroupChatDrawerHeader.qml b/src/qml/Panel/GroupChatDrawerHeader.qml index c0e443604..3c1654fc1 100644 --- a/src/qml/Panel/GroupChatDrawerHeader.qml +++ b/src/qml/Panel/GroupChatDrawerHeader.qml @@ -18,6 +18,9 @@ ColumnLayout { RowLayout { Layout.fillWidth: true Layout.leftMargin: Kirigami.Units.largeSpacing + Layout.topMargin: Kirigami.Units.largeSpacing + Layout.bottomMargin: Kirigami.Units.largeSpacing + spacing: Kirigami.Units.largeSpacing KirigamiComponents.Avatar { diff --git a/src/qml/RoomSettings/General.qml b/src/qml/RoomSettings/General.qml index bd8add7fb..a125fc1c5 100644 --- a/src/qml/RoomSettings/General.qml +++ b/src/qml/RoomSettings/General.qml @@ -9,6 +9,7 @@ import QtQuick.Window 2.15 import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 @@ -38,11 +39,13 @@ Kirigami.ScrollablePage { Item { Layout.fillWidth: true } - Kirigami.Avatar { + KirigamiComponents.Avatar { id: avatar Layout.alignment: Qt.AlignRight name: room.name source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : "" + implicitWidth: Kirigami.Units.iconSizes.medium + implicitHeight: Kirigami.Units.iconSizes.medium } QQC2.Button { Layout.alignment: Qt.AlignLeft diff --git a/src/qml/RoomSettings/Permissions.qml b/src/qml/RoomSettings/Permissions.qml index e50086cc4..07b8a942c 100644 --- a/src/qml/RoomSettings/Permissions.qml +++ b/src/qml/RoomSettings/Permissions.qml @@ -7,6 +7,8 @@ import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.delegates 1.0 as Delegates +import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.kitemmodels 1.0 import org.kde.neochat 1.0 @@ -93,17 +95,19 @@ Kirigami.ScrollablePage { visible: room.canSendState("m.room.power_levels") contentItem: Kirigami.SearchField { - id: userListSearchField - Layout.fillWidth: true - autoAccept: false + id: userListSearchField - Keys.onUpPressed: userListView.decrementCurrentIndex() - Keys.onDownPressed: userListView.incrementCurrentIndex() + autoAccept: false - onAccepted: { - let currentUser = userListView.itemAtIndex(userListView.currentIndex); - currentUser.action.trigger(); - } + Layout.fillWidth: true + + Keys.onUpPressed: userListView.decrementCurrentIndex() + Keys.onDownPressed: userListView.incrementCurrentIndex() + + onAccepted: { + let currentUser = userListView.itemAtIndex(userListView.currentIndex); + currentUser.action.trigger(); + } } QQC2.Popup { id: userListSearchPopup @@ -119,21 +123,31 @@ Kirigami.ScrollablePage { return Math.max(Math.min(filterContentHeight, maxHeight), minHeight); } padding: Kirigami.Units.smallSpacing + leftPadding: Kirigami.Units.smallSpacing / 2 + rightPadding: Kirigami.Units.smallSpacing / 2 modal: false onClosed: userListSearchField.text = "" background: Kirigami.ShadowedRectangle { + property color borderColor: Kirigami.Theme.textColor + + Kirigami.Theme.colorSet: Kirigami.Theme.View + Kirigami.Theme.inherit: false + radius: 4 color: Kirigami.Theme.backgroundColor - property color borderColor: Kirigami.Theme.textColor - border.color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) - border.width: 1 + border { + color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) + width: 1 + } - shadow.xOffset: 0 - shadow.yOffset: 4 - shadow.color: Qt.rgba(0, 0, 0, 0.3) - shadow.size: 8 + shadow { + xOffset: 0 + yOffset: 4 + color: Qt.rgba(0, 0, 0, 0.3) + size: 8 + } } contentItem: QQC2.ScrollView { @@ -158,16 +172,42 @@ Kirigami.ScrollablePage { } } - delegate: Kirigami.BasicListItem { + delegate: Delegates.RoundedItemDelegate { id: userListItem - implicitHeight: Kirigami.Units.gridUnit * 2 - leftPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing + required property string userId + required property string avatar + required property string name + required property int powerLevel + required property string powerLevelString - label: name - labelItem.textFormat: Text.PlainText - subtitle: userId - subtitleItem.textFormat: Text.PlainText + text: name + + contentItem: RowLayout { + KirigamiComponents.Avatar { + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + source: userListItem.avatar ? ("image://" + userListItem.avatar) : "" + name: userListItem.name + } + + Delegates.SubtitleContentItem { + itemDelegate: userListItem + subtitle: userListItem.userId + labelItem.textFormat: Text.PlainText + subtitleItem.textFormat: Text.PlainText + Layout.fillWidth: true + } + + QQC2.Label { + visible: userListItem.powerLevel > 0 + + text: userListItem.powerLevelString + color: Kirigami.Theme.disabledTextColor + textFormat: Text.PlainText + wrapMode: Text.NoWrap + } + } action: Kirigami.Action { id: editPowerLevelAction @@ -175,30 +215,13 @@ Kirigami.ScrollablePage { userListSearchPopup.close() let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { room: root.room, - userId: model.userId, - powerLevel: model.powerLevel + userId: userListItem.userId, + powerLevel: userListItem.powerLevel }); dialog.open(); } } - leading: Kirigami.Avatar { - implicitWidth: height - sourceSize.height: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5 - sourceSize.width: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5 - source: avatar ? ("image://mxc/" + avatar) : "" - name: model.userId - } - - trailing: QQC2.Label { - visible: powerLevel > 0 - - text: powerLevelString - color: Kirigami.Theme.disabledTextColor - textFormat: Text.PlainText - wrapMode: Text.NoWrap - } - Component { id: powerLevelDialog PowerLevelDialog { diff --git a/src/qml/Settings/AccountEditorPage.qml b/src/qml/Settings/AccountEditorPage.qml index beefd497f..0d4962528 100644 --- a/src/qml/Settings/AccountEditorPage.qml +++ b/src/qml/Settings/AccountEditorPage.qml @@ -10,6 +10,7 @@ import QtQuick.Window 2.15 import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 Kirigami.ScrollablePage { @@ -24,6 +25,62 @@ Kirigami.ScrollablePage { rightPadding: 0 ColumnLayout { spacing: 0 + + QQC2.RoundButton { + property var fileDialog: null; + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.topMargin: Kirigami.Units.largeSpacing + + // Square button + implicitWidth: Kirigami.Units.gridUnit * 5 + implicitHeight: implicitWidth + + padding: 0 + + contentItem: KirigamiComponents.Avatar { + id: avatar + source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : "" + name: root.connection.localUser.displayName + } + + onClicked: { + if (fileDialog != null) { + return; + } + + fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.Overlay) + fileDialog.chosen.connect(function(receivedSource) { + mouseArea.fileDialog = null; + if (!receivedSource) { + return; + } + parent.source = receivedSource; + }); + fileDialog.onRejected.connect(function() { + mouseArea.fileDialog = null; + }); + fileDialog.open(); + } + + QQC2.Button { + anchors { + bottom: parent.bottom + right: parent.right + } + visible: avatar.source.toString().length !== 0 + icon.name: "edit-clear" + text: i18n("Remove current avatar") + display: QQC2.AbstractButton.IconOnly + + onClicked: avatar.source = "" + + QQC2.ToolTip.text: text + QQC2.ToolTip.visible: hovered + QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay + } + } + MobileForm.FormHeader { Layout.fillWidth: true title: i18n("User information") @@ -32,73 +89,22 @@ Kirigami.ScrollablePage { Layout.fillWidth: true contentItem: ColumnLayout { spacing: 0 - MobileForm.AbstractFormDelegate { - Layout.fillWidth: true - background: Item {} - contentItem: RowLayout { - Item { - Layout.fillWidth: true - } - Kirigami.Avatar { - id: avatar - Layout.alignment: Qt.AlignRight - source: root.connection && root.connection.localUser.avatarMediaId ? ("image://mxc/" + root.connection.localUser.avatarMediaId) : "" - name: root.connection.localUser.displayName - - MouseArea { - id: mouseArea - anchors.fill: parent - property var fileDialog: null; - onClicked: { - if (fileDialog != null) { - return; - } - - fileDialog = openFileDialog.createObject(QQC2.ApplicationWindow.Overlay) - fileDialog.chosen.connect(function(receivedSource) { - mouseArea.fileDialog = null; - if (!receivedSource) { - return; - } - parent.source = receivedSource; - }); - fileDialog.onRejected.connect(function() { - mouseArea.fileDialog = null; - }); - fileDialog.open(); - } - } - } - QQC2.Button { - Layout.alignment: Qt.AlignLeft - visible: avatar.source.toString().length !== 0 - icon.name: "edit-clear" - text: i18n("Remove current avatar") - display: QQC2.AbstractButton.IconOnly - - onClicked: avatar.source = "" - - QQC2.ToolTip.text: text - QQC2.ToolTip.visible: hovered - } - Item { - Layout.fillWidth: true - } - } - } MobileForm.FormTextFieldDelegate { id: name label: i18n("Name:") text: root.connection ? root.connection.localUser.displayName : "" } + MobileForm.FormDelegateSeparator {} MobileForm.FormTextFieldDelegate { id: accountLabel label: i18n("Label:") text: root.connection ? Controller.activeAccountLabel : "" } + MobileForm.FormDelegateSeparator {} MobileForm.AbstractFormDelegate { Layout.fillWidth: true - background: Item {} + background: null + padding: Kirigami.Units.smallSpacing contentItem: RowLayout { Item { Layout.fillWidth: true @@ -136,18 +142,21 @@ Kirigami.ScrollablePage { visible: root.connection !== undefined && root.connection.canChangePassword === false text: i18n("Your server doesn't support changing your password") } + MobileForm.FormDelegateSeparator { visible: root.connection !== undefined && root.connection.canChangePassword === false } MobileForm.FormTextFieldDelegate { id: currentPassword label: i18n("Current Password:") enabled: root.connection !== undefined && root.connection.canChangePassword !== false echoMode: TextInput.Password } + MobileForm.FormDelegateSeparator {} MobileForm.FormTextFieldDelegate { id: newPassword label: i18n("New Password:") enabled: root.connection !== undefined && root.connection.canChangePassword !== false echoMode: TextInput.Password } + MobileForm.FormDelegateSeparator {} MobileForm.FormTextFieldDelegate { id: confirmPassword label: i18n("Confirm new Password:") @@ -161,9 +170,10 @@ Kirigami.ScrollablePage { confirmPassword.statusMessage = ''; } } + MobileForm.FormDelegateSeparator {} MobileForm.AbstractFormDelegate { Layout.fillWidth: true - background: Item {} + background: null contentItem: RowLayout { Item { Layout.fillWidth: true diff --git a/src/qml/Settings/AccountsPage.qml b/src/qml/Settings/AccountsPage.qml index 28f1a53b8..584383334 100644 --- a/src/qml/Settings/AccountsPage.qml +++ b/src/qml/Settings/AccountsPage.qml @@ -8,6 +8,7 @@ import Qt.labs.platform 1.1 import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 @@ -38,7 +39,7 @@ Kirigami.ScrollablePage { }) contentItem: RowLayout { - Kirigami.Avatar { + KirigamiComponents.Avatar { name: model.connection.localUser.displayName source: model.connection.localUser.avatarMediaId ? ("image://mxc/" + model.connection.localUser.avatarMediaId) : "" diff --git a/src/qml/Settings/AppearanceSettingsPage.qml b/src/qml/Settings/AppearanceSettingsPage.qml index 5b2217fd2..186850102 100644 --- a/src/qml/Settings/AppearanceSettingsPage.qml +++ b/src/qml/Settings/AppearanceSettingsPage.qml @@ -8,6 +8,7 @@ import QtQuick.Layouts 1.15 import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm +import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents import org.kde.neochat 1.0 @@ -42,7 +43,7 @@ Kirigami.ScrollablePage { innerObject: [ RowLayout { Layout.fillWidth: true - Kirigami.Avatar { + KirigamiComponents.Avatar { color: "#4a5bcc" Layout.alignment: Qt.AlignTop visible: Config.showAvatarInTimeline @@ -79,7 +80,7 @@ Kirigami.ScrollablePage { }, RowLayout { Layout.fillWidth: true - Kirigami.Avatar { + KirigamiComponents.Avatar { color: "#9f244b" Layout.alignment: Qt.AlignTop visible: Config.showAvatarInTimeline @@ -132,7 +133,7 @@ Kirigami.ScrollablePage { innerObject: [ RowLayout { Layout.fillWidth: true - Kirigami.Avatar { + KirigamiComponents.Avatar { color: "#4a5bcc" Layout.alignment: Qt.AlignTop visible: Config.showAvatarInTimeline @@ -159,7 +160,7 @@ Kirigami.ScrollablePage { }, RowLayout { Layout.fillWidth: true - Kirigami.Avatar { + KirigamiComponents.Avatar { color: "#9f244b" Layout.alignment: Qt.AlignTop visible: Config.showAvatarInTimeline