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) 
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +521,7 @@ Kirigami.ScrollablePage {
|
||||
onClicked: emojiDialog.open();
|
||||
EmojiDialog {
|
||||
id: emojiDialog
|
||||
onReact: {
|
||||
onChosen: {
|
||||
page.currentRoom.toggleReaction(hoverActions.event.eventId, emoji);
|
||||
chatBox.focusInputField();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user