// SPDX-License-Identifier: LGPL-3.0-or-later import QtQuick 2.12 import QtQuick.Layouts 1.12 import "../../../.." import "../../../../Base" import "../../../../Base/Buttons" import "../../../../PythonBridge" HListView { id: root property string userId property string roomId property QtObject member // RoomMember model item property HStackView stackView property bool powerLevelFieldFocused: false property Future setPowerFuture: null function loadDevices() { py.callClientCoro(userId, "member_devices", [member.id], devices => { root.model.clear() for (const device of devices) root.model.append(device) }) } clip: true bottomMargin: theme.spacing model: ListModel {} delegate: MemberDeviceDelegate { width: root.width userId: root.userId deviceOwner: member.id deviceOwnerDisplayName: member.display_name stackView: root.stackView onTrustSet: trust => root.loadDevices() } section.property: "type" section.delegate: MemberDeviceSection { width: root.width } header: HColumnLayout { x: theme.spacing width: root.width - x * 2 spacing: theme.spacing * 1.5 HUserAvatar { userId: member.id displayName: member.display_name mxc: member.avatar_url Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.maximumWidth: 256 * theme.uiScale Layout.preferredHeight: width Layout.topMargin: theme.spacing HButton { x: -theme.spacing * 0.75 y: x z: 999 circle: true icon.name: "close-view" iconItem.small: true onClicked: root.stackView.pop() } } HColumnLayout { // no spacing between these children HLabel { wrapMode: HLabel.Wrap horizontalAlignment: Qt.AlignHCenter color: utils.nameColor(member.display_name || member.id) text: member.display_name.trim() || member.id Layout.fillWidth: true } HLabel { wrapMode: HLabel.Wrap horizontalAlignment: Qt.AlignHCenter color: theme.colors.dimText text: member.id visible: member.display_name.trim() !== "" Layout.fillWidth: true } } HColumnLayout { HLabel { wrapMode: HLabel.Wrap horizontalAlignment: Qt.AlignHCenter text: member.presence === "online" ? qsTr("Online") : member.presence === "unavailable" ? qsTr("Unavailable") : member.presence === "invisible" ? qsTr("Invisible") : qsTr("Offline / Unknown") color: member.presence === "online" ? theme.colors.positiveText : member.presence === "unavailable" ? theme.colors.warningText : theme.colors.halfDimText Layout.fillWidth: true } HLabel { wrapMode: HLabel.Wrap horizontalAlignment: Qt.AlignHCenter visible: ! member.currently_active && text !== "" color: theme.colors.dimText Timer { repeat: true triggeredOnStart: true running: ! member.currently_active && member.last_active_at > new Date(1) interval: new Date() - member.last_active_at < 60000 ? 1000 : 60000 onTriggered: parent.text = Qt.binding(() => qsTr("Last seen %1 ago").arg(utils.formatRelativeTime( new Date() - member.last_active_at, false, )) ) } Layout.fillWidth: true } } HLabel { wrapMode: HLabel.Wrap text: member.status_msg.trim() visible: text !== "" horizontalAlignment: lineCount > 1 ? Qt.AlignLeft : Qt.AlignHCenter color: theme.colors.halfDimText Layout.fillWidth: true } HLabeledItem { id: powerLevel label.text: qsTr("Power level:") label.horizontalAlignment: Qt.AlignHCenter Layout.preferredWidth: parent.width PowerLevelControl { width: parent.width defaultLevel: member.power_level rowSpacing: powerLevel.spacing onAccepted: applyButton.clicked() onFieldFocusedChanged: root.powerLevelFieldFocused = fieldFocused } } AutoDirectionLayout { visible: scale > 0 id: buttonsLayout scale: powerLevel.item.changed ? 1 : 0 rowSpacing: powerLevel.spacing Layout.preferredWidth: parent.width Layout.preferredHeight: implicitHeight * scale Layout.topMargin: -theme.spacing Behavior on scale { HNumberAnimation {} } HSpacer {} ApplyButton { id: applyButton loading: setPowerFuture !== null onClicked: { setPowerFuture = py.callClientCoro( userId, "room_set_member_power", [roomId, member.id, powerLevel.item.level], () => { setPowerFuture = null } ) } Layout.fillWidth: false Layout.alignment: Qt.AlignCenter } CancelButton { onClicked: { setPowerFuture.cancel() setPowerFuture = null powerLevel.item.reset() } Layout.fillWidth: false Layout.alignment: Qt.AlignCenter } HSpacer {} } Item { // This item is just to have some spacing at the bottom of header visible: root.count > 0 Layout.fillWidth: true } } Component.onCompleted: loadDevices() Component.onDestruction: if (setPowerFuture) setPowerFuture.cancel() Keys.onEnterPressed: Keys.onReturnPressed(event) Keys.onReturnPressed: if (! powerLevelFieldFocused && currentItem) { currentItem.leftClicked() currentItem.clicked() } Keys.onEscapePressed: stackView.pop() Connections { target: py.eventHandlers function onDeviceUpdateSignal(forAccount) { if (forAccount === root.userId) root.loadDevices() } } }