diff --git a/src/contents/ui/room-settings/RoomSettingsPage.qml b/src/contents/ui/room-settings/RoomSettingsPage.qml --- a/src/contents/ui/room-settings/RoomSettingsPage.qml +++ b/src/contents/ui/room-settings/RoomSettingsPage.qml @@ -26,6 +26,27 @@ } property var roomDisplayName: roomNameProvider.name property var customTagIds: room.tagIds.filter(k => k.startsWith('u.')) + property var editingName: false + property var submittingName: false + property var submitName: Kazv.AsyncHandler { + trigger: () => { + roomSettingsPage.submittingName = true; + return roomSettingsPage.room.setName(roomNameEdit.text); + } + onResolved: (success, data) => { + roomSettingsPage.submittingName = false; + if (success) { + roomSettingsPage.editingName = false; + } else { + showPassiveNotification(l10n.get('room-settings-set-name-failed-prompt', { + room: room.roomId, + errorCode: data.errorCode, + errorMsg: data.error, + })); + } + } + } + property var editingTopic: false property var submittingTopic: false property var submitTopic: Kazv.AsyncHandler { @@ -129,17 +150,53 @@ ColumnLayout { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - Label { - objectName: 'roomNameLabel' - Layout.alignment: Qt.AlignHCenter - text: !!room.name ? room.name : room.roomId - } Label { objectName: 'roomIdLabel' Layout.alignment: Qt.AlignHCenter font: Kirigami.Theme.smallFont text: room.roomId - visible: !!room.name + } + } + RowLayout { + visible: !roomSettingsPage.editingName + Kazv.SelectableText { + objectName: 'roomNameLabel' + text: room.name || l10n.get('room-settings-name-missing') + wrapMode: Text.Wrap + Kirigami.Theme.colorGroup: !!room.name ? Kirigami.Theme.Normal : Kirigami.Theme.Inactive + Layout.fillWidth: true + } + Button { + Layout.alignment: Qt.AlignTop + objectName: 'editNameButton' + text: l10n.get('room-settings-edit-name-action') + onClicked: { + roomNameEdit.text = room.name; + roomSettingsPage.editingName = true; + } + } + } + RowLayout { + visible: roomSettingsPage.editingName + TextArea { + id: roomNameEdit + objectName: 'roomNameEdit' + Layout.fillWidth: true + wrapMode: Text.Wrap + } + Button { + Layout.alignment: Qt.AlignTop + objectName: 'saveNameButton' + enabled: !roomSettingsPage.submittingName + text: l10n.get('room-settings-save-name-action') + onClicked: roomSettingsPage.submitName.call() + } + Button { + Layout.alignment: Qt.AlignTop + objectName: 'discardNameButton' + enabled: !roomSettingsPage.submittingName + text: l10n.get('room-settings-discard-name-action') + onClicked: roomSettingsPage.editingName = false } } RowLayout { diff --git a/src/l10n/cmn-Hans/100-ui.ftl b/src/l10n/cmn-Hans/100-ui.ftl --- a/src/l10n/cmn-Hans/100-ui.ftl +++ b/src/l10n/cmn-Hans/100-ui.ftl @@ -106,10 +106,15 @@ room-settings-not-encrypted = 本房间中的消息没有端对端加密。 room-settings-encryption-enabled-notification = 本房间中的加密已经启用。 room-settings-encryption-failed-to-enable-notification = 不能在本房间中启用加密。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。 +room-settings-name-missing = 这个房间没有名字。 room-settings-topic-missing = 这个房间没有话题。 +room-settings-edit-name-action = 编辑房间名字 room-settings-edit-topic-action = 编辑话题 +room-settings-save-name-action = 保存房间名字 room-settings-save-topic-action = 保存话题 +room-settings-discard-name-action = 放弃房间名字 room-settings-discard-topic-action = 放弃话题 +room-settings-set-name-failed-prompt = 不能设置房间名字。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。 room-settings-set-topic-failed-prompt = 不能设置话题。错误代码:{ $errorCode }。错误讯息:{ $errorMsg }。 room-sticker-packs-action = 贴纸包... room-sticker-packs-page-title = { $room } 中的贴纸包 diff --git a/src/l10n/en/100-ui.ftl b/src/l10n/en/100-ui.ftl --- a/src/l10n/en/100-ui.ftl +++ b/src/l10n/en/100-ui.ftl @@ -110,10 +110,15 @@ 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-settings-name-missing = This room dose not have a name. room-settings-topic-missing = This room does not have a topic. +room-settings-edit-name-action = Edit name room-settings-edit-topic-action = Edit topic +room-settings-save-name-action = Save name room-settings-save-topic-action = Save topic +room-settings-discard-name-action = Discard name room-settings-discard-topic-action = Discard topic +room-settings-set-name-failed-prompt = Cannot set name. Error code: { $errorCode }. Error message: { $errorMsg }. room-settings-set-topic-failed-prompt = Cannot set topic. Error code: { $errorCode }. Error message: { $errorMsg }. room-sticker-packs-action = Sticker packs... room-sticker-packs-page-title = Sticker packs in { $room } diff --git a/src/matrix-room.hpp b/src/matrix-room.hpp --- a/src/matrix-room.hpp +++ b/src/matrix-room.hpp @@ -154,6 +154,8 @@ Q_INVOKABLE MatrixPromise *postReadReceipt(const QString &eventId) const; + Q_INVOKABLE MatrixPromise *setName(const QString &newName) const; + Q_INVOKABLE MatrixPromise *setTopic(const QString &newTopic) const; /** diff --git a/src/matrix-room.cpp b/src/matrix-room.cpp --- a/src/matrix-room.cpp +++ b/src/matrix-room.cpp @@ -564,6 +564,11 @@ return new MatrixPromise(m_room.postReceipt(eventId.toStdString())); } +MatrixPromise *MatrixRoom::setName(const QString &newName) const +{ + return new MatrixPromise(m_room.setName(newName.toStdString())); +} + MatrixPromise *MatrixRoom::setTopic(const QString &newTopic) const { return new MatrixPromise(m_room.setTopic(newTopic.toStdString())); diff --git a/src/tests/quick-tests/tst_RoomSettingsPage.qml b/src/tests/quick-tests/tst_RoomSettingsPage.qml --- a/src/tests/quick-tests/tst_RoomSettingsPage.qml +++ b/src/tests/quick-tests/tst_RoomSettingsPage.qml @@ -56,6 +56,7 @@ }, count: 5 }), + setName: mockHelper.promise(), }) property var roomWithoutName: Helpers.factory.room({ @@ -122,6 +123,7 @@ function initTestCase() { pageJoined.contentItem.clip = false; pageWithTopic.contentItem.clip = false; + pageWithMembers.contentItem.clip = false; } function init() { @@ -129,6 +131,8 @@ pageJoined.editingTopic = false; pageWithTopic.submittingTopic = false; pageWithTopic.editingTopic = false; + pageWithMembers.submittingName = false; + pageWithMembers.editingName = false; mockHelper.clearAll(); } @@ -200,14 +204,13 @@ const idLabel = findChild(pageWithMembers, 'roomIdLabel'); verify(nameLabel.text === 'some name'); verify(idLabel.text === '!someid:example.com'); - verify(idLabel.visible); } function test_roomWithoutName() { const nameLabel = findChild(pageWithoutName, 'roomNameLabel'); - const idLabel = findChild(pageWithoutName, 'roomIdLabel'); - verify(nameLabel.text === '!someid:example.com'); - verify(!idLabel.visible) + const idLabel = findChild(pageWithMembers, 'roomIdLabel'); + compare(nameLabel.text, l10n.get('room-settings-name-missing')); + compare(idLabel.text, '!someid:example.com'); } function test_roomWithoutTopic() { @@ -284,5 +287,60 @@ tryVerify(() => textArea.visible); verify(textArea.text === ''); } + + function test_editRoomName() { + const editButton = findChild(pageWithMembers, 'editNameButton'); + mouseClick(editButton); + const textArea = findChild(pageWithMembers, 'roomNameEdit'); + tryVerify(() => textArea.visible); + verify(textArea.text === 'some name'); + textArea.text = 'other name'; + const saveNameButton = findChild(pageWithMembers, 'saveNameButton'); + verify(saveNameButton.visible); + verify(saveNameButton.enabled); + const discardNameButton = findChild(pageWithMembers, 'discardNameButton'); + verify(discardNameButton.visible); + verify(discardNameButton.enabled); + mouseClick(saveNameButton); + tryVerify(() => roomWithMembers.setName.calledTimes() === 1); + compare(roomWithMembers.setName.lastArgs()[0], 'other name'); + verify(!saveNameButton.enabled); + verify(!discardNameButton.enabled); + + roomWithMembers.setName.lastRetVal().resolve(true, {}); + tryVerify(() => editButton.visible); + verify(!saveNameButton.visible); + } + + function test_editRoomNameFailed() { + const editButton = findChild(pageWithMembers, 'editNameButton'); + mouseClick(editButton); + const textArea = findChild(pageWithMembers, 'roomNameEdit'); + tryVerify(() => textArea.visible); + verify(textArea.text === 'some name'); + textArea.text = 'other name'; + const saveNameButton = findChild(pageWithMembers, 'saveNameButton'); + mouseClick(saveNameButton); + tryVerify(() => roomWithMembers.setName.calledTimes() === 1); + roomWithMembers.setName.lastRetVal().resolve(false, {}); + verify(saveNameButton.enabled); + verify(textArea.visible); + } + + function test_editRoomNameDiscard() { + const editButton = findChild(pageWithMembers, 'editNameButton'); + mouseClick(editButton); + const textArea = findChild(pageWithMembers, 'roomNameEdit'); + tryVerify(() => textArea.visible); + verify(textArea.text === 'some name'); + textArea.text = 'other name'; + const discardNameButton = findChild(pageWithMembers, 'discardNameButton'); + mouseClick(discardNameButton); + compare(roomWithMembers.setName.calledTimes(), 0); + verify(!textArea.visible); + mouseClick(editButton); + tryVerify(() => textArea.visible); + verify(textArea.text === 'some name'); + } } }