Use EmojiDialog popup in chatbar

This converts the emoji dialog in the chatbar to be the same popup as for reactions. This includes:

- EmojiPicker and ReactionPicker were already similar and are made identical, as such ReactionPicker no longer needed
- Emoji dialog used for both reactions and chatbar emojis
- Add some parameters to allow for different use cases (include custom emojis and whether selection closes the popup)

![image](/uploads/c71bb5ffdc6914efad654998a886ade6/image.png)
This commit is contained in:
James Graham
2022-12-06 14:49:25 +00:00
parent 1ab5bdb600
commit b5d8acf9de
7 changed files with 62 additions and 141 deletions

View File

@@ -14,7 +14,6 @@ QQC2.ToolBar {
id: chatBar
property alias inputFieldText: inputField.text
property alias textField: inputField
property alias emojiPaneOpened: emojiButton.checked
property alias cursorPosition: inputField.cursorPosition
signal closeAllTriggered()
@@ -205,6 +204,14 @@ QQC2.ToolBar {
display: QQC2.AbstractButton.IconOnly
checkable: true
onClicked: {
if (emojiDialog.visible) {
emojiDialog.close()
} else {
emojiDialog.open()
}
}
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
}
@@ -224,6 +231,19 @@ QQC2.ToolBar {
}
}
EmojiDialog {
id: emojiDialog
x: parent.width - implicitWidth
y: -implicitHeight - Kirigami.Units.smallSpacing
modal: false
includeCustom: true
closeOnChosen: false
onChosen: insertText(emoji)
onClosed: if (emojiButton.checked) emojiButton.checked = false
}
CompletionMenu {
id: completionMenu
height: implicitHeight

View File

@@ -46,38 +46,6 @@ ColumnLayout {
}
}
Kirigami.Separator {
id: emojiPickerLoaderSeparator
visible: emojiPickerLoader.visible
Layout.fillWidth: true
height: visible ? implicitHeight : 0
}
Loader {
id: emojiPickerLoader
active: visible
visible: chatBar.emojiPaneOpened
onItemChanged: if (visible) {
emojiPickerLoader.item.forceActiveFocus()
}
Layout.fillWidth: true
sourceComponent: QQC2.Pane {
onActiveFocusChanged: if(activeFocus) {
emojiPicker.forceActiveFocus()
}
topPadding: 0
bottomPadding: 0
rightPadding: 0
leftPadding: 0
Kirigami.Theme.colorSet: Kirigami.Theme.View
contentItem: EmojiPicker {
id: emojiPicker
onChosen: insertText(emoji)
}
}
}
Kirigami.Separator {
id: replySeparator
visible: replyPane.visible

View File

@@ -8,38 +8,52 @@ import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
ColumnLayout {
id: emojiPicker
id: root
property bool includeCustom: false
readonly property var currentEmojiModel: {
if (includeCustom) {
EmojiModel.categoriesWithCustom
} else {
EmojiModel.categories
}
}
readonly property int categoryIconSize: 45
readonly property var currentCategory: EmojiModel.categoriesWithCustom[categories.currentIndex].category
readonly property int categoryCount: categories.count
readonly property var currentCategory: currentEmojiModel[categories.currentIndex].category
readonly property alias categoryCount: categories.count
signal chosen(string emoji)
spacing: 0
onActiveFocusChanged: if (activeFocus) categories.forceActiveFocus()
QQC2.ScrollView {
Layout.fillWidth: true
Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height
QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
Layout.preferredHeight: emojiPicker.categoryIconSize + QQC2.ScrollBar.horizontal.height
ListView {
id: categories
clip: true
focus: true
orientation: ListView.Horizontal
Keys.onReturnPressed: if (emojiGrid.count > 0) emojiGrid.focus = true
Keys.onEnterPressed: if (emojiGrid.count > 0) emojiGrid.focus = true
KeyNavigation.down: emojiGrid.count > 0 ? emojiGrid : categories
KeyNavigation.tab: emojiGrid.count > 0 ? emojiGrid : categories
keyNavigationEnabled: true
keyNavigationWraps: true
Keys.forwardTo: searchField
interactive: width !== contentWidth
model: EmojiModel.categoriesWithCustom
delegate: EmojiDelegate {
id: emojiDelegate
model: root.currentEmojiModel
Component.onCompleted: categories.forceActiveFocus()
width: emojiPicker.categoryIconSize
delegate: EmojiDelegate {
width: root.categoryIconSize
height: width
checked: categories.currentIndex === model.index
@@ -48,6 +62,7 @@ ColumnLayout {
onClicked: {
categories.currentIndex = index
categories.focus = true
}
}
}
@@ -66,14 +81,13 @@ ColumnLayout {
EmojiGrid {
id: emojiGrid
targetIconSize: emojiPicker.categoryIconSize
model: searchField.text.length === 0 ? EmojiModel.emojis(emojiPicker.currentCategory) : EmojiModel.filterModel(searchField.text, false)
targetIconSize: root.categoryIconSize
model: searchField.text.length === 0 ? EmojiModel.emojis(root.currentCategory) : (root.includeCustom ? EmojiModel.filterModel(searchField.text, false) : EmojiModel.filterModelNoCustom(searchField.text, false))
Layout.fillWidth: true
Layout.preferredHeight: 350
onChosen: emojiPicker.chosen(unicode)
withCustom: true
Layout.fillHeight: true
withCustom: root.includeCustom
onChosen: root.chosen(unicode)
header: categories
Keys.forwardTo: searchField
}
}

View File

@@ -1,86 +0,0 @@
// SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
ColumnLayout {
id: reactionPicker
height: 400
readonly property int categoryIconSize: 45
readonly property var currentCategory: EmojiModel.categories[categories.currentIndex].category
readonly property alias categoryCount: categories.count
signal chosen(string emoji)
spacing: 0
QQC2.ScrollView {
Layout.fillWidth: true
Layout.preferredHeight: reactionPicker.categoryIconSize + QQC2.ScrollBar.horizontal.height
QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
ListView {
id: categories
keyNavigationEnabled: true
focus: true
height: reactionPicker.categoryIconSize
Keys.onReturnPressed: if (emojiGrid.count > 0) emojiGrid.focus = true
Keys.onEnterPressed: if (emojiGrid.count > 0) emojiGrid.focus = true
currentIndex: 2
keyNavigationWraps: true
Keys.forwardTo: searchField
interactive: width !== contentWidth
model: EmojiModel.categories
Component.onCompleted: categories.forceActiveFocus()
delegate: EmojiDelegate {
checked: categories.currentIndex === model.index
emoji: modelData.emoji
name: modelData.name
height: reactionPicker.categoryIconSize
width: height
onClicked: {
categories.currentIndex = index
categories.focus = true
}
}
orientation: Qt.Horizontal
KeyNavigation.down: emojiGrid.count > 0 ? emojiGrid : categories
KeyNavigation.tab: emojiGrid.count > 0 ? emojiGrid : categories
}
}
Kirigami.Separator {
Layout.fillWidth: true
Layout.preferredHeight: 1
}
Kirigami.SearchField {
id: searchField
Layout.margins: Kirigami.Units.smallSpacing
Layout.fillWidth: true
}
EmojiGrid {
id: emojiGrid
targetIconSize: reactionPicker.categoryIconSize
model: searchField.text.length === 0 ? EmojiModel.emojis(reactionPicker.currentCategory) : EmojiModel.filterModelNoCustom(searchField.text, false)
Layout.fillWidth: true
Layout.fillHeight: true
withCustom: false
onChosen: reactionPicker.chosen(unicode)
header: categories
Keys.forwardTo: searchField
}
}

View File

@@ -10,7 +10,11 @@ import org.kde.neochat 1.0
QQC2.Popup {
id: emojiPopup
signal react(string emoji)
property bool includeCustom: false
property bool closeOnChosen: true
signal chosen(string emoji)
Connections {
target: RoomManager
@@ -37,10 +41,12 @@ QQC2.Popup {
implicitHeight: Kirigami.Units.gridUnit * 20 + 2 * padding
width: Math.min(contentItem.categoryIconSize * contentItem.categoryCount + 2 * padding, QQC2.Overlay.overlay.width)
contentItem: ReactionPicker {
contentItem: EmojiPicker {
height: 400
includeCustom: emojiPopup.includeCustom
onChosen: {
react(emoji)
emojiPopup.close()
emojiPopup.chosen(emoji)
if (emojiPopup.closeOnChosen) emojiPopup.close()
}
}
}

View File

@@ -521,7 +521,7 @@ Kirigami.ScrollablePage {
onClicked: emojiDialog.open();
EmojiDialog {
id: emojiDialog
onReact: {
onChosen: {
page.currentRoom.toggleReaction(hoverActions.event.eventId, emoji);
chatBox.focusInputField();
}

View File

@@ -93,7 +93,6 @@
<file alias="ConfirmEncryptionDialog.qml">qml/Dialog/ConfirmEncryptionDialog.qml</file>
<file alias="RemoveSheet.qml">qml/Menu/Timeline/RemoveSheet.qml</file>
<file alias="BanSheet.qml">qml/Menu/Timeline/BanSheet.qml</file>
<file alias="ReactionPicker.qml">qml/Component/Emoji/ReactionPicker.qml</file>
<file alias="EmojiTonesPicker.qml">qml/Component/Emoji/EmojiTonesPicker.qml</file>
<file alias="EmojiDelegate.qml">qml/Component/Emoji/EmojiDelegate.qml</file>
<file alias="EmojiGrid.qml">qml/Component/Emoji/EmojiGrid.qml</file>