feat: add channel switcher when hitting CTRL+K
This commit is contained in:
parent
6afe9088e9
commit
825097f007
|
@ -44,7 +44,7 @@ Rectangle {
|
|||
anchors.left: parent.left
|
||||
radius: 8
|
||||
// Hide the box if it is filtered out
|
||||
property bool isVisible: searchStr == "" || name.includes(searchStr)
|
||||
property bool isVisible: searchStr === "" || name.includes(searchStr)
|
||||
visible: isVisible ? true : false
|
||||
height: isVisible ? !isCompact ? 64 : contactImage.height + Style.current.smallPadding * 2 : 0
|
||||
|
||||
|
|
|
@ -69,6 +69,47 @@ RowLayout {
|
|||
shortcut: "Ctrl+4, Ctrl+,"
|
||||
onTriggered: changeAppSection(Constants.profile)
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+K"
|
||||
onTriggered: {
|
||||
if (channelPicker.opened) {
|
||||
channelPicker.close()
|
||||
} else {
|
||||
channelPicker.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: statusIdenticonComponent
|
||||
StatusIdenticon {}
|
||||
}
|
||||
|
||||
StatusInputListPopup {
|
||||
id: channelPicker
|
||||
title: qsTr("Where do you want to go?")
|
||||
showSearchBox: true
|
||||
width: 350
|
||||
x: parent.width / 2 - width / 2
|
||||
y: parent.height / 2 - height / 2
|
||||
modelList: chatsModel.chats
|
||||
getText: function (modelData) {
|
||||
return modelData.name
|
||||
}
|
||||
getImageComponent: function (parent, modelData) {
|
||||
return statusIdenticonComponent.createObject(parent, {
|
||||
width: channelPicker.imageWidth,
|
||||
height: channelPicker.imageHeight,
|
||||
chatName: modelData.name,
|
||||
chatType: modelData.chatType,
|
||||
identicon: modelData.identicon
|
||||
});
|
||||
}
|
||||
onClicked: function (index) {
|
||||
chatsModel.setActiveChannelByIndex(index)
|
||||
appMain.changeAppSection(Constants.chat)
|
||||
channelPicker.close()
|
||||
}
|
||||
}
|
||||
|
||||
function changeAppSection(section) {
|
||||
let sectionId = -1
|
||||
|
|
|
@ -32,7 +32,8 @@ Item {
|
|||
signal textEdited(string inputValue)
|
||||
|
||||
id: inputBox
|
||||
height: inputRectangle.height + (hasLabel ? inputLabel.height + labelMargin : 0) + (!!validationError ? (validationErrorText.height + validationErrorTopMargin) : 0)
|
||||
implicitHeight: inputRectangle.height + (hasLabel ? inputLabel.height + labelMargin : 0) + (!!validationError ? (validationErrorText.height + validationErrorTopMargin) : 0)
|
||||
height: implicitHeight
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
|
||||
|
|
|
@ -2,31 +2,53 @@ import QtQuick 2.13
|
|||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.12
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Layouts 1.13
|
||||
import "../../imports"
|
||||
import "../../shared"
|
||||
|
||||
Popup {
|
||||
property var modelList
|
||||
property alias listView: listView
|
||||
property var getImageSource: function () {}
|
||||
property var getImageSource
|
||||
property var getImageComponent
|
||||
property var getText: function () {}
|
||||
property var onClicked: function () {}
|
||||
property int imageWidth: 22
|
||||
property int imageHeight: 22
|
||||
property string title
|
||||
property bool showSearchBox: false
|
||||
|
||||
function openPopup(listParam) {
|
||||
modelList = listParam
|
||||
popup.open()
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
listView.currentIndex = 0
|
||||
if (showSearchBox) {
|
||||
searchBox.textField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
id: popup
|
||||
padding: Style.current.smallPadding
|
||||
width: messageInput.width
|
||||
height: Math.min(400, listView.contentHeight + Style.current.smallPadding)
|
||||
x : messageInput.x
|
||||
height: {
|
||||
let possibleHeight = listView.contentHeight + Style.current.smallPadding * 2
|
||||
if (popupTitle.visible) {
|
||||
possibleHeight += popupTitle.height + Style.current.smallPadding
|
||||
}
|
||||
if (searchBox.visible) {
|
||||
possibleHeight += searchBox.height + Style.current.smallPadding
|
||||
}
|
||||
|
||||
return Math.min(400, possibleHeight)
|
||||
}
|
||||
x: messageInput.x
|
||||
y: -height
|
||||
background: Rectangle {
|
||||
id: bgRectangle
|
||||
visible: !!popup.modelList && popup.modelList.length > 0
|
||||
visible: !!popup.title || (!!popup.modelList && popup.modelList.length > 0)
|
||||
color: Style.current.background
|
||||
border.width: 0
|
||||
radius: Style.current.radius
|
||||
|
@ -46,36 +68,133 @@ Popup {
|
|||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: popupTitle
|
||||
visible: !!popup.title
|
||||
height: visible ? implicitHeight : 0
|
||||
text: popup.title
|
||||
font.pixelSize: 17
|
||||
anchors.top: parent.top
|
||||
}
|
||||
|
||||
SearchBox {
|
||||
id: searchBox
|
||||
visible: showSearchBox
|
||||
height: visible ? implicitHeight : 0
|
||||
width: parent.width
|
||||
anchors.top: popupTitle.bottom
|
||||
anchors.topMargin: popupTitle.visible ? Style.current.smallPadding : 0
|
||||
|
||||
function goToNextAvailableIndex(up) {
|
||||
do {
|
||||
if (!up && listView.currentIndex === listView.count - 1) {
|
||||
listView.currentIndex = 0
|
||||
return
|
||||
} else if (up && listView.currentIndex === 0) {
|
||||
listView.currentIndex = listView.count - 1
|
||||
return
|
||||
}
|
||||
|
||||
if (up) {
|
||||
listView.decrementCurrentIndex()
|
||||
} else {
|
||||
listView.incrementCurrentIndex()
|
||||
}
|
||||
} while (!listView.currentItem.visible)
|
||||
}
|
||||
|
||||
Keys.onReleased: function onKeyPress(event) {
|
||||
if (event.key === Qt.Key_Down) {
|
||||
searchBox.goToNextAvailableIndex(false)
|
||||
}
|
||||
if (event.key === Qt.Key_Up) {
|
||||
searchBox.goToNextAvailableIndex(true)
|
||||
}
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
return popup.close()
|
||||
}
|
||||
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
|
||||
return popup.onClicked(listView.currentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
model: popup.modelList || []
|
||||
keyNavigationEnabled: true
|
||||
anchors.fill: parent
|
||||
Layout.fillHeight: true
|
||||
width: parent.width
|
||||
anchors.top: searchBox.bottom
|
||||
anchors.topMargin: searchBox.visible ? Style.current.smallPadding : 0
|
||||
anchors.bottom: parent.bottom
|
||||
clip: true
|
||||
|
||||
delegate: Rectangle {
|
||||
property string myText: {
|
||||
if (typeof modelData === "undefined") {
|
||||
return popup.getText(model)
|
||||
}
|
||||
return popup.getText(modelData)
|
||||
}
|
||||
id: rectangle
|
||||
visible: searchBox.text === "" || myText.includes(searchBox.text)
|
||||
color: listView.currentIndex === index ? Style.current.backgroundHover : Style.current.transparent
|
||||
border.width: 0
|
||||
width: parent.width
|
||||
height: 42
|
||||
height: visible ? 42 : 0
|
||||
radius: Style.current.radius
|
||||
|
||||
SVGImage {
|
||||
id: image
|
||||
source: popup.getImageSource(modelData)
|
||||
Loader {
|
||||
id: imageLoader
|
||||
active: !!popup.getImageComponent || !!popup.getImageSource
|
||||
width: popup.imageWidth
|
||||
height: popup.imageHeight
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
sourceComponent: popup.getImageComponent ? customImageComponent : normalImageComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: customImageComponent
|
||||
Item {
|
||||
id: imageComponentContainer
|
||||
children: {
|
||||
if (!popup.getImageComponent) {
|
||||
return ""
|
||||
}
|
||||
if (typeof modelData === "undefined") {
|
||||
return popup.getImageComponent(imageComponentContainer, model)
|
||||
}
|
||||
return popup.getImageComponent(imageComponentContainer, modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: normalImageComponent
|
||||
SVGImage {
|
||||
visible: !!source
|
||||
width: popup.imageWidth
|
||||
height: popup.imageHeight
|
||||
source: {
|
||||
if (!popup.getImageSource) {
|
||||
return ""
|
||||
}
|
||||
if (typeof modelData === "undefined") {
|
||||
return popup.getImageSource(model)
|
||||
}
|
||||
return popup.getImageSource(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: popup.getText(modelData)
|
||||
text: rectangle.myText
|
||||
color: Style.current.textColor
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: image.right
|
||||
anchors.left: imageLoader.right
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
font.pixelSize: 15
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue