Port Avatar usage in Settings KirigamiAddons

(cherry picked from commit 3e6c426397)
This commit is contained in:
Carl Schwan
2023-07-21 11:17:48 +02:00
parent 410befa4bf
commit 1688b00f48
11 changed files with 175 additions and 145 deletions

View File

@@ -32,11 +32,17 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size)
requestedSize.setWidth(100); requestedSize.setWidth(100);
} }
if (mediaId.count('/') != 1) { if (mediaId.count('/') != 1) {
errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId); if (mediaId.startsWith(QLatin1Char('/'))) {
Q_EMIT finished(); mediaId = mediaId.mid(1);
return; } else {
errorStr = i18n("Media id '%1' doesn't follow server/mediaId pattern", mediaId);
Q_EMIT finished();
return;
}
} }
mediaId = mediaId.split(QLatin1Char('?'))[0];
QImage cachedImage; QImage cachedImage;
if (cachedImage.load(localFile)) { if (cachedImage.load(localFile)) {
image = cachedImage; image = cachedImage;

View File

@@ -34,7 +34,7 @@ private Q_SLOTS:
void prepareResult(); void prepareResult();
private: private:
const QString mediaId; QString mediaId;
QSize requestedSize; QSize requestedSize;
const QString localFile; const QString localFile;
Quotient::MediaThumbnailJob *job = nullptr; Quotient::MediaThumbnailJob *job = nullptr;

View File

@@ -8,8 +8,6 @@ import QtQuick.Controls 2.15 as QQC2
import Qt.labs.qmlmodels 1.0 import Qt.labs.qmlmodels 1.0
import org.kde.kirigami 2.15 as Kirigami 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 import org.kde.neochat 1.0
@@ -45,7 +43,6 @@ QQC2.Popup {
rightPadding: 0 rightPadding: 0
topPadding: 0 topPadding: 0
bottomPadding: 0 bottomPadding: 0
implicitHeight: Math.min(completions.contentHeight, Kirigami.Units.gridUnit * 10) implicitHeight: Math.min(completions.contentHeight, Kirigami.Units.gridUnit * 10)
contentItem: ListView { contentItem: ListView {
@@ -56,35 +53,23 @@ QQC2.Popup {
currentIndex: 0 currentIndex: 0
keyNavigationWraps: true keyNavigationWraps: true
highlightMoveDuration: 100 highlightMoveDuration: 100
delegate: Delegates.RoundedItemDelegate { delegate: Kirigami.BasicListItem {
id: completionDelegate text: model.text
subtitle: model.subtitle ?? ""
required property int index labelItem.textFormat: Text.PlainText
required property string displayName subtitleItem.textFormat: Text.PlainText
required property string subtitle leading: RowLayout {
required property string iconName Kirigami.Avatar {
visible: model.icon !== "invalid"
text: displayName Layout.preferredWidth: height
Layout.fillHeight: true
contentItem: RowLayout { source: model.icon === "invalid" ? "" : ("image://mxc/" + model.icon)
KirigamiComponents.Avatar { name: model.text
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
} }
} }
onClicked: completionMenu.chatDocumentHandler.complete(completionDelegate.index) onClicked: completionMenu.chatDocumentHandler.complete(model.index)
} }
} }
background: Rectangle { background: Rectangle {
color: Kirigami.Theme.backgroundColor color: Kirigami.Theme.backgroundColor
} }

View File

@@ -56,7 +56,7 @@ Components.AlbumMaximizeComponent {
} }
leading: RowLayout { leading: RowLayout {
Kirigami.Avatar { Components.Avatar {
id: userAvatar id: userAvatar
implicitWidth: Kirigami.Units.iconSizes.medium implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium implicitHeight: Kirigami.Units.iconSizes.medium

View File

@@ -40,19 +40,17 @@ Delegates.RoundedItemDelegate {
} }
contentItem: RowLayout { contentItem: RowLayout {
spacing: Kirigami.Units.largeSpacing
Components.Avatar { Components.Avatar {
source: root.avatar ? "image://mxc/" + root.avatar : "" source: root.avatar ? "image://mxc/" + root.avatar : ""
name: root.displayName name: root.displayName
implicitWidth: visible ? height : 0
implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing
visible: Config.showAvatarInRoomDrawer visible: Config.showAvatarInRoomDrawer
sourceSize { implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing implicitWidth: visible ? implicitHeight : 0
height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing
}
Layout.topMargin: Kirigami.Units.largeSpacing / 2 Layout.fillHeight: true
Layout.bottomMargin: Kirigami.Units.largeSpacing / 2 Layout.preferredWidth: height
} }
ColumnLayout { ColumnLayout {

View File

@@ -18,6 +18,9 @@ ColumnLayout {
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.bottomMargin: Kirigami.Units.largeSpacing
spacing: Kirigami.Units.largeSpacing spacing: Kirigami.Units.largeSpacing
KirigamiComponents.Avatar { KirigamiComponents.Avatar {

View File

@@ -9,6 +9,7 @@ import QtQuick.Window 2.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm 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 import org.kde.neochat 1.0
@@ -38,11 +39,13 @@ Kirigami.ScrollablePage {
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
Kirigami.Avatar { KirigamiComponents.Avatar {
id: avatar id: avatar
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
name: room.name name: room.name
source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : "" source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
} }
QQC2.Button { QQC2.Button {
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft

View File

@@ -7,6 +7,8 @@ import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm 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.kitemmodels 1.0
import org.kde.neochat 1.0 import org.kde.neochat 1.0
@@ -93,17 +95,19 @@ Kirigami.ScrollablePage {
visible: room.canSendState("m.room.power_levels") visible: room.canSendState("m.room.power_levels")
contentItem: Kirigami.SearchField { contentItem: Kirigami.SearchField {
id: userListSearchField id: userListSearchField
Layout.fillWidth: true
autoAccept: false
Keys.onUpPressed: userListView.decrementCurrentIndex() autoAccept: false
Keys.onDownPressed: userListView.incrementCurrentIndex()
onAccepted: { Layout.fillWidth: true
let currentUser = userListView.itemAtIndex(userListView.currentIndex);
currentUser.action.trigger(); Keys.onUpPressed: userListView.decrementCurrentIndex()
} Keys.onDownPressed: userListView.incrementCurrentIndex()
onAccepted: {
let currentUser = userListView.itemAtIndex(userListView.currentIndex);
currentUser.action.trigger();
}
} }
QQC2.Popup { QQC2.Popup {
id: userListSearchPopup id: userListSearchPopup
@@ -119,21 +123,31 @@ Kirigami.ScrollablePage {
return Math.max(Math.min(filterContentHeight, maxHeight), minHeight); return Math.max(Math.min(filterContentHeight, maxHeight), minHeight);
} }
padding: Kirigami.Units.smallSpacing padding: Kirigami.Units.smallSpacing
leftPadding: Kirigami.Units.smallSpacing / 2
rightPadding: Kirigami.Units.smallSpacing / 2
modal: false modal: false
onClosed: userListSearchField.text = "" onClosed: userListSearchField.text = ""
background: Kirigami.ShadowedRectangle { background: Kirigami.ShadowedRectangle {
property color borderColor: Kirigami.Theme.textColor
Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false
radius: 4 radius: 4
color: Kirigami.Theme.backgroundColor color: Kirigami.Theme.backgroundColor
property color borderColor: Kirigami.Theme.textColor border {
border.color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3)
border.width: 1 width: 1
}
shadow.xOffset: 0 shadow {
shadow.yOffset: 4 xOffset: 0
shadow.color: Qt.rgba(0, 0, 0, 0.3) yOffset: 4
shadow.size: 8 color: Qt.rgba(0, 0, 0, 0.3)
size: 8
}
} }
contentItem: QQC2.ScrollView { contentItem: QQC2.ScrollView {
@@ -158,16 +172,42 @@ Kirigami.ScrollablePage {
} }
} }
delegate: Kirigami.BasicListItem { delegate: Delegates.RoundedItemDelegate {
id: userListItem id: userListItem
implicitHeight: Kirigami.Units.gridUnit * 2 required property string userId
leftPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing required property string avatar
required property string name
required property int powerLevel
required property string powerLevelString
label: name text: name
labelItem.textFormat: Text.PlainText
subtitle: userId contentItem: RowLayout {
subtitleItem.textFormat: Text.PlainText 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 { action: Kirigami.Action {
id: editPowerLevelAction id: editPowerLevelAction
@@ -175,30 +215,13 @@ Kirigami.ScrollablePage {
userListSearchPopup.close() userListSearchPopup.close()
let dialog = powerLevelDialog.createObject(applicationWindow().overlay, { let dialog = powerLevelDialog.createObject(applicationWindow().overlay, {
room: root.room, room: root.room,
userId: model.userId, userId: userListItem.userId,
powerLevel: model.powerLevel powerLevel: userListItem.powerLevel
}); });
dialog.open(); 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 { Component {
id: powerLevelDialog id: powerLevelDialog
PowerLevelDialog { PowerLevelDialog {

View File

@@ -10,6 +10,7 @@ import QtQuick.Window 2.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm 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 import org.kde.neochat 1.0
Kirigami.ScrollablePage { Kirigami.ScrollablePage {
@@ -24,6 +25,62 @@ Kirigami.ScrollablePage {
rightPadding: 0 rightPadding: 0
ColumnLayout { ColumnLayout {
spacing: 0 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 { MobileForm.FormHeader {
Layout.fillWidth: true Layout.fillWidth: true
title: i18n("User information") title: i18n("User information")
@@ -32,73 +89,22 @@ Kirigami.ScrollablePage {
Layout.fillWidth: true Layout.fillWidth: true
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 0 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 { MobileForm.FormTextFieldDelegate {
id: name id: name
label: i18n("Name:") label: i18n("Name:")
text: root.connection ? root.connection.localUser.displayName : "" text: root.connection ? root.connection.localUser.displayName : ""
} }
MobileForm.FormDelegateSeparator {}
MobileForm.FormTextFieldDelegate { MobileForm.FormTextFieldDelegate {
id: accountLabel id: accountLabel
label: i18n("Label:") label: i18n("Label:")
text: root.connection ? Controller.activeAccountLabel : "" text: root.connection ? Controller.activeAccountLabel : ""
} }
MobileForm.FormDelegateSeparator {}
MobileForm.AbstractFormDelegate { MobileForm.AbstractFormDelegate {
Layout.fillWidth: true Layout.fillWidth: true
background: Item {} background: null
padding: Kirigami.Units.smallSpacing
contentItem: RowLayout { contentItem: RowLayout {
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
@@ -136,18 +142,21 @@ Kirigami.ScrollablePage {
visible: root.connection !== undefined && root.connection.canChangePassword === false visible: root.connection !== undefined && root.connection.canChangePassword === false
text: i18n("Your server doesn't support changing your password") text: i18n("Your server doesn't support changing your password")
} }
MobileForm.FormDelegateSeparator { visible: root.connection !== undefined && root.connection.canChangePassword === false }
MobileForm.FormTextFieldDelegate { MobileForm.FormTextFieldDelegate {
id: currentPassword id: currentPassword
label: i18n("Current Password:") label: i18n("Current Password:")
enabled: root.connection !== undefined && root.connection.canChangePassword !== false enabled: root.connection !== undefined && root.connection.canChangePassword !== false
echoMode: TextInput.Password echoMode: TextInput.Password
} }
MobileForm.FormDelegateSeparator {}
MobileForm.FormTextFieldDelegate { MobileForm.FormTextFieldDelegate {
id: newPassword id: newPassword
label: i18n("New Password:") label: i18n("New Password:")
enabled: root.connection !== undefined && root.connection.canChangePassword !== false enabled: root.connection !== undefined && root.connection.canChangePassword !== false
echoMode: TextInput.Password echoMode: TextInput.Password
} }
MobileForm.FormDelegateSeparator {}
MobileForm.FormTextFieldDelegate { MobileForm.FormTextFieldDelegate {
id: confirmPassword id: confirmPassword
label: i18n("Confirm new Password:") label: i18n("Confirm new Password:")
@@ -161,9 +170,10 @@ Kirigami.ScrollablePage {
confirmPassword.statusMessage = ''; confirmPassword.statusMessage = '';
} }
} }
MobileForm.FormDelegateSeparator {}
MobileForm.AbstractFormDelegate { MobileForm.AbstractFormDelegate {
Layout.fillWidth: true Layout.fillWidth: true
background: Item {} background: null
contentItem: RowLayout { contentItem: RowLayout {
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true

View File

@@ -8,6 +8,7 @@ import Qt.labs.platform 1.1
import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigami 2.19 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm 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 import org.kde.neochat 1.0
@@ -38,7 +39,7 @@ Kirigami.ScrollablePage {
}) })
contentItem: RowLayout { contentItem: RowLayout {
Kirigami.Avatar { KirigamiComponents.Avatar {
name: model.connection.localUser.displayName name: model.connection.localUser.displayName
source: model.connection.localUser.avatarMediaId ? ("image://mxc/" + model.connection.localUser.avatarMediaId) : "" source: model.connection.localUser.avatarMediaId ? ("image://mxc/" + model.connection.localUser.avatarMediaId) : ""

View File

@@ -8,6 +8,7 @@ import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm 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 import org.kde.neochat 1.0
@@ -42,7 +43,7 @@ Kirigami.ScrollablePage {
innerObject: [ innerObject: [
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Kirigami.Avatar { KirigamiComponents.Avatar {
color: "#4a5bcc" color: "#4a5bcc"
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
visible: Config.showAvatarInTimeline visible: Config.showAvatarInTimeline
@@ -79,7 +80,7 @@ Kirigami.ScrollablePage {
}, },
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Kirigami.Avatar { KirigamiComponents.Avatar {
color: "#9f244b" color: "#9f244b"
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
visible: Config.showAvatarInTimeline visible: Config.showAvatarInTimeline
@@ -132,7 +133,7 @@ Kirigami.ScrollablePage {
innerObject: [ innerObject: [
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Kirigami.Avatar { KirigamiComponents.Avatar {
color: "#4a5bcc" color: "#4a5bcc"
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
visible: Config.showAvatarInTimeline visible: Config.showAvatarInTimeline
@@ -159,7 +160,7 @@ Kirigami.ScrollablePage {
}, },
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
Kirigami.Avatar { KirigamiComponents.Avatar {
color: "#9f244b" color: "#9f244b"
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
visible: Config.showAvatarInTimeline visible: Config.showAvatarInTimeline