Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85805512
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
23 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/contents/ui/CreateRoomPage.qml b/src/contents/ui/CreateRoomPage.qml
index 25caf7a..b06b5df 100644
--- a/src/contents/ui/CreateRoomPage.qml
+++ b/src/contents/ui/CreateRoomPage.qml
@@ -1,172 +1,175 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
import moe.kazv.mxc.kazv 0.0 as MK
Kazv.ClosableScrollablePage {
id: createRoomPage
title: l10n.get('create-room-page-title')
property var creatingRoom: false
property var inviteUserIds: []
ButtonGroup {
id: roomTypeButtons
}
Kirigami.FormLayout {
anchors.fill: parent
ColumnLayout {
Kirigami.FormData.label: l10n.get('create-room-page-type-prompt')
RadioButton {
id: typePublic
objectName: 'typePublicRadio'
checked: true
text: l10n.get('create-room-page-type-public')
ButtonGroup.group: roomTypeButtons
}
RadioButton {
id: typePrivate
objectName: 'typePrivateRadio'
text: l10n.get('create-room-page-type-private')
ButtonGroup.group: roomTypeButtons
}
RadioButton {
id: typeDirect
objectName: 'typeDirectRadio'
text: l10n.get('create-room-page-type-direct')
ButtonGroup.group: roomTypeButtons
}
}
TextField {
id: roomName
objectName: 'roomNameInput'
Kirigami.FormData.label: l10n.get('create-room-page-name-prompt')
placeholderText: l10n.get('create-room-page-name-placeholder')
Layout.fillWidth: true
}
TextField {
id: roomAlias
objectName: 'roomAliasInput'
Kirigami.FormData.label: l10n.get('create-room-page-alias-prompt')
placeholderText: l10n.get('create-room-page-alias-placeholder')
Layout.fillWidth: true
}
TextField {
id: roomTopic
objectName: 'roomTopicInput'
Kirigami.FormData.label: l10n.get('create-room-page-topic-prompt')
placeholderText: l10n.get('create-room-page-topic-placeholder')
Layout.fillWidth: true
}
CheckBox {
id: allowFederate
checked: true
text: l10n.get('create-room-page-allow-federate-prompt')
Layout.fillWidth: true
}
Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: l10n.get('create-room-invite-userids-prompt')
}
ColumnLayout {
Repeater {
model: createRoomPage.inviteUserIds.length
delegate: Kirigami.SwipeListItem {
objectName: 'inviteUserItem_' + index
Layout.fillWidth: true
Layout.minimumWidth: Kirigami.Units.gridUnit * 10
- Label {
- objectName: 'inviteUserIdLabel'
- text: createRoomPage.inviteUserIds[index]
+ contentItem: RowLayout {
+ Label {
+ Layout.fillWidth: true
+ objectName: 'inviteUserIdLabel'
+ text: createRoomPage.inviteUserIds[index]
+ }
}
actions: [
Kirigami.Action {
objectName: 'removeInviteAction'
icon.name: 'list-remove-symbolic'
text: l10n.get('create-room-page-action-remove-invite')
onTriggered: {
createRoomPage.inviteUserIds.splice(index, 1);
// trigger reactivity
createRoomPage.inviteUserIds = createRoomPage.inviteUserIds;
}
}
]
}
}
}
TextField {
id: newInviteUserId
Kirigami.FormData.label: l10n.get('create-room-page-add-invite-prompt')
placeholderText: l10n.get('create-room-page-add-invite-placeholder')
objectName: 'newInviteUserInput'
text: ''
Layout.fillWidth: true
}
Button {
objectName: 'addInviteUserButton'
text: l10n.get('create-room-page-action-add-invite')
Layout.fillWidth: true
onClicked: {
createRoomPage.inviteUserIds.push(newInviteUserId.text);
// trigger reactivity
createRoomPage.inviteUserIds = createRoomPage.inviteUserIds;
newInviteUserId.text = '';
}
}
Button {
Layout.fillWidth: true
objectName: 'createRoomButton'
text: l10n.get('create-room-page-action-create-room')
onClicked: createRoomPage.createRoom.call()
}
}
property var createRoom: Kazv.AsyncHandler {
trigger: () => matrixSdk.createRoom(
/* isPrivate = */ typePrivate.checked || typeDirect.checked,
roomName.text,
roomAlias.text,
createRoomPage.inviteUserIds,
/* isDirect = */ typeDirect.checked && createRoomPage.inviteUserIds.length === 1,
/* allowFederate = */ allowFederate.checked,
roomTopic.text,
/* powerLevelContentOverride = */ {},
/* preset = */ typeDirect.checked
? MK.MatrixSdk.TrustedPrivateChat
: typePrivate.checked
? MK.MatrixSdk.PrivateChat
: MK.MatrixSdk.PublicChat
)
onResolved: {
if (success) {
showPassiveNotification(l10n.get('create-room-page-success-prompt'));
pageStack.removePage(createRoomPage);
} else {
showPassiveNotification(l10n.get('create-room-page-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
}
diff --git a/src/contents/ui/RoomListViewItemDelegate.qml b/src/contents/ui/RoomListViewItemDelegate.qml
index 95bcc1b..40a0751 100644
--- a/src/contents/ui/RoomListViewItemDelegate.qml
+++ b/src/contents/ui/RoomListViewItemDelegate.qml
@@ -1,134 +1,135 @@
/*
* 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(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
}
- RowLayout {
+ 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 {
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: 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(timeline, timelineCount, readersCount) {
return !!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 21ae15e..65feaf1 100644
--- a/src/contents/ui/RoomMemberListViewItemDelegate.qml
+++ b/src/contents/ui/RoomMemberListViewItemDelegate.qml
@@ -1,52 +1,52 @@
/*
* 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
- RowLayout {
+ 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/device-mgmt/Device.qml b/src/contents/ui/device-mgmt/Device.qml
index 9f14b3a..480d980 100644
--- a/src/contents/ui/device-mgmt/Device.qml
+++ b/src/contents/ui/device-mgmt/Device.qml
@@ -1,157 +1,157 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 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
Kirigami.SwipeListItem {
id: device
property var item
property var userId
- RowLayout {
+ contentItem: RowLayout {
ColumnLayout {
Label {
objectName: 'deviceIdLabel'
text: item.deviceId
}
Label {
objectName: 'displayNameLabel'
text: item.displayName
font.pixelSize: Kirigami.Units.gridUnit * 0.5
visible: !!item.displayName
}
Layout.fillWidth: true
}
RowLayout {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: Kirigami.Units.largeSpacing
Kirigami.Icon {
source: device.getTrustLevelIcon(item.trustLevel)
Layout.preferredHeight: Kirigami.Units.iconSizes.sizeForLabels
Layout.preferredWidth: Kirigami.Units.iconSizes.sizeForLabels
Accessible.ignored: true
}
Label {
objectName: 'trustLevelLabel'
text: l10n.get(`device-trust-level-${item.trustLevel}`)
}
}
}
property var sheet: Kirigami.OverlaySheet {
id: popup
title: l10n.get('device-set-trust-level-dialog-title')
parent: applicationWindow().overlay
property var setTrustLevelPromise: null
property var conn: Connections {
target: popup.setTrustLevelPromise
function onResolved(success, data) {
if (!success) {
console.log('Error setting trust level:', JSON.stringify(data));
}
popup.setTrustLevelPromise = null;
popup.close();
}
}
ColumnLayout {
Label {
text: l10n.get('device-set-trust-level-dialog-name-label', { name: item.displayName })
}
Label {
text: l10n.get('device-set-trust-level-dialog-id-label', { id: item.deviceId })
}
Label {
text: l10n.get('device-set-trust-level-dialog-ed25519-key-label', { key: item.ed25519Key })
}
Label {
text: l10n.get('device-set-trust-level-dialog-curve25519-key-label', { key: item.curve25519Key })
}
ButtonGroup {
buttons: trustLevelChoices.children
}
ColumnLayout {
id: trustLevelChoices
objectName: 'trustLevelChoices'
Layout.fillHeight: true
Repeater {
model: ['blocked', 'unseen', 'seen', 'verified']
delegate: RadioButton {
objectName: 'trustLevelChoice_' + modelData
property var level: modelData
autoExclusive: true
checked: item.trustLevel === modelData
text: l10n.get(`device-trust-level-${modelData}`)
icon.name: device.getTrustLevelIcon(modelData)
}
}
}
RowLayout {
Button {
text: l10n.get('device-set-trust-level-dialog-save')
onClicked: {
const current = popup.getNewTrustLevel();
popup.setTrustLevelPromise = matrixSdk.setDeviceTrustLevel(userId, item.deviceId, current);
}
}
Button {
text: l10n.get('device-set-trust-level-dialog-cancel')
onClicked: {
popup.close();
}
}
}
}
function getNewTrustLevel() {
for (let i = 0; i < trustLevelChoices.children.length; ++i) {
const curItem = trustLevelChoices.children[i];
if (curItem.checked) {
return curItem.level;
}
}
return 'unknown';
}
}
actions: [
Kirigami.Action {
text: l10n.get('device-set-trust-level')
icon.name: 'settings-configure'
onTriggered: {
popup.open();
}
}
]
function getTrustLevelIcon(level)
{
switch (level) {
case 'blocked':
return 'emblem-error';
case 'unseen':
return 'emblem-warning';
case 'seen':
return 'emblem-added';
case 'verified':
return 'emblem-checked';
default:
return 'emblem-question';
}
}
}
diff --git a/src/contents/ui/room-settings/RoomSettingsPage.qml b/src/contents/ui/room-settings/RoomSettingsPage.qml
index 59940c8..8bf150c 100644
--- a/src/contents/ui/room-settings/RoomSettingsPage.qml
+++ b/src/contents/ui/room-settings/RoomSettingsPage.qml
@@ -1,239 +1,242 @@
/*
* 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.'))
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
}
ColumnLayout {
Button {
text: l10n.get('room-settings-members-action')
Layout.fillWidth: true
onClicked: pageStack.push(Qt.resolvedUrl('qrc:/room-settings/RoomMemberListPage.qml'), { room: room, members: room.members() })
}
Button {
text: l10n.get('room-settings-banned-members-action')
Layout.fillWidth: true
onClicked: pageStack.push(Qt.resolvedUrl('qrc:/room-settings/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()
}
Label {
text: l10n.get('room-settings-tags')
Layout.fillWidth: true
}
CheckBox {
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
- Label {
- text: tagIdToName(customTagIds[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')
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')
Layout.fillWidth: true
onClicked: {
activateRoomInvitePage(roomSettingsPage.room);
}
}
Button {
objectName: 'leaveRoomButton'
text: l10n.get('room-leave-action')
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 }));
}
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Oct 11, 1:22 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1785813
Default Alt Text
(23 KB)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline
Log In to Comment