Fix focus and simplify popup-opener menu items
Introduce a HmenuItemPopupSpawner component that takes care of reacting to onTriggered signals and calling the utils.makePopup() function. The combination of this new component used in HMenu to open a HPopup now correctly takes and restore focus to the right element when closed.
This commit is contained in:
parent
d9b7118f45
commit
9bd739a0db
10
TODO.md
10
TODO.md
|
@ -48,13 +48,13 @@
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
- invisible uploaded mxc images?
|
- `EventImage`s for `m.image` sometimes appear broken, can be made normal
|
||||||
- first undecryptable message
|
by switching to another room and coming back
|
||||||
- Join button 502
|
- First sent message in E2E room is sometimes undecryptable
|
||||||
- Leave box button focus
|
- Handle matrix errors for accept/decline invite buttons and other
|
||||||
|
|
||||||
|
- Pause upload, switch to other room, then come back → wrong state displayed
|
||||||
- Pausing uploads doesn't work well, servers end up dropping the connection
|
- Pausing uploads doesn't work well, servers end up dropping the connection
|
||||||
- Pause upload, switch to other room, then come back, wrong state displayed
|
|
||||||
|
|
||||||
- In the "Leave me" room, "join > Hi > left" aren't combined
|
- In the "Leave me" room, "join > Hi > left" aren't combined
|
||||||
- When selecting text and scrolling up, selection stops working after a while
|
- When selecting text and scrolling up, selection stops working after a while
|
||||||
|
|
|
@ -25,9 +25,17 @@ Menu {
|
||||||
border.width: theme.controls.menu.borderWidth
|
border.width: theme.controls.menu.borderWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
onAboutToShow: previouslyFocused = window.activeFocusItem
|
onAboutToShow: {
|
||||||
onClosed: if (previouslyFocused) previouslyFocused.forceActiveFocus()
|
previouslyFocused = window.activeFocusItem
|
||||||
|
focusOnClosed = Qt.binding(() => previouslyFocused)
|
||||||
|
}
|
||||||
|
onClosed: if (focusOnClosed) focusOnClosed.forceActiveFocus()
|
||||||
|
|
||||||
|
|
||||||
property var previouslyFocused: null
|
property var previouslyFocused: null
|
||||||
|
|
||||||
|
// MenuItems that open popups (or other elements taking focus when opened)
|
||||||
|
// should set this to null. It will be reset to previouslyFocus when
|
||||||
|
// the Menu is closed and opened again.
|
||||||
|
property Item focusOnClosed: previouslyFocused
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,6 @@ MenuItem {
|
||||||
bottomPadding: topPadding
|
bottomPadding: topPadding
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
|
|
||||||
|
|
||||||
readonly property alias iconItem: contentItem.icon
|
|
||||||
readonly property alias label: contentItem.label
|
|
||||||
|
|
||||||
|
|
||||||
background: HButtonBackground {
|
background: HButtonBackground {
|
||||||
button: menuItem
|
button: menuItem
|
||||||
buttonTheme: theme.controls.menuItem
|
buttonTheme: theme.controls.menuItem
|
||||||
|
@ -28,4 +23,8 @@ MenuItem {
|
||||||
buttonTheme: theme.controls.menuItem
|
buttonTheme: theme.controls.menuItem
|
||||||
label.horizontalAlignment: Label.AlignLeft
|
label.horizontalAlignment: Label.AlignLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
readonly property alias iconItem: contentItem.icon
|
||||||
|
readonly property alias label: contentItem.label
|
||||||
}
|
}
|
||||||
|
|
27
src/gui/Base/HMenuItemPopupSpawner.qml
Normal file
27
src/gui/Base/HMenuItemPopupSpawner.qml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Controls 2.12
|
||||||
|
|
||||||
|
HMenuItem {
|
||||||
|
onTriggered: {
|
||||||
|
print( parent.parent.parent)
|
||||||
|
menu.focusOnClosed = null
|
||||||
|
|
||||||
|
utils.makePopup(
|
||||||
|
popup,
|
||||||
|
popupParent,
|
||||||
|
utils.objectUpdate(
|
||||||
|
{ focusOnClosed: menu.previouslyFocused }, properties,
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
autoDestruct,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
property var popup // url or HPopup Component
|
||||||
|
property QtObject popupParent: window
|
||||||
|
property bool autoDestruct: true
|
||||||
|
property var properties: ({})
|
||||||
|
}
|
|
@ -24,10 +24,11 @@ Popup {
|
||||||
}
|
}
|
||||||
|
|
||||||
onAboutToShow: previouslyFocused = window.activeFocusItem
|
onAboutToShow: previouslyFocused = window.activeFocusItem
|
||||||
onClosed: if (previouslyFocused) previouslyFocused.forceActiveFocus()
|
onClosed: if (focusOnClosed) focusOnClosed.forceActiveFocus()
|
||||||
|
|
||||||
|
|
||||||
property var previouslyFocused: null
|
property var previouslyFocused: null
|
||||||
|
property Item focusOnClosed: previouslyFocused
|
||||||
|
|
||||||
readonly property int maximumPreferredWidth:
|
readonly property int maximumPreferredWidth:
|
||||||
window.width - leftMargin - rightMargin - leftInset - rightInset
|
window.width - leftMargin - rightMargin - leftInset - rightInset
|
||||||
|
|
|
@ -110,15 +110,13 @@ HTileDelegate {
|
||||||
onTriggered: Clipboard.text = model.data.user_id
|
onTriggered: Clipboard.text = model.data.user_id
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItemPopupSpawner {
|
||||||
icon.name: "sign-out"
|
icon.name: "sign-out"
|
||||||
icon.color: theme.colors.negativeBackground
|
icon.color: theme.colors.negativeBackground
|
||||||
text: qsTr("Sign out")
|
text: qsTr("Sign out")
|
||||||
onTriggered: utils.makePopup(
|
|
||||||
"Popups/SignOutPopup.qml",
|
popup: "Popups/SignOutPopup.qml"
|
||||||
window,
|
properties: { "userId": model.data.user_id }
|
||||||
{ "userId": model.data.user_id },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,22 +91,19 @@ HTileDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
contextMenu: HMenu {
|
contextMenu: HMenu {
|
||||||
HMenuItem {
|
HMenuItemPopupSpawner {
|
||||||
visible: joined
|
visible: joined
|
||||||
enabled: model.data.can_invite
|
enabled: model.data.can_invite
|
||||||
icon.name: "room-send-invite"
|
icon.name: "room-send-invite"
|
||||||
text: qsTr("Invite members")
|
text: qsTr("Invite members")
|
||||||
|
|
||||||
onTriggered: utils.makePopup(
|
popup: "Popups/InviteToRoomPopup.qml"
|
||||||
"Popups/InviteToRoomPopup.qml",
|
properties: ({
|
||||||
window,
|
|
||||||
{
|
|
||||||
userId: model.user_id,
|
userId: model.user_id,
|
||||||
roomId: model.data.room_id,
|
roomId: model.data.room_id,
|
||||||
roomName: model.data.display_name,
|
roomName: model.data.display_name,
|
||||||
invitingAllowed: Qt.binding(() => model.data.can_invite)
|
invitingAllowed: Qt.binding(() => model.data.can_invite)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItem {
|
||||||
|
@ -129,39 +126,32 @@ HTileDelegate {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItemPopupSpawner {
|
||||||
visible: invited || joined
|
visible: invited || joined
|
||||||
icon.name: invited ? "invite-decline" : "room-leave"
|
icon.name: invited ? "invite-decline" : "room-leave"
|
||||||
icon.color: theme.colors.negativeBackground
|
icon.color: theme.colors.negativeBackground
|
||||||
text: invited ? qsTr("Decline invite") : qsTr("Leave")
|
text: invited ? qsTr("Decline invite") : qsTr("Leave")
|
||||||
|
|
||||||
onTriggered: utils.makePopup(
|
popup: "Popups/LeaveRoomPopup.qml"
|
||||||
"Popups/LeaveRoomPopup.qml",
|
properties: ({
|
||||||
window,
|
|
||||||
{
|
|
||||||
userId: model.user_id,
|
userId: model.user_id,
|
||||||
roomId: model.data.room_id,
|
roomId: model.data.room_id,
|
||||||
roomName: model.data.display_name,
|
roomName: model.data.display_name,
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItemPopupSpawner {
|
||||||
icon.name: "room-forget"
|
icon.name: "room-forget"
|
||||||
icon.color: theme.colors.negativeBackground
|
icon.color: theme.colors.negativeBackground
|
||||||
text: qsTr("Forget")
|
text: qsTr("Forget")
|
||||||
|
|
||||||
onTriggered: utils.makePopup(
|
popup: "Popups/ForgetRoomPopup.qml"
|
||||||
"Popups/ForgetRoomPopup.qml",
|
autoDestruct: false
|
||||||
window,
|
properties: ({
|
||||||
{
|
|
||||||
userId: model.user_id,
|
userId: model.user_id,
|
||||||
roomId: model.data.room_id,
|
roomId: model.data.room_id,
|
||||||
roomName: model.data.display_name,
|
roomName: model.data.display_name,
|
||||||
},
|
})
|
||||||
null,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,14 +170,13 @@ HColumnLayout {
|
||||||
Clipboard.text = selectableLabelContainer.joinedSelection
|
Clipboard.text = selectableLabelContainer.joinedSelection
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItemPopupSpawner {
|
||||||
icon.name: "clear-messages"
|
icon.name: "clear-messages"
|
||||||
text: qsTr("Clear messages")
|
text: qsTr("Clear messages")
|
||||||
onTriggered: utils.makePopup(
|
|
||||||
"Popups/ClearMessagesPopup.qml",
|
popup: "Popups/ClearMessagesPopup.qml"
|
||||||
chat,
|
popupParent: chat
|
||||||
{userId: chat.userId, roomId: chat.roomId},
|
properties: ({userId: chat.userId, roomId: chat.roomId})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,11 @@ QtObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function objectUpdate(current, update) {
|
||||||
|
return Object.assign({}, current, update)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function objectUpdateRecursive(current, update) {
|
function objectUpdateRecursive(current, update) {
|
||||||
for (const key of Object.keys(update)) {
|
for (const key of Object.keys(update)) {
|
||||||
if ((key in current) && typeof(current[key]) === "object" &&
|
if ((key in current) && typeof(current[key]) === "object" &&
|
||||||
|
|
Loading…
Reference in New Issue
Block a user