Page MenuHomePhorge

No OneTemporary

Size
59 KB
Referenced Files
None
Subscribers
None
diff --git a/src/contents/ui/UserNameProvider.qml b/src/contents/ui/UserNameProvider.qml
index e9283ac..7142263 100644
--- a/src/contents/ui/UserNameProvider.qml
+++ b/src/contents/ui/UserNameProvider.qml
@@ -1,29 +1,37 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 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 'matrix-helpers.js' as Helpers
QtObject {
property var user
+ property var overridedName: getOverridedName(user)
property var name: getName(user)
function getName(u) {
if (!u) {
return '';
}
return Helpers.userDisplayName(
u.name,
u.userId,
sdkVars.userGivenNicknameMap.map,
l10n,
);
}
+
+ function getOverridedName(u) {
+ if (!u) {
+ return '';
+ }
+ return sdkVars.userGivenNicknameMap.map[u.userId] || '';
+ }
}
diff --git a/src/contents/ui/UserPage.qml b/src/contents/ui/UserPage.qml
index e50d93d..b0f7df2 100644
--- a/src/contents/ui/UserPage.qml
+++ b/src/contents/ui/UserPage.qml
@@ -1,295 +1,330 @@
/*
* 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.20 as Kirigami
import moe.kazv.mxc.kazv 0.0 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 roomName: Helpers.roomNameOrHeroes(room, l10n)
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: {
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: {
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 {
Kirigami.Avatar {
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
}
+ 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
}
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'
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
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
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/l10n/cmn-Hans/100-ui.ftl b/src/l10n/cmn-Hans/100-ui.ftl
index aa0ce83..4da6c37 100644
--- a/src/l10n/cmn-Hans/100-ui.ftl
+++ b/src/l10n/cmn-Hans/100-ui.ftl
@@ -1,290 +1,293 @@
### This file is part of kazv.
### SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
### SPDX-License-Identifier: AGPL-3.0-or-later
app-title = { -kt-app-name }
user-name-with-id = { $name } ({ $userId })
user-name-overrided = { $overridedName } ({ $globalName })
global-drawer-title = { -kt-app-name }
global-drawer-action-switch-account = 切换账号
global-drawer-action-hard-logout = 登出
global-drawer-action-save-session = 保存当前会话
global-drawer-action-configure-shortcuts = 配置快捷键
global-drawer-action-settings = 设置
global-drawer-action-create-room = 创建房间
global-drawer-action-join-room = 加入房间
action-settings-page-title = 配置快捷键
action-settings-shortcut-prompt = 快捷键:{ $shortcut }
action-settings-shortcut-none = (无)
action-settings-shortcut-edit-action = 编辑
action-settings-shortcut-remove-action = 清除
action-settings-shortcut-conflict-modal-title = 冲突的快捷键
action-settings-shortcut-conflict = 快捷键 { $shortcut } 跟别的指令有冲突。<br>若要继续,别的指令的快捷键会被清除。<br><br>冲突的指令有:<br>{ $conflictingAction }
action-settings-shortcut-conflict-continue = 继续
action-settings-shortcut-conflict-cancel = 取消
empty-room-page-title = 没有选中房间
empty-room-page-description = 当前没有选中的房间。
login-page-title = 登录
login-page-userid-prompt = 用户 id:
login-page-userid-input-placeholder = 例如: @foo:example.org
login-page-password-prompt = 密码:
login-page-login-button = 登录
login-page-close-button = 关闭
login-page-existing-sessions-prompt = 从已有会话中选一个:
login-page-alternative-password-login-prompt = 或者用用户 id 和密码启动新会话:
login-page-restore-session-button = 恢复会话
login-page-request-failed-prompt = 登录失败。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
login-page-discover-failed-prompt = 不能检测此用户所在的服务器,或者服务器不可用。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
main-page-title = { -kt-app-name } - { $userId }
main-page-recent-tab-title = 最近
main-page-favourites-tab-title = 最爱
main-page-people-tab-title = 人们
main-page-rooms-tab-title = 房间
main-page-room-filter-prompt = 过滤房间...
room-list-view-room-item-title-name = { $name }
room-list-view-room-item-title-heroes = { $hero } { $otherNum ->
[0] { "" }
[1] 和 { $secondHero }
*[other] 和别的 { $otherNum } 个人
}
room-list-view-room-item-title-id = 未命名房间({ $roomId })
room-list-view-room-item-fav-action = 设为最爱
room-list-view-room-item-unread-indicator = 未读
room-tags-fav-action-notification = 把 { $name } 设为了最爱
room-tags-fav-action-notification-failed = 不能把 { $name } 设为最爱。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-tags-unfav-action-notification = 把 { $name } 从最爱中移除了
room-tags-unfav-action-notification-failed = 不能把 { $name } 从最爱中移除。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-tags-add-tag-action-notification = 把标签 { $tag } 添加到了 { $name }
room-tags-add-tag-action-notification-failed = 不能把标签 { $tag } 添加到 { $name }。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-tags-remove-tag-action-notification = 把标签 { $tag } 从 { $name } 移除了
room-tags-remove-tag-action-notification-failed = 不能把标签 { $tag } 从 { $name } 移除。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-list-view-room-item-more-action = 更多...
room-list-view-room-item-invited = (邀请)
room-list-view-room-item-left = (已离开)
room-settings-action = 房间设置...
room-settings-page-title = { $room } 的房间设置
room-settings-tags = 房间标签
room-settings-favourited = 设为最爱
room-settings-remove-tag = 移除标签
room-settings-add-tag = 添加标签
room-settings-members-action = 房间成员...
room-settings-banned-members-action = 被封禁的成员...
room-settings-enable-encryption-prompt-dialog-title = 启用加密
room-settings-enable-encryption-prompt-dialog-prompt = 一旦在本房间中启用了加密,就不能再禁用了。确定吗?
room-settings-enable-encryption-action = 启用加密
room-settings-encrypted = 本房间中的消息是端对端加密了的。
room-settings-not-encrypted = 本房间中的消息没有端对端加密。
room-settings-encryption-enabled-notification = 本房间中的加密已经启用。
room-settings-encryption-failed-to-enable-notification = 不能在本房间中启用加密。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-member-list-page-title = { $room } 的成员
room-leave-action = 离开房间
room-leave-confirm-popup-title = 离开房间
room-leave-confirm-popup-message = 你确定要离开这个房间吗?
room-leave-confirm-popup-confirm-action = 离开
room-leave-confirm-popup-cancel-action = 留下
send-message-box-input-placeholder = 在此输入您的讯息...
send-message-box-send = 发送
send-message-box-send-file = 发送文件
send-message-box-reply-to = 回复给
send-message-box-edit = 编辑
send-message-box-remove-reply-to-action = 移除回复关系
send-message-box-remove-replace-action = 取消编辑
send-message-box-stickers = 发送贴纸...
send-message-box-stickers-popup-title = 发送贴纸
sticker-picker-user-stickers = 我的贴纸
room-timeline-load-more-action = 加载更多
room-invite-accept-action = 接受邀请
room-invite-reject-action = 拒绝邀请
room-invite-popup-title = 被邀请了
room-invite-popup-text = 你被邀请到这个房间了。
room-invite-popup-text-with-inviter = 你被 { $inviterName } 邀请到这个房间了。
## 状态事件
## 通用参数:
## gender = 发送者的性别(male/female/neutral)
## stateKeyUser = state key 用户的名字
## stateKeyUserGender = state key 用户的性别
member-state-joined-room = 加入了房间。
member-state-changed-name-and-avatar = 修改了名字和头像。
member-state-changed-name = 修改了名字。
member-state-changed-avatar = 修改了头像。
member-state-invited = 把 { $stateKeyUser } 邀请到了本房间。
member-state-left = 离开了房间。
member-state-kicked = 踢出了 { $stateKeyUser }。
member-state-banned = 封禁了 { $stateKeyUser }。
member-state-unbanned = 解封了 { $stateKeyUser }。
state-room-created = 创建了房间。
state-room-name-changed = 把房间名字改成了 { $newName }。
state-room-topic-changed = 把房间话题改成了 { $newTopic }。
state-room-avatar-changed = 修改了房间头像。
state-room-pinned-events-changed = 修改了房间的置顶讯息。
state-room-alias-changed = 修改了房间的别名。
state-room-join-rules-changed = 修改了房间的加入规则。
state-room-power-levels-changed = 修改了房间的权限。
state-room-encryption-activated = 对本房间启用了加密。
event-message-image-sent = 发送了图片「{ $body }」。
event-message-file-sent = 发送了文件「{ $body }」。
event-message-video-sent = 发送了视频「{ $body }」。
event-message-audio-sent = 发送了音频「{ $body }」。
event-message-audio-play-audio = 播放音频
event-sending = 发送中...
event-send-failed = 发送失败
event-resend = 重试发送这个事件
event-deleted = (已删除)
event-delete = 删除
event-delete-failed = 删除事件出错。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
event-view-source = 查看源码...
event-source-popup-title = 事件源码
event-source-decrypted = 解密的事件源码
event-source-original = 原始的事件源码
event-reply-action = 回复
event-popup-action = 更多关于这个事件...
event-reacted-with = 回应了「{ $key }」
event-react-action = 回应...
event-react-popup-title = 回应一条消息
event-react-accept-action = 回应
event-react-cancel-action = 取消
event-react-with-prompt = 回应以:
event-edit-action = 编辑
event-encrypted = 这条消息已加密
event-msgtype-fallback-text = 未知的消息类型:{ $msgtype }
event-fallback-text = 未知事件:{ $type }
event-cannot-decrypt-text = (加密内容)
event-read-indicator-more = +{ $rest }
event-read-indicator-list-title = { $numUsers } 个用户已读
event-edited-indicator = (编辑过了)
media-file-menu-option-view = 查看
media-file-menu-option-save-as = 保存为
media-file-menu-add-sticker-action = 添加到贴纸...
add-sticker-popup-title = 添加到贴纸
add-sticker-popup-short-code-prompt = 短代码:
add-sticker-popup-short-code-exists-warning = 贴纸包里已经有这个短代码了。上面的贴纸会覆盖已有的。
add-sticker-popup-add-sticker-button = 添加
add-sticker-popup-cancel-button = 取消
add-sticker-popup-failed-prompt = 无法添加贴纸。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
kazv-io-download-success-prompt = 下载成功
kazv-io-download-failure-prompt = 下载失败:{ $detail }
kazv-io-failure-detail-user-cancel = 用户已取消
kazv-io-failure-detail-network-error = 网络错误
kazv-io-failure-detail-open-file-error = 打开文件错误
kazv-io-failure-detail-write-file-error = 写入文件错误
kazv-io-failure-detail-hash-error = 哈息值校验失败
kazv-io-failure-detail-kazv-error = 未知错误,请将此报告为漏洞
kazv-io-upload-failure-prompt = 上传失败:{ $detail }
kazv-io-downloading-prompt = 正在下载:{ $fileName }
kazv-io-uploading-prompt = 正在上传:{ $fileName }
kazv-io-prompt-close = 好的
kazv-io-pause = 暂停
kazv-io-resume = 继续
kazv-io-cancel = 取消
create-room-page-title = 创建房间
create-room-page-visibility-prompt = 房间可见性:
create-room-page-visibility-public = 公开
create-room-page-visibility-private = 私有
create-room-page-name-prompt = 房间名称(可选):
create-room-page-name-placeholder = 无名
create-room-page-alias-prompt = 房间别名(可选):
create-room-page-alias-placeholder = #foo:example.org
create-room-page-topic-prompt = 房间主题(可选):
create-room-page-topic-placeholder = 无题
create-room-page-allow-federate-prompt = 允许别的服务器上的用户加入
create-room-page-action-create-room = 创建房间
create-room-page-success-prompt = 房间已创建。
create-room-page-failed-prompt = 无法创建房间。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
join-room-page-title = 加入房间
join-room-page-id-or-alias-prompt = 房间 id 或别名:
join-room-page-id-or-alias-placeholder = #foo:example.org 或 !abcdef:example.org
join-room-page-servers-prompt = 经由服务器(可选,用换行分割):
join-room-page-servers-placeholder =
example.org
example.com
join-room-page-action-join-room = 加入房间
join-room-page-success-prompt = 成功加入房间 { $room }。
join-room-page-failed-prompt = 无法加入房间 { $room }。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
leave-room-success-prompt = 成功离开房间 { $room }。
leave-room-failed-prompt = 无法离开房间 { $room }。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。
device-trust-level-unseen = 未曾见过
device-trust-level-seen = 见过
device-trust-level-verified = 已验证
device-trust-level-blocked = 已屏蔽
device-set-trust-level = 设置信任等级...
device-set-trust-level-dialog-title = 设置信任等级
device-set-trust-level-dialog-name-label = 设备名:{ $name }
device-set-trust-level-dialog-id-label = 设备id:{ $id }
device-set-trust-level-dialog-ed25519-key-label = Ed25519公钥:{ $key }
device-set-trust-level-dialog-curve25519-key-label = Curve25519公钥:{ $key }
device-set-trust-level-dialog-save = 保存
device-set-trust-level-dialog-cancel = 取消
settings-page-title = 设置
settings-save = 保存设置
settings-profile-load-failed-prompt = 无法加载用户资料。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
settings-profile-change-avatar = 改变头像...
settings-profile-display-name = 显示名:
settings-profile-save-failed-prompt = 无法保存用户资料。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
settings-cache-directory = 缓存目录:
typing-indicator = { $typingUser } { $otherNum ->
[0] 正在输入...
[1] 和 { $secondTypingUser } 正在输入...
*[other] 和另外 { $otherNum } 人正在输入...
}
notification-message = <b>{ $user }:</b> { $message }
notification-message-no-content = <b>{ $user }</b> 给你发了一条讯息。
notification-open = 打开
user-page-power-level = 权限等级:{ $powerLevel }
user-page-edit-power-level-action = 编辑
user-page-save-power-level-action = 保存
user-page-discard-power-level-action = 丢弃
user-page-set-power-level-failed-prompt = 无法设置权限等级。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
user-page-kick-user-action = 踢出
user-page-kick-user-confirm-dialog-title = 踢出用户
user-page-kick-user-confirm-dialog-content = 确定要把 { $name }({ $userId })踢出 { $roomName } 吗?
user-page-kick-user-reason-prompt = 原因(可选):
user-page-kick-user-failed-prompt = 无法踢出用户。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
user-page-ban-user-action = 封禁
user-page-ban-user-confirm-dialog-titile = 封禁用户
user-page-ban-user-confirm-dialog-content = 确定要在 { $roomName } 中封禁 { $name }({ $userId })吗?
user-page-ban-user-reason-prompt = 原因(可选):
user-page-ban-user-failed-prompt = 无法封禁用户。错误码:{ $error }。错误讯息:{ $errorMsg }。
user-page-unban-user-action = 解禁
user-page-unban-user-failed-prompt = 无法解禁用户。错误码:{ $error }。错误讯息:{ $errorMsg }。
+user-page-overrided-name-placeholder = 自定义显示名...
+user-page-save-name-override-action = 保存
+user-page-update-name-override-failed-prompt = 无法设置自定义显示名。错误码:{ $error }。错误讯息:{ $errorMsg }。
room-invite-page-title = 邀请用户到 { $room }
room-invite-page-invite-failed-prompt = 无法邀请用户。错误码:{ $errorCode }。错误讯息:{ $errorMsg }。
room-invite-invitee-matrix-id-placeholder = 用户的 Matrix id,比如 @foo:example.org
room-invite-invitee-matrix-id-prompt = 要邀请的用户:
room-invite-page-invite-button = 邀请
room-invite-action = 邀请到房间...
confirm-upload-popup-title = 确认上传
confirm-upload-popup-prompt = 即将上传「{ $file }」({ $current } / { $total })。
confirm-upload-popup-prompt-single-file = 即将上传「{ $file }」。
confirm-upload-popup-accept-button = 上传
confirm-upload-popup-cancel-button = 取消
diff --git a/src/l10n/en/100-ui.ftl b/src/l10n/en/100-ui.ftl
index fbe0f0e..312cb50 100644
--- a/src/l10n/en/100-ui.ftl
+++ b/src/l10n/en/100-ui.ftl
@@ -1,311 +1,314 @@
### This file is part of kazv.
### SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
### SPDX-License-Identifier: AGPL-3.0-or-later
app-title = { -kt-app-name }
user-name-with-id = { $name } ({ $userId })
user-name-overrided = { $overridedName } ({ $globalName })
global-drawer-title = { -kt-app-name }
global-drawer-action-switch-account = Switch account
global-drawer-action-hard-logout = Logout
global-drawer-action-save-session = Save current session
global-drawer-action-configure-shortcuts = Configure shortcuts
global-drawer-action-settings = Settings
global-drawer-action-create-room = Create room
global-drawer-action-join-room = Join room
action-settings-page-title = Configure shortcuts
action-settings-shortcut-prompt = Shortcut: { $shortcut }
action-settings-shortcut-none = (none)
action-settings-shortcut-edit-action = Edit
action-settings-shortcut-remove-action = Clear
action-settings-shortcut-conflict-modal-title = Conflicting shortcuts
action-settings-shortcut-conflict = The shortcut { $shortcut } has conflicts with other actions. <br>If you continue, the shortcuts for other actions will be cleared. <br><br>Conflicting actions: <br>{ $conflictingAction }
action-settings-shortcut-conflict-continue = Continue
action-settings-shortcut-conflict-cancel = Cancel
empty-room-page-title = No rooms selected
empty-room-page-description = There is no room selected now.
login-page-title = Log in
login-page-userid-prompt = User id:
login-page-userid-input-placeholder = E.g.: @foo:example.org
login-page-password-prompt = Password:
login-page-login-button = Log in
login-page-close-button = Close
login-page-existing-sessions-prompt = Choose from one of the existing sessions:
login-page-alternative-password-login-prompt = Or start a new session with user id and password:
login-page-restore-session-button = Restore session
login-page-request-failed-prompt = Login failed. Error code: { $errorCode }. Error message: { $errorMsg }.
login-page-discover-failed-prompt = Unable to detect the server this user is on, or the server is unavailable. Error code: { $errorCode }. Error message: { $errorMsg }.
main-page-title = { -kt-app-name } - { $userId }
main-page-recent-tab-title = Recent
main-page-favourites-tab-title = Favourites
main-page-people-tab-title = People
main-page-rooms-tab-title = Rooms
main-page-room-filter-prompt = Filter rooms by...
room-list-view-room-item-title-name = { $name }
room-list-view-room-item-title-heroes = { $hero } { $otherNum ->
[0] { "" }
[1] and { $secondHero }
*[other] and { $otherNum } others
}
room-list-view-room-item-title-id = Unnamed room ({ $roomId })
room-list-view-room-item-fav-action = Set as favourite
room-list-view-room-item-unread-indicator = Unread
room-tags-fav-action-notification = Set { $name } as favourite
room-tags-fav-action-notification-failed = Cannot set { $name } as favourite. Error code: { $errorCode }. Error message: { $errorMsg }.
room-tags-unfav-action-notification = Removed { $name } from favourites
room-tags-unfav-action-notification-failed = Cannot remove { $name } from favourites. Error code: { $errorCode }. Error message: { $errorMsg }.
room-tags-add-tag-action-notification = Added tag { $tag } to { $name }
room-tags-add-tag-action-notification-failed = Cannot add tag { $tag } to { $name }. Error code: { $errorCode }. Error message: { $errorMsg }.
room-tags-remove-tag-action-notification = Removed tag { $tag } from { $name }
room-tags-remove-tag-action-notification-failed = Cannot remove tag { $tag } from { $name }. Error code: { $errorCode }. Error message: { $errorMsg }.
room-list-view-room-item-more-action = More...
room-list-view-room-item-invited = (Invited)
room-list-view-room-item-left = (Left)
room-settings-action = Room settings...
room-settings-page-title = Room settings for { $room }
room-settings-tags = Room tags
room-settings-favourited = Set as favourite
room-settings-remove-tag = Remove tag
room-settings-add-tag = Add tag
room-settings-members-action = Room members...
room-settings-banned-members-action = Banned members...
room-settings-enable-encryption-prompt-dialog-title = Enabling encryption
room-settings-enable-encryption-prompt-dialog-prompt = Once you enable encryption in this room, you cannot disable it again. Are you sure?
room-settings-enable-encryption-action = Enable encryption
room-settings-encrypted = Messages in this room are end-to-end encrypted.
room-settings-not-encrypted = Messages in this room are not end-to-end-encrypted.
room-settings-encryption-enabled-notification = Encryption is now enabled in this room.
room-settings-encryption-failed-to-enable-notification = Cannot enable encryption in this room. Error code: { $errorCode }. Error message: { $errorMsg }.
room-member-list-page-title = Members of { $room }
room-leave-action = Leave room
room-leave-confirm-popup-title = Leaving room
room-leave-confirm-popup-message = Are you sure you want to leave this room?
room-leave-confirm-popup-confirm-action = Leave
room-leave-confirm-popup-cancel-action = Stay
send-message-box-input-placeholder = Type your message here...
send-message-box-send = Send
send-message-box-send-file = Send file
send-message-box-reply-to = Replying to
send-message-box-edit = Editing
send-message-box-remove-reply-to-action = Remove reply-to relationship
send-message-box-remove-replace-action = Cancel editing
send-message-box-stickers = Send a sticker...
send-message-box-stickers-popup-title = Send a sticker
sticker-picker-user-stickers = My stickers
room-timeline-load-more-action = Load more
room-invite-accept-action = Accept invite
room-invite-reject-action = Reject invite
room-invite-popup-title = Invited
room-invite-popup-text = You are invited to join this room.
room-invite-popup-text-with-inviter = You are invited to join this room by { $inviterName }.
## State events
## Common parameters:
## gender = gender of the sender (male/female/neutral)
## stateKeyUser = name of the state key user
## stateKeyUserGender = gender of the state key user
member-state-joined-room = joined the room.
member-state-changed-name-and-avatar = changed { $gender ->
[male] his
[female] her
*[neutral] their
} name and avatar.
member-state-changed-name = changed { $gender ->
[male] his
[female] her
*[neutral] their
} name.
member-state-changed-avatar = changed { $gender ->
[male] his
[female] her
*[neutral] their
} avatar.
member-state-invited = invited { $stateKeyUser } to the room.
member-state-left = left the room.
member-state-kicked = kicked { $stateKeyUser }.
member-state-banned = banned { $stateKeyUser }.
member-state-unbanned = unbanned { $stateKeyUser }.
state-room-created = created the room.
state-room-name-changed = changed the name of the room to { $newName }.
state-room-topic-changed = changed the topic of the room to { $newTopic }.
state-room-avatar-changed = changed the avatar of the room.
state-room-pinned-events-changed = changed the pinned events of the room.
state-room-alias-changed = changed the aliases of the room.
state-room-join-rules-changed = changed join rules of the room.
state-room-power-levels-changed = changed power levels of the room.
state-room-encryption-activated = enabled encryption for this room.
event-message-image-sent = sent an image "{ $body }".
event-message-file-sent = sent a file "{ $body }".
event-message-video-sent = sent a video "{ $body }".
event-message-audio-sent = sent an audio "{ $body }".
event-message-audio-play-audio = Play audio
event-sending = Sending...
event-send-failed = Failed to send
event-resend = Retry sending this event
event-deleted = (Deleted)
event-delete = Delete
event-delete-failed = Error deleting event. Error code: { $errorCode }. Error message: { $errorMsg }.
event-view-source = View source...
event-source-popup-title = Event source
event-source-decrypted = Decrypted event source
event-source-original = Original event source
event-reply-action = Reply
event-popup-action = More about this event...
event-reacted-with = Reacted with "{ $key }"
event-react-action = React...
event-react-popup-title = React to a message
event-react-accept-action = React
event-react-cancel-action = Cancel
event-react-with-prompt = React with:
event-edit-action = Edit
event-encrypted = This message is encrypteed
event-msgtype-fallback-text = Unknown message type: { $msgtype }
event-fallback-text = Unknown event: { $type }
event-cannot-decrypt-text = (Encrypted content)
event-read-indicator-more = +{ $rest }
event-read-indicator-list-title = Read by { $numUsers ->
[1] 1 user
*[other] { $numUsers } users
}
event-edited-indicator = (edited)
media-file-menu-option-view = View
media-file-menu-option-save-as = Save as
media-file-menu-add-sticker-action = Add to sticker...
add-sticker-popup-title = Add to sticker
add-sticker-popup-short-code-prompt = Short code:
add-sticker-popup-short-code-exists-warning = The short code already exists in this pack. The sticker above will override the existing one.
add-sticker-popup-add-sticker-button = Add
add-sticker-popup-cancel-button = Cancel
add-sticker-popup-failed-prompt = Unable to add sticker. Error code: { $errorCode }. Error message: { $errorMsg }.
kazv-io-download-success-prompt = Download successful
kazv-io-download-failure-prompt = Download failure: { $detail }
kazv-io-failure-detail-user-cancel = User canceled
kazv-io-failure-detail-network-error = Network error
kazv-io-failure-detail-open-file-error = Open file error
kazv-io-failure-detail-write-file-error = Write file error
kazv-io-failure-detail-hash-error = Hash check error
kazv-io-failure-detail-kazv-error = Unknow Error, please report this as bug.
kazv-io-upload-failure-prompt = Upload failure: { $detail }
kazv-io-downloading-prompt = Downloading: { $fileName }
kazv-io-uploading-prompt = Uploading: { $fileName }
kazv-io-prompt-close = Got it
kazv-io-pause = Pause
kazv-io-resume = Resume
kazv-io-cancel = Cancel
create-room-page-title = Create room
create-room-page-type-prompt = Room type:
create-room-page-type-public = Public (everyone can join)
create-room-page-type-private = Private (only invited users can join)
create-room-page-type-direct = Direct message (same as private, but those initially invited get admin permissions)
create-room-page-name-prompt = Room name (optional):
create-room-page-name-placeholder = No name
create-room-page-alias-prompt = Room alias (optional):
create-room-page-alias-placeholder = #foo:example.org
create-room-page-topic-prompt = Room topic (optional):
create-room-page-topic-placeholder = No topic
create-room-page-allow-federate-prompt = Allow users from other servers to join
create-room-page-action-create-room = Create room
create-room-page-success-prompt = Room created.
create-room-page-failed-prompt = Unable to create room. Error code: { $errorCode }. Error message: { $errorMsg }.
create-room-invite-userids-prompt = Matrix ids of users to invite:
create-room-page-add-invite-prompt = Add a new user to invite:
create-room-page-add-invite-placeholder = Matrix id, e.g. @foo:example.org
create-room-page-action-add-invite = Add
create-room-page-action-remove-invite = Remove
join-room-page-title = Join room
join-room-page-id-or-alias-prompt = Room id or alias:
join-room-page-id-or-alias-placeholder = #foo:example.org or !abcdef:example.org
join-room-page-servers-prompt = Via servers (optional, separated by newlines):
join-room-page-servers-placeholder =
example.org
example.com
join-room-page-action-join-room = Join room
join-room-page-success-prompt = Successfully joined room { $room }.
join-room-page-failed-prompt = Unable to join room { $room }. Error code: { $errorCode }. Error message: { $errorMsg }.
leave-room-success-prompt = Successfully left room { $room }.
leave-room-failed-prompt = Unable to leave room { $room }. Error code: { $errorCode }. Error message: { $errorMsg }.
device-trust-level-unseen = Unseen
device-trust-level-seen = Seen
device-trust-level-verified = Verified
device-trust-level-blocked = Blocked
device-set-trust-level = Set trust level...
device-set-trust-level-dialog-title = Set trust level
device-set-trust-level-dialog-name-label = Device name: { $name }
device-set-trust-level-dialog-id-label = Device id: { $id }
device-set-trust-level-dialog-ed25519-key-label = Ed25519 public key: { $key }
device-set-trust-level-dialog-curve25519-key-label = Curve25519 public key: { $key }
device-set-trust-level-dialog-save = Save
device-set-trust-level-dialog-cancel = Cancel
settings-page-title = Settings
settings-save = Save settings
settings-profile-load-failed-prompt = Unable to load profile. Error code: { $errorCode }. Error message: { $errorMsg }.
settings-profile-change-avatar = Change avatar...
settings-profile-display-name = Display name:
settings-profile-save-failed-prompt = Unable to save profile. Error code: { $errorCode }. Error message: { $errorMsg }.
settings-cache-directory = Cache directory:
typing-indicator = { $typingUser } { $otherNum ->
[0] is typing...
[1] and { $secondTypingUser } are typing...
*[other] and { $otherNum } others are typing...
}
notification-message = <b>{ $user }:</b> { $message }
notification-message-no-content = <b>{ $user }</b> sent you a message.
notification-open = Open
user-page-power-level = Power level: { $powerLevel }
user-page-edit-power-level-action = Edit
user-page-save-power-level-action = Save
user-page-discard-power-level-action = Discard
user-page-set-power-level-failed-prompt = Unable to set power level. Error code: { $errorCode }. Error message: { $errorMsg }.
user-page-kick-user-action = Kick
user-page-kick-user-confirm-dialog-title = Kicking user
user-page-kick-user-confirm-dialog-content = Are you sure you want to kick { $name } ({ $userId }) out of { $roomName }?
user-page-kick-user-reason-prompt = Reason (optional):
user-page-kick-user-failed-prompt = Unable to kick user. Error code: { $errorCode }. Error message: { $errorMsg }.
user-page-ban-user-action = Ban
user-page-ban-user-confirm-dialog-title = Banning user
user-page-ban-user-confirm-dialog-content = Are you sure you want to ban { $name } ({ $userId }) in { $roomName }?
user-page-ban-user-reason-prompt = Reason (optional):
user-page-ban-user-failed-prompt = Unable to ban user. Error code: { $errorCode }. Error message: { $errorMsg }.
user-page-unban-user-action = Unban
user-page-unban-user-failed-prompt = Unable to unban user. Error code: { $errorCode }. Error message: { $errorMsg }.
+user-page-overrided-name-placeholder = Custom display name...
+user-page-save-name-override-action = Save
+user-page-update-name-override-failed-prompt = Unable to set custom display name. Error code: { $errorCode }. Error message: { $errorMsg }.
room-invite-page-title = Inviting user to { $room }
room-invite-page-invite-failed-prompt = Unable to invite user. Error code: { $errorCode }. Error message: { $errorMsg }.
room-invite-invitee-matrix-id-placeholder = Matrix id of the user, e.g. @foo:example.org
room-invite-invitee-matrix-id-prompt = User to invite:
room-invite-page-invite-button = Invite
room-invite-action = Invite to room...
confirm-upload-popup-title = Confirm upload
confirm-upload-popup-prompt = You are about to upload "{ $file }" ({ $current } / { $total }).
confirm-upload-popup-prompt-single-file = You are about to upload "{ $file }".
confirm-upload-popup-accept-button = Upload
confirm-upload-popup-cancel-button = Cancel
diff --git a/src/tests/quick-tests/tst_UserNameProvider.qml b/src/tests/quick-tests/tst_UserNameProvider.qml
index cae19ee..73e4755 100644
--- a/src/tests/quick-tests/tst_UserNameProvider.qml
+++ b/src/tests/quick-tests/tst_UserNameProvider.qml
@@ -1,101 +1,108 @@
/*
* 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 QtTest 1.0
import '../../contents/ui' as Kazv
import './test-helpers' as TestHelpers
import 'test-helpers.js' as Helpers
TestCase {
id: userNameProviderTest
name: 'UserNameProviderTest'
when: true
property var sdkVars: QtObject {
property var userGivenNicknameMap: QtObject {
property var map: ({})
}
}
property var l10n: Helpers.fluentMock
property var userOverrided: ({
name: 'foo',
userId: '@foo:tusooa.xyz'
})
property var userNotOverrided: ({
name: 'bar',
userId: '@bar:tusooa.xyz'
})
property var userIdOnly: ({ userId: '@bar:tusooa.xyz' })
property var providerFunctional: Kazv.UserNameProvider {}
property var providerReactive: Kazv.UserNameProvider {}
property var userComp: Component {
QtObject {
property var name: 'bar'
property var userId: '@bar:tusooa.xyz'
}
}
function init() {
sdkVars.userGivenNicknameMap.map = {
'@foo:tusooa.xyz': 'something',
};
}
function test_functional() {
compare(
providerFunctional.getName(userOverrided),
l10n.get(
'user-name-overrided', { overridedName: 'something', globalName: 'foo' }));
+ compare(providerFunctional.getOverridedName(userOverrided), 'something');
compare(
providerFunctional.getName(userNotOverrided),
'bar'
);
+ compare(providerFunctional.getOverridedName(userNotOverrided), '');
compare(
providerFunctional.getName(userIdOnly),
'@bar:tusooa.xyz'
);
}
function test_reactiveAgainstUser() {
providerReactive.user = userComp.createObject(userNameProviderTest);
compare(providerReactive.name, 'bar');
+ compare(providerReactive.overridedName, '');
providerReactive.user.userId = '@foo:tusooa.xyz';
compare(
providerReactive.name,
l10n.get(
'user-name-overrided', { overridedName: 'something', globalName: 'bar' }));
+ compare(providerReactive.overridedName, 'something');
providerReactive.user = userComp.createObject(userNameProviderTest, {
userId: '@foo:tusooa.xyz',
name: 'foo',
});
compare(
providerReactive.name,
l10n.get(
'user-name-overrided', { overridedName: 'something', globalName: 'foo' }));
+ compare(providerReactive.overridedName, 'something');
}
function test_reactiveAgainstOverrides() {
providerReactive.user = userComp.createObject(userNameProviderTest);
compare(providerReactive.name, 'bar');
+ compare(providerReactive.overridedName, '');
sdkVars.userGivenNicknameMap.map = {
'@bar:tusooa.xyz': 'something',
};
compare(
providerReactive.name,
l10n.get(
'user-name-overrided', { overridedName: 'something', globalName: 'bar' }));
+ compare(providerReactive.overridedName, 'something');
}
}
diff --git a/src/tests/quick-tests/tst_UserPage.qml b/src/tests/quick-tests/tst_UserPage.qml
index ee2cc35..f00fc7a 100644
--- a/src/tests/quick-tests/tst_UserPage.qml
+++ b/src/tests/quick-tests/tst_UserPage.qml
@@ -1,314 +1,401 @@
/*
* 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 QtTest 1.0
import '../../contents/ui' as Kazv
import './test-helpers' as TestHelpers
import 'test-helpers.js' as Helpers
Item {
id: upper
width: 800
height: 600
property var l10n: Helpers.fluentMock
- property var matrixSdk: TestHelpers.MatrixSdkMock {}
+ property var matrixSdk: TestHelpers.MatrixSdkMock {
+ property var userId: '@foo:example.com'
+ }
+ property var sdkVars: QtObject {
+ property var userGivenNicknameMap: QtObject {
+ id: gnMap
+ property var map: ({})
+ property var _setAndUploadCalled: 0
+ property var _setAndUploadArgs: []
+ property var _setAndUploadPromise: null
+ function setAndUpload(userId, value) {
+ ++_setAndUploadCalled;
+ _setAndUploadArgs = [userId, value];
+ _setAndUploadPromise = promiseComp.createObject(upper);
+ return _setAndUploadPromise;
+ }
+ }
+ }
property var lastNotification: undefined
function showPassiveNotification(msg) {
upper.lastNotification = msg;
}
property var promiseComp: Component {
TestHelpers.MatrixPromiseMock {
}
}
property var powerLevelMapping: ({
'@mew:example.com': 100,
})
property var room: ({
userPowerLevel(userId) {
return powerLevelMapping[userId];
},
setUserPowerLevel(userId, powerLevel) {
upper.room._setUserPowerLevelUserId = userId;
upper.room._setUserPowerLevelPowerLevel = powerLevel;
upper.room._setUserPowerLevelPromise = promiseComp.createObject(upper.room);
return upper.room._setUserPowerLevelPromise;
},
ensureStateEvent(type, stateKey) {
const promise = promiseComp.createObject(upper.room);
console.log('ensureStateEvent', type, stateKey, promise);
upper.room._ensureStateEventPromises.push(promise);
console.log(upper.room._ensureStateEventPromises);
return promise;
},
kickUser(userId, reason) {
upper.room._kickUserUserId = userId;
upper.room._kickUserReason = reason;
upper.room._kickUserPromise = promiseComp.createObject(upper.room);
return upper.room._kickUserPromise;
},
banUser(userId, reason) {
upper.room._banUserUserId = userId;
upper.room._banUserReason = reason;
upper.room._banUserPromise = promiseComp.createObject(upper.room);
return upper.room._banUserPromise;
},
unbanUser(userId) {
upper.room._unbanUserUserId = userId;
upper.room._unbanUserPromise = promiseComp.createObject(upper.room);
return upper.room._unbanUserPromise;
},
_setUserPowerLevelUserId: undefined,
_setUserPowerLevelPowerLevel: undefined,
_setUserPowerLevelPromise: undefined,
_ensureStateEventPromises: [],
_kickUserUserId: undefined,
_kickUserReason: undefined,
_kickUserPromise: undefined,
_banUserUserId: undefined,
_banUserReason: undefined,
_banUserPromise: undefined,
_unbanUserUserId: undefined,
_unbanUserPromise: undefined,
})
ColumnLayout {
Kazv.UserPage {
id: userPage
userId: '@mew:example.com'
- user: ({})
+ user: ({ userId: '@mew:example.com', name: 'mew' })
room: upper.room
}
+
+ Kazv.UserPage {
+ id: userPageSelf
+ userId: '@foo:example.com'
+ }
}
TestCase {
id: userPageTest
name: 'UserPageTest'
when: windowShown
function cleanupTestCase() {
upper.room._setUserPowerLevelUserId = undefined;
upper.room._setUserPowerLevelPowerLevel = undefined;
upper.room._setUserPowerLevelPromise = undefined;
upper.room._ensureStateEventPromises = [];
upper.room._kickUserUserId = undefined;
upper.room._kickUserReason = undefined;
upper.room._kickUserPromise = undefined;
upper.room._banUserUserId = undefined;
upper.room._banUserReason = undefined;
upper.room._banUserPromise = undefined;
upper.room._unbanUserUserId = undefined;
upper.room._unbanUserPromise = undefined;
userPage.submittingPowerLevel = false;
userPage.editingPowerLevel = false;
userPage.powerLevelsLoaded = false;
userPage.banningUser = false;
userPage.unbanningUser = false;
upper.lastNotification = undefined;
userPage.user = ({});
+ gnMap.map = {};
+ gnMap._setAndUploadCalled = 0;
+ gnMap._setAndUploadArgs = [];
+ gnMap._setAndUploadPromise = null;
}
function test_powerLevel() {
verify(findChild(userPage, 'powerLevelLabel').visible);
verify(findChild(userPage, 'powerLevelLabel').text.includes('100'));
verify(!findChild(userPage, 'newPowerLevelInput').visible);
const editButton = findChild(userPage, 'editPowerLevelButton');
verify(editButton.visible);
verify(!editButton.enabled);
tryVerify(() => userPage.room._ensureStateEventPromises[1], 1000);
userPage.room._ensureStateEventPromises[1].resolve(true, {});
tryVerify(() => editButton.enabled);
mouseClick(editButton);
const textField = findChild(userPage, 'newPowerLevelInput');
tryVerify(() => textField.visible, 1000);
textField.text = '50';
const saveButton = findChild(userPage, 'savePowerLevelButton');
mouseClick(saveButton);
tryVerify(() => room._setUserPowerLevelPromise, 1000);
// Text field is not closed until the request succeeded
verify(textField.visible);
verify(textField.readOnly);
verify(room._setUserPowerLevelUserId === '@mew:example.com');
verify(room._setUserPowerLevelPowerLevel === 50);
// the buttons are disabled until the request responded
verify(!saveButton.enabled);
verify(!findChild(userPage, 'discardPowerLevelButton').enabled);
room._setUserPowerLevelPromise.resolve(true, {});
tryVerify(() => !textField.visible, 1000);
// Text field is editable when we try to edit the power level again
mouseClick(editButton);
tryVerify(() => textField.visible, 1000);
verify(!textField.readOnly);
}
function test_powerLevelEditFailure() {
tryVerify(() => userPage.room._ensureStateEventPromises[1], 1000);
userPage.room._ensureStateEventPromises[1].resolve(true, {});
const editButton = findChild(userPage, 'editPowerLevelButton');
tryVerify(() => editButton.enabled);
mouseClick(editButton);
const textField = findChild(userPage, 'newPowerLevelInput');
tryVerify(() => textField.visible, 1000);
textField.text = '50';
const saveButton = findChild(userPage, 'savePowerLevelButton');
mouseClick(saveButton);
tryVerify(() => room._setUserPowerLevelPromise, 1000);
// Text field is not closed until the request succeeded
room._setUserPowerLevelPromise.resolve(false, {});
// text field is no longer readonly if failed
tryVerify(() => !textField.readOnly, 1000);
// show error message
verify(upper.lastNotification);
// the buttons are enabled when the request responded
verify(saveButton.enabled);
verify(findChild(userPage, 'discardPowerLevelButton').enabled);
}
/**
* The zz prefix is to allow this test to run after tst_powerlevel,
* which would otherwise fail for unknown reasons.
*/
function test_zzbanUser() {
// Ban user is only available if membership ! = "ban"
userPage.user = ({ membership: "join" });
const banButton = findChild(userPage, 'banUserButton');
verify(banButton.visible);
verify(banButton.enabled);
const reasonDialog = findChild(userPage, 'banUserReasonDialog');
verify(!reasonDialog.opened);
const textField = findChild(userPage, 'banUserReasonInput');
mouseClick(banButton);
verify(!reasonDialog.opened);
verify(textField.visible);
verify(!textField.readOnly);
textField.text = 'some reason';
reasonDialog.accept();
tryVerify(() => !reasonDialog.opened, 1000);
tryVerify(() => !banButton.enabled, 1000);
tryVerify(() => room._banUserPromise, 1000);
verify(room._banUserUserId === '@mew:example.com');
verify(room._banUserReason === 'some reason');
room._banUserPromise.resolve(true, {});
tryVerify(() => textField.text === '', 1000);
tryVerify(() => banButton.enabled, 1000);
}
function test_zzbanUserFailure() {
// Ban user is only available if membership ! = "ban"
userPage.user = ({ membership: "join" });
const banButton = findChild(userPage, 'banUserButton');
verify(banButton.visible);
verify(banButton.enabled);
const reasonDialog = findChild(userPage, 'banUserReasonDialog');
verify(!reasonDialog.opened);
const textField = findChild(userPage, 'banUserReasonInput');
mouseClick(banButton);
verify(!reasonDialog.opened);
verify(textField.visible);
verify(!textField.readOnly);
textField.text = 'some reason';
reasonDialog.accept();
tryVerify(() => !reasonDialog.opened, 1000);
tryVerify(() => !banButton.enabled, 1000);
tryVerify(() => room._banUserPromise, 1000);
verify(room._banUserUserId === '@mew:example.com');
verify(room._banUserReason === 'some reason');
room._banUserPromise.resolve(false, {});
tryVerify(() => upper.lastNotification, 1000);
// text field is not cleared when failed
tryVerify(() => textField.text === 'some reason', 1000);
tryVerify(() => banButton.enabled, 1000);
}
function test_unbanUser() {
// Unban user is only available if membership == "ban"
userPage.user = ({ membership: "ban" });
const unbanButton = findChild(userPage, 'unbanUserButton');
verify(unbanButton.visible);
verify(unbanButton.enabled);
mouseClick(unbanButton);
tryVerify(() => !unbanButton.enabled, 1000);
verify(room._unbanUserUserId == '@mew:example.com');
verify(room._unbanUserPromise);
room._unbanUserPromise.resolve(true, {});
tryVerify(() => unbanButton.enabled, 1000);
}
function test_unbanUserFailure() {
// Unban user is only available if membership == "ban"
userPage.user = ({ membership: "ban" });
const unbanButton = findChild(userPage, 'unbanUserButton');
verify(unbanButton.visible);
verify(unbanButton.enabled);
mouseClick(unbanButton);
tryVerify(() => !unbanButton.enabled, 1000);
verify(room._unbanUserUserId == '@mew:example.com');
verify(room._unbanUserPromise);
room._unbanUserPromise.resolve(false, {});
tryVerify(() => upper.lastNotification, 1000);
tryVerify(() => unbanButton.enabled, 1000);
}
}
function test_kickUser() {
const kickButton = findChild(userPage, 'kickUserButton');
verify(kickButton.visible);
verify(kickButton.enabled);
const reasonDialog = findChild(userPage, 'kickUserReasonDialog');
verify(!reasonDialog.opened);
const textField = findChild(userPage, 'kickUserReasonInput');
mouseClick(kickButton);
verify(!reasonDialog.opened);
verify(textField.visible);
verify(!textField.readOnly);
textField.text = 'some reason';
reasonDialog.accept();
tryVerify(() => !reasonDialog.opened, 1000);
tryVerify(() => !kickButton.enabled, 1000);
tryVerify(() => room._kickUserPromise, 1000);
verify(room._kickUserUserId === '@mew:example.com');
verify(room._kickUserReason === 'some reason');
room._kickUserPromise.resolve(true, {});
tryVerify(() => textField.text === '', 1000);
// still available only because this is a mock call, no real action
// is performed on the user
tryVerify(() => kickButton.enabled, 1000);
}
+
+ function test_overridedName() {
+ const input = findChild(userPage, 'nameOverrideInput');
+ compare(input.text, '');
+
+ gnMap.map = { '@mew:example.com': 'something' };
+ compare(input.text, 'something');
+
+ verify(!findChild(userPageSelf, 'nameOverrideInput').visible);
+ }
+
+ function test_updateOverridedName() {
+ const input = findChild(userPage, 'nameOverrideInput');
+ compare(input.text, '');
+ verify(input.enabled);
+ input.text = 'something';
+ const saveButton = findChild(userPage, 'saveNameOverrideButton');
+ verify(saveButton.enabled);
+ mouseClick(saveButton);
+ tryVerify(() => !input.enabled);
+ verify(!saveButton.enabled);
+ compare(gnMap._setAndUploadCalled, 1);
+ verify(TestHelpers.deepEqual(gnMap._setAndUploadArgs, ['@mew:example.com', 'something']));
+ gnMap._setAndUploadPromise.resolve(true, {});
+ tryVerify(() => input.enabled);
+ verify(saveButton.enabled);
+ }
+
+ function test_updateOverridedNameFailed() {
+ const input = findChild(userPage, 'nameOverrideInput');
+ compare(input.text, '');
+ verify(input.enabled);
+ input.text = 'something';
+ const saveButton = findChild(userPage, 'saveNameOverrideButton');
+ verify(saveButton.enabled);
+ mouseClick(saveButton);
+ tryVerify(() => !input.enabled);
+ verify(!saveButton.enabled);
+ compare(gnMap._setAndUploadCalled, 1);
+ verify(TestHelpers.deepEqual(gnMap._setAndUploadArgs, ['@mew:example.com', 'something']));
+ gnMap._setAndUploadPromise.resolve(false, {});
+ tryVerify(() => input.enabled);
+ verify(saveButton.enabled);
+ }
+
+ function test_removeOverridedName() {
+ gnMap.map = { '@mew:example.com': 'something' };
+ const input = findChild(userPage, 'nameOverrideInput');
+ compare(input.text, 'something');
+ input.text = '';
+ const saveButton = findChild(userPage, 'saveNameOverrideButton');
+ verify(saveButton.enabled);
+ mouseClick(saveButton);
+ tryVerify(() => !input.enabled);
+ verify(!saveButton.enabled);
+ compare(gnMap._setAndUploadCalled, 1);
+ verify(TestHelpers.deepEqual(gnMap._setAndUploadArgs, ['@mew:example.com', null]));
+ gnMap._setAndUploadPromise.resolve(true, {});
+ tryVerify(() => input.enabled);
+ verify(saveButton.enabled);
+ }
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Aug 9, 3:42 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1724680
Default Alt Text
(59 KB)

Event Timeline