Page MenuHomePhorge

No OneTemporary

Size
37 KB
Referenced Files
None
Subscribers
None
diff --git a/src/contents/ui/RoomListViewItemDelegate.qml b/src/contents/ui/RoomListViewItemDelegate.qml
index 1c70715..feeee53 100644
--- a/src/contents/ui/RoomListViewItemDelegate.qml
+++ b/src/contents/ui/RoomListViewItemDelegate.qml
@@ -1,160 +1,158 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import moe.kazv.mxc.kazv 0.0 as MK
import 'matrix-helpers.js' as Helpers
import 'room-settings' as RoomSettings
import '.' as Kazv
Kirigami.SwipeListItem {
id: upper
property var item
property var iconSize: 1
property var isFavourite: item.tagIds.includes('m.favourite')
property var roomNameProvider: Kazv.RoomNameProvider {
room: upper.item
}
property var roomDisplayName: roomNameProvider.name
property var roomTimeline: item.timeline()
property var lastUnreadMessage: getLastUnreadMessage(roomTimeline, roomTimeline.count)
property var lastUnreadMessageReaders: lastUnreadMessage ? lastUnreadMessage.readers() : null
// The readers count is to make hasUnreadMessages prop reactive
// against our newly-posted receipts
property var hasUnreadMessages: getHasUnreadMessages(item, roomTimeline, roomTimeline.count, lastUnreadMessageReaders ? lastUnreadMessageReaders.count : 0)
onClicked: switchToRoomRequested(item.roomId)
checkable: true
checked: sdkVars.currentRoomId == item.roomId
autoExclusive: true
Kirigami.Theme.colorSet: !checked ? Kirigami.Theme.View : Kirigami.Theme.Selection
Kirigami.Theme.inherit: false
background: Rectangle {
anchors.fill: parent
color: hovered ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
}
contentItem: RowLayout {
Kazv.AvatarAdapter {
- sourceSize.width: iconSize
- sourceSize.height: iconSize
source: item.roomOrHeroAvatarMxcUri ? matrixSdk.mxcUriToHttp(item.roomOrHeroAvatarMxcUri) : ''
name: Helpers.roomAvatarPlaceholderName(item)
}
Label {
objectName: 'inviteIndicator'
visible: item.membership === MK.MatrixRoom.Invite
text: l10n.get('room-list-view-room-item-invited')
background: Rectangle {
color: Kirigami.Theme.activeBackgroundColor
}
color: Kirigami.Theme.activeTextColor
}
Label {
objectName: 'leaveIndicator'
visible: item.membership === MK.MatrixRoom.Leave
text: l10n.get('room-list-view-room-item-left')
color: Kirigami.Theme.disabledTextColor
}
Label {
objectName: 'roomDisplayNameLabel'
text: roomDisplayName
Layout.fillWidth: true
elide: Text.ElideRight
color: item.membership === MK.MatrixRoom.Leave ? Kirigami.Theme.disabledTextColor : Kirigami.Theme.textColor
}
Rectangle {
objectName: 'unreadNotificationCount'
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.preferredWidth: Math.max(unreadNotificationCountLabel.implicitWidth, Kirigami.Units.gridUnit)
Layout.preferredHeight: Kirigami.Units.gridUnit
radius: Kirigami.Units.gridUnit / 2
color: Kirigami.Theme.activeBackgroundColor
visible: !!item.unreadNotificationCount
RowLayout {
anchors.fill: parent
Label {
id: unreadNotificationCountLabel
Layout.alignment: Qt.AlignHCenter
color: Kirigami.Theme.activeTextColor
text: l10n.get('room-list-view-room-item-unread-notification-count', { count: item.unreadNotificationCount })
Accessible.ignored: true
}
}
Accessible.role: Accessible.Indicator
Accessible.name: l10n.get('room-list-view-room-item-unread-notification-count-text', { count: item.unreadNotificationCount })
}
Rectangle {
objectName: 'unreadIndicator'
Layout.alignment: Qt.AlignRight
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.preferredWidth: Kirigami.Units.iconSizes.small
Layout.preferredHeight: Kirigami.Units.iconSizes.small
radius: Kirigami.Units.iconSizes.small / 2
color: Kirigami.Theme.activeTextColor
visible: !item.unreadNotificationCount && hasUnreadMessages
Accessible.role: Accessible.Indicator
Accessible.name: l10n.get('room-list-view-room-item-unread-indicator')
}
}
actions: [
Kirigami.Action {
text: l10n.get("room-list-view-room-item-fav-action")
checkable: true
checked: isFavourite
icon.name: isFavourite ? 'starred-symbolic' : 'non-starred-symbolic'
onTriggered: toggleFavourite()
},
Kirigami.Action {
text: l10n.get('room-list-view-room-item-more-action')
icon.name: 'view-more-horizontal-symbolic'
onTriggered: activateRoomSettingsPage(item)
}
]
function toggleFavourite() {
favouriteToggler.toggleTag('m.favourite');
}
property var favouriteToggler: RoomSettings.RoomTagHandler {
room: item
}
function getHasUnreadMessages(room, timeline, timelineCount, readersCount) {
return !!room.unreadNotificationCount || !!getLastUnreadMessage(timeline, timelineCount);
}
function getLastUnreadMessage(timeline, timelineCount) {
for (let i = 0; i < timelineCount; ++i) {
const event = timeline.at(i);
if (event.isLocalEcho) {
// Skip local echoes
} else if (event.sender === matrixSdk.userId) {
// Own message here
return undefined;
} else if (Helpers.isEventReadBy(event, matrixSdk.userId)) {
// This message is read
return undefined;
} else {
// The latest message is not read and not sent by the current user
return event;
}
}
}
}
diff --git a/src/contents/ui/RoomMemberListViewItemDelegate.qml b/src/contents/ui/RoomMemberListViewItemDelegate.qml
index 65feaf1..1227548 100644
--- a/src/contents/ui/RoomMemberListViewItemDelegate.qml
+++ b/src/contents/ui/RoomMemberListViewItemDelegate.qml
@@ -1,52 +1,50 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
Kirigami.SwipeListItem {
id: roomMemberListViewItemDelegate
property var member
property var nameProvider: Kazv.UserNameProvider {
user: member
}
property var displayName: nameProvider.name
property var iconSize
contentItem: RowLayout {
Kazv.AvatarAdapter {
- sourceSize.width: iconSize
- sourceSize.height: iconSize
source: member.avatarMxcUri ? matrixSdk.mxcUriToHttp(member.avatarMxcUri) : ''
name: displayName
Layout.preferredWidth: iconSize
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft
Label {
text: displayName
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
}
Label {
text: member.userId
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
}
}
}
onClicked: {
activateUserPage(member, room);
}
}
diff --git a/src/contents/ui/UserPage.qml b/src/contents/ui/UserPage.qml
index 1718d3a..6508187 100644
--- a/src/contents/ui/UserPage.qml
+++ b/src/contents/ui/UserPage.qml
@@ -1,364 +1,362 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import moe.kazv.mxc.kazv as MK
import '.' as Kazv
import 'device-mgmt' as KazvDM
import 'matrix-helpers.js' as Helpers
Kazv.ClosableScrollablePage {
id: userPage
property string userId: ''
property var user: ({})
property var nameProvider: Kazv.UserNameProvider {
user: userPage.user
}
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: userPage.room
}
property var roomName: roomNameProvider.name
property var editingPowerLevel: false
property var submittingPowerLevel: false
property var powerLevelsLoaded: false
property var userPowerLevel: room.userPowerLevel(userId)
property var kickingUser: false
property var canKickUser: !(user.membership === 'ban' || user.membership === 'leave')
property var banningUser: false
property var unbanningUser: false
Connections {
target: room
function onPowerLevelsChanged() {
userPage.userPowerLevel = room.userPowerLevel(userPage.userId);
}
}
title: nameProvider.name
property var ensureMemberEvent: Kazv.AsyncHandler {
trigger: () => room.ensureStateEvent('m.room.member', userId)
}
property var ensurePowerLevels: Kazv.AsyncHandler {
trigger: () => room.ensureStateEvent('m.room.power_levels', '')
onResolved: (success, data) => {
if (success) {
userPage.powerLevelsLoaded = true;
}
}
}
property var updatingNameOverride: false
property var updateNameOverride: Kazv.AsyncHandler {
trigger: () => {
userPage.updatingNameOverride = true;
return sdkVars.userGivenNicknameMap.setAndUpload(
userPage.userId, nameOverrideInput.text || null);
}
onResolved: (success, data) => {
userPage.updatingNameOverride = false;
if (!success) {
showPassiveNotification(l10n.get('user-page-update-name-override-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
Component.onCompleted: {
userPage.ensureMemberEvent.call();
userPage.ensurePowerLevels.call();
}
property var setPowerLevel: Kazv.AsyncHandler {
trigger: () => {
userPage.submittingPowerLevel = true;
return room.setUserPowerLevel(userPage.userId, parseInt(newPowerLevel.text));
}
onResolved: (success, data) => {
if (!success) {
showPassiveNotification(l10n.get('user-page-set-power-level-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
userPage.editingPowerLevel = false;
}
userPage.submittingPowerLevel = false;
}
}
property var kickUser: Kazv.AsyncHandler {
trigger: () => {
userPage.kickingUser = true;
return room.kickUser(userPage.userId, kickUserReasonInput.text);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-kick-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
kickUserReasonInput.text = '';
}
userPage.kickingUser = false;
}
}
property var banUser: Kazv.AsyncHandler {
trigger: () => {
userPage.banningUser = true;
return room.banUser(userPage.userId, banUserReasonInput.text);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-ban-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
banUserReasonInput.text = '';
}
userPage.banningUser = false;
}
}
property var unbanUser: Kazv.AsyncHandler {
trigger: () => {
userPage.unbanningUser = true;
return room.unbanUser(userPage.userId);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-unban-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
userPage.unbanningUser = false;
}
}
ColumnLayout {
Kazv.AvatarAdapter {
id: avatar
objectName: 'avatar'
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Kirigami.Units.iconSizes.enormous
Layout.preferredWidth: Kirigami.Units.iconSizes.enormous
source: userPage.user.avatarMxcUri ? matrixSdk.mxcUriToHttp(userPage.user.avatarMxcUri) : ''
- sourceSize.width: Kirigami.Units.iconSizes.enormous
- sourceSize.height: Kirigami.Units.iconSizes.enormous
name: nameProvider.name
}
ColumnLayout {
Layout.preferredWidth: this.parent.width
Label {
objectName: 'userNameLabel'
Layout.alignment: Qt.AlignHCenter
font.pixelSize: Kirigami.Units.gridUnit
text: !!userPage.user.name ? userPage.user.name : userPage.userId
}
Label {
objectName: 'userIdLabel'
Layout.alignment: Qt.AlignHCenter
font.pixelSize: Kirigami.Units.gridUnit * 0.8
visible: !!userPage.user.name
text: userPage.userId
}
}
RowLayout {
// Do not allow user to set a name override for themselves
visible: userPage.userId !== matrixSdk.userId
TextField {
id: nameOverrideInput
objectName: 'nameOverrideInput'
placeholderText: l10n.get('user-page-overrided-name-placeholder')
Layout.fillWidth: true
enabled: !userPage.updatingNameOverride
text: nameProvider.overridedName
}
Button {
objectName: 'saveNameOverrideButton'
text: l10n.get('user-page-save-name-override-action')
enabled: !userPage.updatingNameOverride
onClicked: updateNameOverride.call()
}
}
RowLayout {
visible: !userPage.editingPowerLevel
Label {
objectName: 'powerLevelLabel'
Layout.fillWidth: true
text: l10n.get('user-page-power-level', { powerLevel: userPage.userPowerLevel })
}
Button {
objectName: 'editPowerLevelButton'
text: l10n.get('user-page-edit-power-level-action')
enabled: userPage.powerLevelsLoaded
onClicked: {
userPage.editingPowerLevel = true;
}
}
}
RowLayout {
visible: userPage.editingPowerLevel
TextField {
objectName: 'newPowerLevelInput'
id: newPowerLevel
Layout.fillWidth: true
text: `${userPage.userPowerLevel}`
readOnly: userPage.submittingPowerLevel
}
Button {
objectName: 'savePowerLevelButton'
text: l10n.get('user-page-save-power-level-action')
onClicked: {
setPowerLevel.call();
}
enabled: !userPage.submittingPowerLevel
}
Button {
objectName: 'discardPowerLevelButton'
text: l10n.get('user-page-discard-power-level-action')
enabled: !userPage.submittingPowerLevel
onClicked: {
userPage.editingPowerLevel = false;
newPowerLevel.text = `${userPage.userPowerLevel}`;
}
}
}
ColumnLayout {
Kirigami.PromptDialog {
id: kickUserReasonDialog
objectName: 'kickUserReasonDialog'
title: l10n.get('user-page-kick-user-confirm-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
userPage.kickUser.call()
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-kick-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: nameProvider.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-kick-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: userPage.user.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
Kirigami.FormLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: kickUserReasonInput
objectName: 'kickUserReasonInput'
readOnly: userPage.kickingUser
Kirigami.FormData.label: l10n.get('user-page-kick-user-reason-prompt')
}
}
}
}
}
Button {
objectName: 'kickUserButton'
icon.name: 'im-kick-user'
Layout.fillWidth: true
enabled: !userPage.kickingUser
text: l10n.get('user-page-kick-user-action')
visible: userPage.canKickUser
onClicked: {
kickUserReasonDialog.open()
}
}
}
RowLayout {
Kirigami.PromptDialog {
id: banUserReasonDialog
objectName: 'banUserReasonDialog'
title: l10n.get('user-page-ban-user-confirm-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
userPage.banUser.call()
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-ban-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: nameProvider.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
Kirigami.FormLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: banUserReasonInput
objectName: 'banUserReasonInput'
readOnly: userPage.banningUser
Kirigami.FormData.label: l10n.get('user-page-ban-user-reason-prompt')
}
}
}
}
Button {
objectName: 'banUserButton'
Layout.fillWidth: true
icon.name: 'im-ban-kick-user'
enabled: !userPage.banningUser
text: l10n.get('user-page-ban-user-action')
visible: !unbanUserButton.visible
onClicked: {
banUserReasonDialog.open()
}
}
Button {
id: unbanUserButton
objectName: 'unbanUserButton'
Layout.fillWidth: true
icon.name: 'im-user-online'
enabled: !userPage.unbanningUser
text: l10n.get('user-page-unban-user-action')
visible: user.membership === "ban"
onClicked: {
userPage.unbanUser.call()
}
}
}
KazvDM.DeviceList {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height
userId: userPage.userId
devices: matrixSdk.devicesOfUser(userId)
}
}
}
diff --git a/src/contents/ui/event-types/Simple.qml b/src/contents/ui/event-types/Simple.qml
index c05d9e9..1e81c28 100644
--- a/src/contents/ui/event-types/Simple.qml
+++ b/src/contents/ui/event-types/Simple.qml
@@ -1,131 +1,127 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import '..' as Kazv
ColumnLayout {
objectName: 'eventViewMainItem'
property var event
property var sender
default property alias children: container.data
property var isSelected
/// The item shown after the username, in compact mode
property var summaryItem: Item {}
property var nameProvider: Kazv.UserNameProvider {
user: sender
}
property var senderNickname: nameProvider.name
property var contentMaxWidth: {
(parent.width
// avatar size and margins
- iconSize
- 2 * Kirigami.Units.largeSpacing
- 2 * Kirigami.Units.largeSpacing
)
}
property var shouldCollapseSender: (
!compactMode
&& prevEventType
&& prevEventType !== 'ignore'
&& (
event.sender === prevEvent.sender
// local echo does not have a sender, will use the current user
|| (!!event.isLocalEcho && !!prevEvent.isLocalEcho)
|| (!!event.isLocalEcho && prevEvent.sender === matrixSdk.userId)
)
)
id: layout
RowLayout {
// width: parent.width
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.topMargin: shouldCollapseSender ? 0 : Kirigami.Units.largeSpacing
Layout.bottomMargin: 0
Kazv.AvatarAdapter {
id: avatar
objectName: 'senderAvatar'
Layout.alignment: Qt.AlignTop
- sourceSize.width: iconSize
- sourceSize.height: iconSize
source: sender.avatarMxcUri ? matrixSdk.mxcUriToHttp(sender.avatarMxcUri) : ''
name: senderNickname
visible: !compactMode && !shouldCollapseSender
TapHandler {
onTapped: {
activateUserPage(sender, room, event.sender);
}
}
}
Item {
objectName: 'senderCollapsedPlaceholder'
visible: shouldCollapseSender
Layout.preferredWidth: iconSize
Layout.preferredHeight: 1
}
ColumnLayout {
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
RowLayout {
visible: !shouldCollapseSender
Kazv.AvatarAdapter {
id: avatarCompact
Layout.preferredWidth: Kirigami.Units.iconSizes.sizeForLabels
Layout.preferredHeight: Kirigami.Units.iconSizes.sizeForLabels
- sourceSize.width: Kirigami.Units.iconSizes.sizeForLabels
- sourceSize.height: Kirigami.Units.iconSizes.sizeForLabels
source: sender.avatarMxcUri ? matrixSdk.mxcUriToHttp(sender.avatarMxcUri) : ''
name: senderNickname
visible: compactMode
}
Label {
id: userNicknameText
objectName: 'userNicknameText'
text: senderNickname
Layout.fillWidth: !compactMode
property var reasonableWidth: Math.max(contentWidth, Kirigami.Units.gridUnit)
TapHandler {
enabled: !compactMode
onTapped: {
if (point.position.x <= userNicknameText.reasonableWidth) {
mentionUserRequested(sender.userId);
}
}
}
}
RowLayout {
objectName: 'compactModeSummary'
visible: compactMode
data: [summaryItem]
}
}
RowLayout {
id: container
Layout.fillWidth: true
}
}
}
}
diff --git a/src/contents/ui/room-settings/RoomSettingsPage.qml b/src/contents/ui/room-settings/RoomSettingsPage.qml
index b798902..fc3fb75 100644
--- a/src/contents/ui/room-settings/RoomSettingsPage.qml
+++ b/src/contents/ui/room-settings/RoomSettingsPage.qml
@@ -1,362 +1,360 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.20 as Kirigami
import moe.kazv.mxc.kazv 0.0 as MK
import '../matrix-helpers.js' as Helpers
import '..' as Kazv
import '.' as RoomSettings
Kazv.ClosableScrollablePage {
id: roomSettingsPage
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomSettingsPage.room
}
property var roomDisplayName: roomNameProvider.name
property var customTagIds: room.tagIds.filter(k => k.startsWith('u.'))
property var editingTopic: false
property var submittingTopic: false
property var submitTopic: Kazv.AsyncHandler {
trigger: () => {
roomSettingsPage.submittingTopic = true;
return roomSettingsPage.room.setTopic(roomTopicEdit.text);
}
onResolved: (success, data) => {
roomSettingsPage.submittingTopic = false;
if (success) {
roomSettingsPage.editingTopic = false;
} else {
showPassiveNotification(l10n.get('room-settings-set-topic-failed-prompt', {
room: room.roomId,
errorCode: data.errorCode,
errorMsg: data.error,
}));
}
}
}
title: l10n.get('room-settings-page-title', { room: roomDisplayName })
function tagIdToName(tagId) {
return tagId.slice(2);
}
property var encryptionPopup: Kirigami.PromptDialog {
parent: roomSettingsPage.overlay
objectName: 'encryptionPopup'
title: l10n.get('room-settings-enable-encryption-prompt-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('room-settings-enable-encryption-prompt-dialog-prompt')
wrapMode: Text.Wrap
}
}
onAccepted: enableEncryption.call()
}
property var enablingEncryption: false
property var enableEncryption: Kazv.AsyncHandler {
trigger: () => {
roomSettingsPage.enablingEncryption = true;
return room.sendStateEvent({
type: 'm.room.encryption',
state_key: '',
content: {
algorithm: 'm.megolm.v1.aes-sha2',
},
});
}
onResolved: (success, data) => {
roomSettingsPage.enablingEncryption = false;
if (success) {
showPassiveNotification(l10n.get('room-settings-encryption-enabled-notification'));
} else {
showPassiveNotification(l10n.get('room-settings-encryption-failed-to-enable-notification', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
property var tagHandler: RoomSettings.RoomTagHandler {
room: roomSettingsPage.room
}
property var members: room.members()
property var avatarCount: 4
ColumnLayout {
RowLayout {
Layout.alignment: Qt.AlignHCenter
Repeater {
objectName: 'roomMembersAvatarsRepeater'
model: Math.min(members.count, roomSettingsPage.avatarCount)
Kazv.AvatarAdapter {
property var member: members.at(index)
property var nameProvider: Kazv.UserNameProvider {
user: member
}
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
source: member.avatarMxcUri ?
matrixSdk.mxcUriToHttp(member.avatarMxcUri) : ''
- sourceSize.width: Kirigami.Units.iconSizes.huge
- sourceSize.height: Kirigami.Units.iconSizes.huge
name: nameProvider.name
}
}
Kirigami.Icon {
objectName: 'roomMembersAvatarsMore'
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
source: 'go-next-skip'
visible: members.count > roomSettingsPage.avatarCount
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Label {
objectName: 'roomNameLabel'
Layout.alignment: Qt.AlignHCenter
font.pixelSize: Kirigami.Units.gridUnit
text: !!room.name ? room.name : room.roomId
}
Label {
objectName: 'roomIdLabel'
Layout.alignment: Qt.AlignHCenter
font.pixelSize: Math.ceil(Kirigami.Units.gridUnit * 0.8)
text: room.roomId
visible: !!room.name
}
}
RowLayout {
visible: !roomSettingsPage.editingTopic
Kazv.SelectableText {
objectName: 'roomTopicLabel'
text: room.topic || l10n.get('room-settings-topic-missing')
font.italic: !room.topic
wrapMode: Text.Wrap
Kirigami.Theme.colorGroup: !!room.topic ? Kirigami.Theme.Normal : Kirigami.Theme.Inactive
Layout.fillWidth: true
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'editTopicButton'
text: l10n.get('room-settings-edit-topic-action')
onClicked: {
roomTopicEdit.text = room.topic;
roomSettingsPage.editingTopic = true;
}
}
}
RowLayout {
visible: roomSettingsPage.editingTopic
TextArea {
id: roomTopicEdit
objectName: 'roomTopicEdit'
Layout.fillWidth: true
wrapMode: Text.Wrap
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'saveTopicButton'
enabled: !roomSettingsPage.submittingTopic
text: l10n.get('room-settings-save-topic-action')
onClicked: roomSettingsPage.submitTopic.call()
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'discardTopicButton'
enabled: !roomSettingsPage.submittingTopic
text: l10n.get('room-settings-discard-topic-action')
onClicked: roomSettingsPage.editingTopic = false
}
}
Button {
text: l10n.get('room-settings-members-action')
icon.name: 'im-user'
Layout.fillWidth: true
onClicked: pageStack.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.members() })
}
Button {
text: l10n.get('room-settings-banned-members-action')
icon.name: 'im-kick-user'
icon.color: Kirigami.Theme.negativeTextColor
Layout.fillWidth: true
onClicked: pageStack.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.bannedMembers() })
}
Label {
objectName: 'encryptionIndicator'
Layout.fillWidth: true
text: !!room.encrypted ? l10n.get('room-settings-encrypted') : l10n.get('room-settings-not-encrypted')
}
Button {
objectName: 'enableEncryptionButton'
Layout.fillWidth: true
visible: !room.encrypted
enabled: !roomSettingsPage.enablingEncryption
text: l10n.get('room-settings-enable-encryption-action')
onClicked: encryptionPopup.open()
}
RowLayout {
Layout.fillWidth: true
Label {
text: l10n.get('room-settings-tags')
Layout.fillWidth: true
}
CheckBox {
Layout.alignment: Qt.AlignRight
text: l10n.get('room-settings-favourited')
checkable: true
checked: tagHandler.hasTag('m.favourite')
enabled: tagHandler.available
onToggled: tagHandler.toggleTag('m.favourite')
}
}
ListView {
model: customTagIds.length
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height
delegate: Kirigami.SwipeListItem {
required property var index
contentItem: RowLayout {
Label {
Layout.fillWidth: true
text: tagIdToName(customTagIds[index])
}
}
actions: [
Kirigami.Action {
enabled: tagHandler.available
icon.name: 'list-remove-symbolic'
text: l10n.get('room-settings-remove-tag')
onTriggered: tagHandler.toggleTag(customTagIds[index])
}
]
}
}
RowLayout {
TextField {
id: newTagName
enabled: tagHandler.available
text: ''
Layout.fillWidth: true
}
Button {
enabled: tagHandler.available
text: l10n.get('room-settings-add-tag')
icon.name: 'list-add'
onClicked: {
tagHandler.toggleTag('u.' + newTagName.text)
}
}
Connections {
target: tagHandler
function onTagAdded(tagId) {
if (tagId === 'u.' + newTagName.text) {
newTagName.text = '';
}
}
}
}
Button {
text: l10n.get('room-invite-action')
icon.name: 'list-add-user'
Layout.fillWidth: true
onClicked: {
activateRoomInvitePage(roomSettingsPage.room);
}
}
Button {
objectName: 'leaveRoomButton'
text: l10n.get('room-leave-action')
icon.name: 'im-ban-kick-user'
icon.color: Kirigami.Theme.negativeTextColor
Layout.fillWidth: true
onClicked: {
confirmLeaveOverlay.open();
}
}
Button {
objectName: 'forgetRoomButton'
text: l10n.get('room-forget-action')
Layout.fillWidth: true
visible: room.membership === MK.MatrixRoom.Leave
onClicked: {
confirmForgetOverlay.open();
}
}
}
property var confirmLeaveOverlay: Kazv.ConfirmationOverlay {
objectName: 'confirmLeaveRoomPopup'
parent: roomSettingsPage.overlay
title: l10n.get('room-leave-confirm-popup-title')
message: l10n.get('room-leave-confirm-popup-message')
confirmActionText: l10n.get('room-leave-confirm-popup-confirm-action')
cancelActionText: l10n.get('room-leave-confirm-popup-cancel-action')
onAccepted: leaveRoomHandler.call()
}
property var leaveRoomHandler: Kazv.AsyncHandler {
trigger: () => room.leaveRoom()
onResolved: {
if (success) {
showPassiveNotification(l10n.get('leave-room-success-prompt', { room: room.roomId }));
inviteOverlay.close();
} else {
showPassiveNotification(l10n.get('leave-room-failed-prompt', { room: room.roomId, errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
property var confirmForgetOverlay: Kazv.ConfirmationOverlay {
objectName: 'confirmForgetRoomPopup'
parent: roomSettingsPage.overlay
title: l10n.get('room-forget-confirm-popup-title')
message: l10n.get('room-forget-confirm-popup-message')
confirmActionText: l10n.get('room-forget-confirm-popup-confirm-action')
cancelActionText: l10n.get('room-forget-confirm-popup-cancel-action')
onAccepted: forgetRoomHandler.call()
}
property var forgetRoomHandler: Kazv.AsyncHandler {
trigger: () => room.forgetRoom()
onResolved: (success, data) => {
if (success) {
showPassiveNotification(l10n.get('forget-room-success-prompt', { room: room.roomId }));
} else {
showPassiveNotification(l10n.get('forget-room-failed-prompt', { room: room.roomId, errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
}
diff --git a/src/contents/ui/settings/ProfileSettings.qml b/src/contents/ui/settings/ProfileSettings.qml
index 6d2a9cd..3c55ef1 100644
--- a/src/contents/ui/settings/ProfileSettings.qml
+++ b/src/contents/ui/settings/ProfileSettings.qml
@@ -1,112 +1,110 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import '..' as Kazv
ColumnLayout {
id: profileSettings
property var avatarUrl: ''
property var displayName: ''
property var getSelfProfilePromise: undefined
property var loaded: false
Kazv.AvatarAdapter {
id: avatar
objectName: 'avatar'
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Kirigami.Units.iconSizes.enormous
Layout.preferredWidth: Kirigami.Units.iconSizes.enormous
source: profileSettings.avatarUrl ? matrixSdk.mxcUriToHttp(profileSettings.avatarUrl) : ''
- sourceSize.width: Kirigami.Units.iconSizes.enormous
- sourceSize.height: Kirigami.Units.iconSizes.enormous
}
property var saveAvatarUrl: Kazv.AsyncHandler {
trigger: () => {
profileSettings.loaded = false;
return matrixSdk.setAvatarUrl(profileSettings.avatarUrl);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('settings-profile-save-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
profileSettings.loaded = true;
}
}
property var uploadFileHelper: Kazv.UploadFileHelper {
onUploaded: {
profileSettings.avatarUrl = mxcUri;
saveAvatarUrl.call();
}
onFailed: showPassiveNotification(l10n.get('kazv-io-upload-failure-prompt'))
}
Button {
Layout.fillWidth: true
text: l10n.get('settings-profile-change-avatar')
enabled: profileSettings.loaded
onClicked: profileSettings.uploadFileHelper.chooseFileAndUpload()
}
RowLayout {
Layout.fillWidth: true
Label {
text: l10n.get('settings-profile-display-name')
}
TextField {
Layout.fillWidth: true
id: displayNameEntry
objectName: 'displayNameEntry'
text: profileSettings.displayName
enabled: profileSettings.loaded
}
}
property var getSelfPromise: Kazv.AsyncHandler {
trigger: () => matrixSdk.getSelfProfile()
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('settings-profile-load-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
profileSettings.displayName = data.displayName;
profileSettings.avatarUrl = data.avatarUrl;
profileSettings.loaded = true;
}
}
}
Component.onCompleted: {
getSelfPromise.call();
}
property var saveDisplayName: Kazv.AsyncHandler {
trigger: () => {
profileSettings.loaded = false;
return matrixSdk.setDisplayName(displayNameEntry.text);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('settings-profile-save-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
profileSettings.loaded = true;
}
}
function save() {
if (displayNameEntry.text !== profileSettings.displayName) {
saveDisplayName.call();
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 7:59 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55426
Default Alt Text
(37 KB)

Event Timeline