Make room settings pane scrollable
The new Base/ButtonLayout components will be used in the near future to refactor other HBox-based components
This commit is contained in:
parent
48faac9a32
commit
3314489a26
|
@ -62,6 +62,8 @@ and this project adheres to
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- The room settings pane is now scrollable
|
||||||
|
|
||||||
- Avoid potential error if the room list data model is initialized after an
|
- Avoid potential error if the room list data model is initialized after an
|
||||||
initial sync has already been completed
|
initial sync has already been completed
|
||||||
|
|
||||||
|
|
13
TODO.md
13
TODO.md
|
@ -3,7 +3,6 @@
|
||||||
## Refactoring
|
## Refactoring
|
||||||
|
|
||||||
- Rewrite account settings using `HTabbedContainer`
|
- Rewrite account settings using `HTabbedContainer`
|
||||||
- Get rid of all `currentSpacing` stuff
|
|
||||||
- Use new default/reset controls system
|
- Use new default/reset controls system
|
||||||
- Display name field text should be colored
|
- Display name field text should be colored
|
||||||
|
|
||||||
|
@ -16,9 +15,13 @@
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
- Don't send typing notification when switching to a room where the composer
|
- 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
|
- `TextArea`s in Popups grow past window height instead of being scrollable
|
||||||
|
|
||||||
- Jumping between accounts (clicking in account bar or alt+(Shift+)N) is
|
- 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
|
- 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
|
- `code`, mentions and links in quote ("> http://example.com") aren't properly
|
||||||
in room "last message" subtitle
|
colored in room delegate "last message" subtitle
|
||||||
|
|
||||||
- `Timer` and `Animation` are bound to framerate
|
- `Timer` and `Animation` are bound to framerate
|
||||||
- Can't use `QQmlApplicationEngine`, problem with QApplication?
|
- Can't use `QQmlApplicationEngine`, problem with QApplication?
|
||||||
|
|
14
src/gui/Base/ButtonLayout/ApplyButton.qml
Normal file
14
src/gui/Base/ButtonLayout/ApplyButton.qml
Normal file
|
@ -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
|
||||||
|
}
|
23
src/gui/Base/ButtonLayout/ButtonLayout.qml
Normal file
23
src/gui/Base/ButtonLayout/ButtonLayout.qml
Normal file
|
@ -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
|
||||||
|
}
|
14
src/gui/Base/ButtonLayout/CancelButton.qml
Normal file
14
src/gui/Base/ButtonLayout/CancelButton.qml
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -103,8 +103,6 @@ Rectangle {
|
||||||
Keys.onUpPressed: previous.forceActiveFocus()
|
Keys.onUpPressed: previous.forceActiveFocus()
|
||||||
Keys.onRightPressed: next.forceActiveFocus()
|
Keys.onRightPressed: next.forceActiveFocus()
|
||||||
Keys.onDownPressed: next.forceActiveFocus()
|
Keys.onDownPressed: next.forceActiveFocus()
|
||||||
Keys.onReturnPressed: if (button.enabled) button.clicked()
|
|
||||||
Keys.onEnterPressed: Keys.onReturnPressed(event)
|
|
||||||
|
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
if (name === focusButton) forceActiveFocus()
|
if (name === focusButton) forceActiveFocus()
|
||||||
|
|
|
@ -41,6 +41,10 @@ Button {
|
||||||
buttonTheme: theme.controls.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 iconItem: contentItem.icon
|
||||||
readonly property alias label: contentItem.label
|
readonly property alias label: contentItem.label
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
|
|
||||||
HPage {
|
HPage {
|
||||||
|
id: page
|
||||||
|
|
||||||
|
|
||||||
default property alias columnData: column.data
|
default property alias columnData: column.data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,16 @@ import QtQuick 2.12
|
||||||
import "../ShortcutBundles"
|
import "../ShortcutBundles"
|
||||||
|
|
||||||
HPage {
|
HPage {
|
||||||
property alias flickable: flickable
|
id: page
|
||||||
|
|
||||||
|
|
||||||
default property alias columnData: column.data
|
default property alias columnData: column.data
|
||||||
|
property alias column: column
|
||||||
|
property alias flickable: flickable
|
||||||
|
property alias flickShortcuts: flickShortcuts
|
||||||
|
|
||||||
|
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
|
||||||
HFlickable {
|
HFlickable {
|
||||||
|
@ -16,14 +24,20 @@ HPage {
|
||||||
contentHeight: column.childrenRect.height
|
contentHeight: column.childrenRect.height
|
||||||
|
|
||||||
FlickShortcuts {
|
FlickShortcuts {
|
||||||
|
id: flickShortcuts
|
||||||
active: ! mainUI.debugConsole.visible
|
active: ! mainUI.debugConsole.visible
|
||||||
flickable: flickable
|
flickable: flickable
|
||||||
}
|
}
|
||||||
|
|
||||||
HColumnLayout {
|
HColumnLayout {
|
||||||
id: column
|
id: column
|
||||||
width: flickable.width
|
x: padding
|
||||||
height: flickable.height
|
y: padding
|
||||||
|
width: flickable.width - padding * 2
|
||||||
|
height: flickable.height - padding * 2
|
||||||
|
|
||||||
|
property int padding:
|
||||||
|
page.currentSpacing < theme.spacing ? 0 : page.currentSpacing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,17 @@ import QtQuick 2.12
|
||||||
import QtQuick.Controls 2.12
|
import QtQuick.Controls 2.12
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
leftPadding: currentSpacing < theme.spacing ? 0 : currentSpacing
|
padding: currentSpacing < theme.spacing ? 0 : currentSpacing
|
||||||
rightPadding: leftPadding
|
|
||||||
background: null
|
background: null
|
||||||
|
|
||||||
|
|
||||||
|
property bool useVariableSpacing: true
|
||||||
|
|
||||||
property int currentSpacing:
|
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 {} }
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ Item {
|
||||||
readonly property alias loader: loader
|
readonly property alias loader: loader
|
||||||
readonly property alias roomPane: roomPaneLoader.item
|
readonly property alias roomPane: roomPaneLoader.item
|
||||||
|
|
||||||
|
readonly property bool composerHasFocus:
|
||||||
|
Boolean(loader.item && loader.item.composer.hasFocus)
|
||||||
|
|
||||||
|
|
||||||
HShortcut {
|
HShortcut {
|
||||||
sequences: window.settings.keys.leaveRoom
|
sequences: window.settings.keys.leaveRoom
|
||||||
|
|
|
@ -10,8 +10,7 @@ import "Timeline"
|
||||||
|
|
||||||
HColumnPage {
|
HColumnPage {
|
||||||
id: chatPage
|
id: chatPage
|
||||||
leftPadding: 0
|
padding: 0
|
||||||
rightPadding: 0
|
|
||||||
|
|
||||||
onLoadEventListChanged: if (loadEventList) loadedOnce = true
|
onLoadEventListChanged: if (loadEventList) loadedOnce = true
|
||||||
Component.onDestruction: if (loadMembersFuture) loadMembersFuture.cancel()
|
Component.onDestruction: if (loadMembersFuture) loadMembersFuture.cancel()
|
||||||
|
|
|
@ -7,6 +7,7 @@ import "../../../Base"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
property alias eventList: messageArea.eventList
|
property alias eventList: messageArea.eventList
|
||||||
|
readonly property bool hasFocus: messageArea.activeFocus
|
||||||
|
|
||||||
|
|
||||||
function takeFocus() { messageArea.forceActiveFocus() }
|
function takeFocus() { messageArea.forceActiveFocus() }
|
||||||
|
|
|
@ -76,7 +76,7 @@ MultiviewPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberView {}
|
MemberView {}
|
||||||
SettingsView { fillAvailableHeight: true }
|
SettingsView {}
|
||||||
|
|
||||||
HShortcut {
|
HShortcut {
|
||||||
sequences: window.settings.keys.toggleFocusRoomPane
|
sequences: window.settings.keys.toggleFocusRoomPane
|
||||||
|
|
|
@ -3,29 +3,20 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.12
|
||||||
import "../../../Base"
|
import "../../../Base"
|
||||||
|
import "../../../Base/ButtonLayout"
|
||||||
|
|
||||||
HBox {
|
HFlickableColumnPage {
|
||||||
color: theme.chat.roomPane.roomSettings.background
|
property var saveFuture: null
|
||||||
|
|
||||||
buttonModel: [
|
readonly property bool anyChange:
|
||||||
{
|
nameField.item.changed || topicArea.item.changed ||
|
||||||
name: "apply",
|
encryptCheckBox.changed || requireInviteCheckbox.changed ||
|
||||||
text: qsTr("Save"),
|
forbidGuestsCheckBox.changed
|
||||||
iconName: "apply",
|
|
||||||
enabled: anyChange,
|
|
||||||
loading: saveFuture !== null,
|
|
||||||
disableWhileLoading: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "cancel",
|
|
||||||
text: qsTr("Cancel"),
|
|
||||||
iconName: "cancel",
|
|
||||||
enabled: anyChange || saveFuture !== null,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
buttonCallbacks: ({
|
readonly property Item keybindFocusItem: nameField.item
|
||||||
apply: button => {
|
|
||||||
|
|
||||||
|
function save() {
|
||||||
if (saveFuture) saveFuture.cancel()
|
if (saveFuture) saveFuture.cancel()
|
||||||
|
|
||||||
const args = [
|
const args = [
|
||||||
|
@ -46,9 +37,9 @@ HBox {
|
||||||
saveFuture = py.callClientCoro(
|
saveFuture = py.callClientCoro(
|
||||||
chat.userId, "room_set", args, onDone, onDone,
|
chat.userId, "room_set", args, onDone, onDone,
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
cancel: button => {
|
function cancel() {
|
||||||
if (saveFuture) {
|
if (saveFuture) {
|
||||||
saveFuture.cancel()
|
saveFuture.cancel()
|
||||||
saveFuture = null
|
saveFuture = null
|
||||||
|
@ -59,18 +50,33 @@ HBox {
|
||||||
encryptCheckBox.reset()
|
encryptCheckBox.reset()
|
||||||
requireInviteCheckbox.reset()
|
requireInviteCheckbox.reset()
|
||||||
forbidGuestsCheckBox.reset()
|
forbidGuestsCheckBox.reset()
|
||||||
},
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
property var saveFuture: null
|
useVariableSpacing: false
|
||||||
|
column.spacing: theme.spacing * 1.5
|
||||||
|
|
||||||
readonly property bool anyChange:
|
flickShortcuts.active:
|
||||||
nameField.item.changed || topicArea.item.changed ||
|
! mainUI.debugConsole.visible && ! chat.composerHasFocus
|
||||||
encryptCheckBox.changed || requireInviteCheckbox.changed ||
|
|
||||||
forbidGuestsCheckBox.changed
|
|
||||||
|
|
||||||
readonly property Item keybindFocusItem: nameField.item
|
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 {
|
HRoomAvatar {
|
||||||
|
@ -108,6 +114,7 @@ HBox {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
HTextArea {
|
HTextArea {
|
||||||
|
// TODO: limit height
|
||||||
width: parent.width
|
width: parent.width
|
||||||
placeholderText: qsTr("This room is about...")
|
placeholderText: qsTr("This room is about...")
|
||||||
defaultText: chat.roomInfo.plain_topic
|
defaultText: chat.roomInfo.plain_topic
|
||||||
|
|
|
@ -175,7 +175,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
FlickShortcuts {
|
FlickShortcuts {
|
||||||
active: ! mainUI.debugConsole.visible
|
active: chat.composerHasFocus
|
||||||
flickable: eventList
|
flickable: eventList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user