diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8336e2..abee9f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,8 @@ and this project adheres to ### Fixed +- The room settings pane is now scrollable + - Avoid potential error if the room list data model is initialized after an initial sync has already been completed diff --git a/TODO.md b/TODO.md index 872e9c77..d91767c7 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,6 @@ ## Refactoring - Rewrite account settings using `HTabbedContainer` - - Get rid of all `currentSpacing` stuff - Use new default/reset controls system - Display name field text should be colored @@ -16,9 +15,13 @@ ## Issues - Don't send typing notification when switching to a room where the composer - has loaded text + has preloaded text -- Popups and room settings can't be scrolled when not enough height to show all +- When calling `Backend.update_room_read_marker()` for a recent message, + the marker will only be updated for accounts that have already received + it (server lag) + +- Popups can't be scrolled when not enough height to show all - `TextArea`s in Popups grow past window height instead of being scrollable - Jumping between accounts (clicking in account bar or alt+(Shift+)N) is @@ -37,8 +40,8 @@ - After forgetting a room, it comes back because of the "you left" event -- `code` and links in quote ("> http://example.com") aren't properly colored - in room "last message" subtitle +- `code`, mentions and links in quote ("> http://example.com") aren't properly + colored in room delegate "last message" subtitle - `Timer` and `Animation` are bound to framerate - Can't use `QQmlApplicationEngine`, problem with QApplication? diff --git a/src/gui/Base/ButtonLayout/ApplyButton.qml b/src/gui/Base/ButtonLayout/ApplyButton.qml new file mode 100644 index 00000000..89c8bc05 --- /dev/null +++ b/src/gui/Base/ButtonLayout/ApplyButton.qml @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import ".." + +HButton { + implicitHeight: theme.baseElementsHeight + text: qsTr("Apply") + icon.name: "apply" + icon.color: theme.colors.positiveBackground + + Layout.fillWidth: true +} diff --git a/src/gui/Base/ButtonLayout/ButtonLayout.qml b/src/gui/Base/ButtonLayout/ButtonLayout.qml new file mode 100644 index 00000000..818a9ff7 --- /dev/null +++ b/src/gui/Base/ButtonLayout/ButtonLayout.qml @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import ".." + +HGridLayout { + readonly property int summedImplicitWidth: { + const widths = [] + + for (let i = 0; i < visibleChildren.length; i++) { + const item = visibleChildren[i] + if (item) widths.push(item.width > 0 ? item.implicitWidth : 0) + } + + return utils.sum(widths) + } + + flow: + width >= summedImplicitWidth ? + GridLayout.LeftToRight : + GridLayout.TopToBottom +} diff --git a/src/gui/Base/ButtonLayout/CancelButton.qml b/src/gui/Base/ButtonLayout/CancelButton.qml new file mode 100644 index 00000000..fa53c69e --- /dev/null +++ b/src/gui/Base/ButtonLayout/CancelButton.qml @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import ".." + +HButton { + implicitHeight: theme.baseElementsHeight + text: qsTr("Cancel") + icon.name: "cancel" + icon.color: theme.colors.negativeBackground + + Layout.fillWidth: true +} diff --git a/src/gui/Base/HBox.qml b/src/gui/Base/HBox.qml index dbf73661..4d5846c9 100644 --- a/src/gui/Base/HBox.qml +++ b/src/gui/Base/HBox.qml @@ -103,8 +103,6 @@ Rectangle { Keys.onUpPressed: previous.forceActiveFocus() Keys.onRightPressed: next.forceActiveFocus() Keys.onDownPressed: next.forceActiveFocus() - Keys.onReturnPressed: if (button.enabled) button.clicked() - Keys.onEnterPressed: Keys.onReturnPressed(event) Component.onCompleted: if (name === focusButton) forceActiveFocus() diff --git a/src/gui/Base/HButton.qml b/src/gui/Base/HButton.qml index 10e635db..c1deed1d 100644 --- a/src/gui/Base/HButton.qml +++ b/src/gui/Base/HButton.qml @@ -41,6 +41,10 @@ Button { buttonTheme: theme.controls.button } + Keys.onReturnPressed: if (enabled) clicked() + Keys.onEnterPressed: Keys.onReturnPressed(event) + activeFocusOnTab: true + readonly property alias iconItem: contentItem.icon readonly property alias label: contentItem.label diff --git a/src/gui/Base/HColumnPage.qml b/src/gui/Base/HColumnPage.qml index b4320445..f640b7d2 100644 --- a/src/gui/Base/HColumnPage.qml +++ b/src/gui/Base/HColumnPage.qml @@ -3,6 +3,9 @@ import QtQuick 2.12 HPage { + id: page + + default property alias columnData: column.data diff --git a/src/gui/Base/HFlickableColumnPage.qml b/src/gui/Base/HFlickableColumnPage.qml index 28f51d6e..a8394175 100644 --- a/src/gui/Base/HFlickableColumnPage.qml +++ b/src/gui/Base/HFlickableColumnPage.qml @@ -4,8 +4,16 @@ import QtQuick 2.12 import "../ShortcutBundles" HPage { - property alias flickable: flickable + id: page + + default property alias columnData: column.data + property alias column: column + property alias flickable: flickable + property alias flickShortcuts: flickShortcuts + + + padding: 0 HFlickable { @@ -16,14 +24,20 @@ HPage { contentHeight: column.childrenRect.height FlickShortcuts { + id: flickShortcuts active: ! mainUI.debugConsole.visible flickable: flickable } HColumnLayout { id: column - width: flickable.width - height: flickable.height + x: padding + y: padding + width: flickable.width - padding * 2 + height: flickable.height - padding * 2 + + property int padding: + page.currentSpacing < theme.spacing ? 0 : page.currentSpacing } } diff --git a/src/gui/Base/HPage.qml b/src/gui/Base/HPage.qml index 9f9deccb..419319f1 100644 --- a/src/gui/Base/HPage.qml +++ b/src/gui/Base/HPage.qml @@ -4,14 +4,17 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 Page { - leftPadding: currentSpacing < theme.spacing ? 0 : currentSpacing - rightPadding: leftPadding + padding: currentSpacing < theme.spacing ? 0 : currentSpacing background: null + property bool useVariableSpacing: true + property int currentSpacing: - Math.min(theme.spacing * width / 400, theme.spacing) + useVariableSpacing ? + Math.min(theme.spacing * width / 400, theme.spacing) : + theme.spacing - Behavior on leftPadding { HNumberAnimation {} } + Behavior on padding { HNumberAnimation {} } } diff --git a/src/gui/Pages/Chat/Chat.qml b/src/gui/Pages/Chat/Chat.qml index 0415c17f..11b09efb 100644 --- a/src/gui/Pages/Chat/Chat.qml +++ b/src/gui/Pages/Chat/Chat.qml @@ -29,6 +29,9 @@ Item { readonly property alias loader: loader readonly property alias roomPane: roomPaneLoader.item + readonly property bool composerHasFocus: + Boolean(loader.item && loader.item.composer.hasFocus) + HShortcut { sequences: window.settings.keys.leaveRoom diff --git a/src/gui/Pages/Chat/ChatPage.qml b/src/gui/Pages/Chat/ChatPage.qml index 5d62d61d..34d000d9 100644 --- a/src/gui/Pages/Chat/ChatPage.qml +++ b/src/gui/Pages/Chat/ChatPage.qml @@ -10,8 +10,7 @@ import "Timeline" HColumnPage { id: chatPage - leftPadding: 0 - rightPadding: 0 + padding: 0 onLoadEventListChanged: if (loadEventList) loadedOnce = true Component.onDestruction: if (loadMembersFuture) loadMembersFuture.cancel() diff --git a/src/gui/Pages/Chat/Composer/Composer.qml b/src/gui/Pages/Chat/Composer/Composer.qml index 667afa63..94e2033d 100644 --- a/src/gui/Pages/Chat/Composer/Composer.qml +++ b/src/gui/Pages/Chat/Composer/Composer.qml @@ -7,6 +7,7 @@ import "../../../Base" Rectangle { property alias eventList: messageArea.eventList + readonly property bool hasFocus: messageArea.activeFocus function takeFocus() { messageArea.forceActiveFocus() } diff --git a/src/gui/Pages/Chat/RoomPane/RoomPane.qml b/src/gui/Pages/Chat/RoomPane/RoomPane.qml index 7c16fefe..5e90a25a 100644 --- a/src/gui/Pages/Chat/RoomPane/RoomPane.qml +++ b/src/gui/Pages/Chat/RoomPane/RoomPane.qml @@ -76,7 +76,7 @@ MultiviewPane { } MemberView {} - SettingsView { fillAvailableHeight: true } + SettingsView {} HShortcut { sequences: window.settings.keys.toggleFocusRoomPane diff --git a/src/gui/Pages/Chat/RoomPane/SettingsView.qml b/src/gui/Pages/Chat/RoomPane/SettingsView.qml index 4b87bea1..939f58e8 100644 --- a/src/gui/Pages/Chat/RoomPane/SettingsView.qml +++ b/src/gui/Pages/Chat/RoomPane/SettingsView.qml @@ -3,66 +3,9 @@ import QtQuick 2.12 import QtQuick.Layouts 1.12 import "../../../Base" +import "../../../Base/ButtonLayout" -HBox { - color: theme.chat.roomPane.roomSettings.background - - buttonModel: [ - { - name: "apply", - text: qsTr("Save"), - iconName: "apply", - enabled: anyChange, - loading: saveFuture !== null, - disableWhileLoading: false, - }, - { - name: "cancel", - text: qsTr("Cancel"), - iconName: "cancel", - enabled: anyChange || saveFuture !== null, - }, - ] - - buttonCallbacks: ({ - apply: button => { - if (saveFuture) saveFuture.cancel() - - const args = [ - chat.roomId, - nameField.item.changed ? nameField.item.text : undefined, - topicArea.item.changed ? topicArea.item.text : undefined, - encryptCheckBox.changed ? true : undefined, - - requireInviteCheckbox.changed ? - requireInviteCheckbox.checked : undefined, - - forbidGuestsCheckBox.changed ? - forbidGuestsCheckBox.checked : undefined, - ] - - function onDone() { saveFuture = null } - - saveFuture = py.callClientCoro( - chat.userId, "room_set", args, onDone, onDone, - ) - }, - - cancel: button => { - if (saveFuture) { - saveFuture.cancel() - saveFuture = null - } - - nameField.item.reset() - topicArea.item.reset() - encryptCheckBox.reset() - requireInviteCheckbox.reset() - forbidGuestsCheckBox.reset() - }, - }) - - +HFlickableColumnPage { property var saveFuture: null readonly property bool anyChange: @@ -73,6 +16,69 @@ HBox { readonly property Item keybindFocusItem: nameField.item + function save() { + if (saveFuture) saveFuture.cancel() + + const args = [ + chat.roomId, + nameField.item.changed ? nameField.item.text : undefined, + topicArea.item.changed ? topicArea.item.text : undefined, + encryptCheckBox.changed ? true : undefined, + + requireInviteCheckbox.changed ? + requireInviteCheckbox.checked : undefined, + + forbidGuestsCheckBox.changed ? + forbidGuestsCheckBox.checked : undefined, + ] + + function onDone() { saveFuture = null } + + saveFuture = py.callClientCoro( + chat.userId, "room_set", args, onDone, onDone, + ) + } + + function cancel() { + if (saveFuture) { + saveFuture.cancel() + saveFuture = null + } + + nameField.item.reset() + topicArea.item.reset() + encryptCheckBox.reset() + requireInviteCheckbox.reset() + forbidGuestsCheckBox.reset() + } + + + useVariableSpacing: false + column.spacing: theme.spacing * 1.5 + + flickShortcuts.active: + ! mainUI.debugConsole.visible && ! chat.composerHasFocus + + background: Rectangle { + color: theme.chat.roomPane.roomSettings.background + } + + footer: ButtonLayout { + ApplyButton { + enabled: anyChange + loading: saveFuture !== null + disableWhileLoading: false + onClicked: save() + + } + + CancelButton { + enabled: anyChange || saveFuture !== null + onClicked: cancel() + } + } + + HRoomAvatar { id: avatar roomId: chat.roomId @@ -108,6 +114,7 @@ HBox { Layout.fillWidth: true HTextArea { + // TODO: limit height width: parent.width placeholderText: qsTr("This room is about...") defaultText: chat.roomInfo.plain_topic diff --git a/src/gui/Pages/Chat/Timeline/EventList.qml b/src/gui/Pages/Chat/Timeline/EventList.qml index afa01eaa..3bb17fb0 100644 --- a/src/gui/Pages/Chat/Timeline/EventList.qml +++ b/src/gui/Pages/Chat/Timeline/EventList.qml @@ -175,7 +175,7 @@ Rectangle { } FlickShortcuts { - active: ! mainUI.debugConsole.visible + active: chat.composerHasFocus flickable: eventList }