Improve account status msg field & add history
- Up to 5 previously set status are now shown under the field for quick access; the history is shared between accounts - When focusing the field, the text gets auto-selected since most of the time we want to set a totally different status, not edit the current one - Typing in the field will autosuggest any matching history entry - Keyboard focus now skips the "apply" button, since we can just hit enter in the field
This commit is contained in:
parent
67edd63c5a
commit
3402a1d5f8
|
@ -8,7 +8,7 @@ import Clipboard 0.1
|
||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
HMenu {
|
HMenu {
|
||||||
id: accountMenu
|
id: root
|
||||||
|
|
||||||
property string userId
|
property string userId
|
||||||
property string presence
|
property string presence
|
||||||
|
@ -20,32 +20,69 @@ HMenu {
|
||||||
py.callClientCoro(userId, "set_presence", [presence, statusMsg])
|
py.callClientCoro(userId, "set_presence", [presence, statusMsg])
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpened: statusText.forceActiveFocus()
|
function statusFieldApply(newStatus=null) {
|
||||||
|
if (newStatus === null) newStatus = statusField.editText.trim()
|
||||||
|
|
||||||
|
if (newStatus) {
|
||||||
|
const existing = statusRepeater.items.indexOf(newStatus)
|
||||||
|
if (existing !== -1) statusRepeater.items.splice(existing, 1)
|
||||||
|
|
||||||
|
statusRepeater.items.unshift(newStatus)
|
||||||
|
statusRepeater.items.length = Math.min(statusRepeater.count, 5)
|
||||||
|
statusRepeater.itemsChanged()
|
||||||
|
window.saveState(statusRepeater)
|
||||||
|
}
|
||||||
|
|
||||||
|
setPresence(presence, newStatus)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpened: statusField.forceActiveFocus()
|
||||||
|
|
||||||
HLabeledItem {
|
HLabeledItem {
|
||||||
id: statusMsgLabel
|
id: statusMsgLabel
|
||||||
enabled: presence && presence !== "offline"
|
enabled: presence && presence !== "offline"
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
|
|
||||||
label.text: qsTr("Status message:")
|
label.text: qsTr("Status message:")
|
||||||
label.horizontalAlignment: Qt.AlignHCenter
|
label.horizontalAlignment: Qt.AlignHCenter
|
||||||
|
label.leftPadding: theme.spacing
|
||||||
Keys.onDownPressed: onlineButton.forceActiveFocus()
|
label.rightPadding: label.leftPadding
|
||||||
|
label.topPadding: theme.spacing / 2
|
||||||
|
label.bottomPadding: label.topPadding
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
HTextField {
|
HComboBox {
|
||||||
id: statusText
|
// We use a ComboBox disguised as a field for the
|
||||||
maximumLength: 255
|
// autosuggestion-as-we-type feature
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
onAccepted: {
|
|
||||||
setPresence(presence, statusText.text)
|
|
||||||
accountMenu.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultText: statusMsg
|
id: statusField
|
||||||
placeholderText: presence ? "" : "Unsupported server"
|
editable: true
|
||||||
|
indicator: null
|
||||||
|
popup: null
|
||||||
|
model: statusRepeater.model
|
||||||
|
currentIndex: statusRepeater.items.indexOf(
|
||||||
|
root.currentIndex !== -1 &&
|
||||||
|
root.itemAt(root.currentIndex).isStatus ?
|
||||||
|
root.itemAt(root.currentIndex).text :
|
||||||
|
root.statusMsg
|
||||||
|
)
|
||||||
|
|
||||||
|
field.placeholderText: presence ? "" : "Unsupported server"
|
||||||
|
field.maximumLength: 255
|
||||||
|
|
||||||
|
onAccepted: root.statusFieldApply()
|
||||||
|
onActiveFocusChanged: if (activeFocus) field.selectAll()
|
||||||
|
|
||||||
|
Keys.onBacktabPressed: event => Keys.upPressed(event)
|
||||||
|
Keys.onTabPressed: event => Keys.downPressed(event)
|
||||||
|
|
||||||
|
Keys.onUpPressed: signOutItem.forceActiveFocus()
|
||||||
|
Keys.onDownPressed:
|
||||||
|
(statusRepeater.itemAt(0) || onlineItem).forceActiveFocus()
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
@ -56,10 +93,7 @@ HMenu {
|
||||||
|
|
||||||
icon.name: "apply"
|
icon.name: "apply"
|
||||||
icon.color: theme.colors.positiveBackground
|
icon.color: theme.colors.positiveBackground
|
||||||
onClicked: {
|
onClicked: root.statusFieldApply()
|
||||||
setPresence(presence, statusText.text)
|
|
||||||
accountMenu.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
@ -68,14 +102,43 @@ HMenu {
|
||||||
|
|
||||||
HMenuSeparator {}
|
HMenuSeparator {}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: statusRepeater
|
||||||
|
|
||||||
|
// Separate property instead of setting model directly so that we can
|
||||||
|
// manipulate this as a JS list, not a QQmlModel
|
||||||
|
property var items: window.getState(this, "items", [])
|
||||||
|
|
||||||
|
readonly property string saveName: "lastStatus"
|
||||||
|
readonly property string saveId: "ALL"
|
||||||
|
readonly property var saveProperties: ["items"]
|
||||||
|
|
||||||
|
model: items
|
||||||
|
|
||||||
|
delegate: HMenuItem {
|
||||||
|
readonly property bool isStatus: true
|
||||||
|
|
||||||
|
icon.name: "previously-set-status"
|
||||||
|
text: modelData
|
||||||
|
onTriggered: root.statusFieldApply(text)
|
||||||
|
|
||||||
|
Keys.onBacktabPressed: event => Keys.upPressed(event)
|
||||||
|
|
||||||
|
Keys.onUpPressed: event => {
|
||||||
|
event.accepted = index === 0
|
||||||
|
if (event.accepted) statusField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HMenuSeparator { visible: statusRepeater.count > 0 }
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItem {
|
||||||
id: onlineButton
|
id: onlineItem
|
||||||
icon.name: "presence-online"
|
icon.name: "presence-online"
|
||||||
icon.color: theme.controls.presence.online
|
icon.color: theme.controls.presence.online
|
||||||
text: qsTr("Online")
|
text: qsTr("Online")
|
||||||
onTriggered: setPresence("online")
|
onTriggered: setPresence("online")
|
||||||
|
|
||||||
Keys.onUpPressed: statusText.forceActiveFocus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItem {
|
HMenuItem {
|
||||||
|
@ -133,11 +196,14 @@ HMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
HMenuItemPopupSpawner {
|
HMenuItemPopupSpawner {
|
||||||
|
id: signOutItem
|
||||||
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")
|
||||||
|
|
||||||
popup: "Popups/SignOutPopup.qml"
|
popup: "Popups/SignOutPopup.qml"
|
||||||
properties: { "userId": userId }
|
properties: { "userId": userId }
|
||||||
|
|
||||||
|
Keys.onDownPressed: statusField.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveState(obj) {
|
function saveState(obj) {
|
||||||
|
// obj should have these properties: saveName (str),
|
||||||
|
// saveId (str, default "ALL"), and saveProperties (array of str)
|
||||||
|
|
||||||
if (! obj.saveName || ! obj.saveProperties ||
|
if (! obj.saveName || ! obj.saveProperties ||
|
||||||
obj.saveProperties.length < 1) return
|
obj.saveProperties.length < 1) return
|
||||||
|
|
||||||
|
|
3
src/icons/thin/previously-set-status.svg
Normal file
3
src/icons/thin/previously-set-status.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m24 12c0 6.627-5.373 12-12 12s-12-5.373-12-12h2c0 5.514 4.486 10 10 10s10-4.486 10-10-4.486-10-10-10c-2.777 0-5.287 1.141-7.099 2.977l2.061 2.061-6.962 1.354 1.305-7.013 2.179 2.18c2.172-2.196 5.182-3.559 8.516-3.559 6.627 0 12 5.373 12 12zm-13-6v8h7v-2h-5v-6z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 368 B |
Loading…
Reference in New Issue
Block a user