Warning, /network/neochat/src/qml/EmojiPicker.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
0002 // SPDX-License-Identifier: GPL-2.0-or-later
0003
0004 import QtQuick
0005 import QtQuick.Controls as QQC2
0006 import QtQuick.Layouts
0007 import org.kde.kirigami as Kirigami
0008 import org.kde.neochat
0009
0010 ColumnLayout {
0011 id: root
0012
0013 /**
0014 * @brief The current room that user is viewing.
0015 */
0016 property NeoChatRoom currentRoom
0017
0018 property bool includeCustom: false
0019 property bool showQuickReaction: false
0020
0021 readonly property var currentEmojiModel: {
0022 if (includeCustom) {
0023 EmojiModel.categoriesWithCustom;
0024 } else {
0025 EmojiModel.categories;
0026 }
0027 }
0028
0029 readonly property int categoryIconSize: Math.round(Kirigami.Units.gridUnit * 2.5)
0030 readonly property var currentCategory: currentEmojiModel[categories.currentIndex].category
0031 readonly property alias categoryCount: categories.count
0032 property int selectedType: 0
0033
0034 signal chosen(string emoji)
0035
0036 onActiveFocusChanged: if (activeFocus) {
0037 searchField.forceActiveFocus();
0038 }
0039
0040 spacing: 0
0041
0042 Kirigami.NavigationTabBar {
0043 id: types
0044 Layout.fillWidth: true
0045 Kirigami.Theme.colorSet: Kirigami.Theme.View
0046
0047 background: null
0048 actions: [
0049 Kirigami.Action {
0050 id: emojis
0051 icon.name: "smiley"
0052 text: i18n("Emojis")
0053 checked: true
0054 onTriggered: root.selectedType = 0
0055 },
0056 Kirigami.Action {
0057 id: stickers
0058 icon.name: "stickers"
0059 text: i18n("Stickers")
0060 onTriggered: root.selectedType = 1
0061 }
0062 ]
0063 }
0064
0065 QQC2.ScrollView {
0066 Layout.fillWidth: true
0067 Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height
0068 QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
0069
0070 ListView {
0071 id: categories
0072 clip: true
0073 focus: true
0074 orientation: ListView.Horizontal
0075
0076 Keys.onReturnPressed: if (emojiGrid.count > 0) {
0077 emojiGrid.focus = true;
0078 }
0079 Keys.onEnterPressed: if (emojiGrid.count > 0) {
0080 emojiGrid.focus = true;
0081 }
0082
0083 KeyNavigation.down: emojiGrid.count > 0 ? emojiGrid : categories
0084 KeyNavigation.tab: emojiGrid.count > 0 ? emojiGrid : categories
0085
0086 keyNavigationEnabled: true
0087 keyNavigationWraps: true
0088 Keys.forwardTo: searchField
0089 interactive: width !== contentWidth
0090
0091 model: root.selectedType === 0 ? root.currentEmojiModel : stickerPackModel
0092 Component.onCompleted: categories.forceActiveFocus()
0093
0094 delegate: root.selectedType === 0 ? emojiDelegate : stickerDelegate
0095 }
0096 }
0097
0098 Kirigami.Separator {
0099 Layout.fillWidth: true
0100 Layout.preferredHeight: 1
0101 }
0102
0103 Kirigami.SearchField {
0104 id: searchField
0105 Layout.margins: Kirigami.Units.smallSpacing
0106 Layout.fillWidth: true
0107 visible: selectedType === 0
0108
0109 /**
0110 * The focus is manged by the parent and we don't want to use the standard
0111 * shortcut as it could block other SearchFields from using it.
0112 */
0113 focusSequence: ""
0114 }
0115
0116 EmojiGrid {
0117 id: emojiGrid
0118 targetIconSize: root.currentCategory === EmojiModel.Custom ? Kirigami.Units.gridUnit * 3 : root.categoryIconSize // Custom emojis are bigger
0119 model: root.selectedType === 1 ? emoticonFilterModel : searchField.text.length === 0 ? EmojiModel.emojis(root.currentCategory) : (root.includeCustom ? EmojiModel.filterModel(searchField.text, false) : EmojiModel.filterModelNoCustom(searchField.text, false))
0120 Layout.fillWidth: true
0121 Layout.fillHeight: true
0122 withCustom: root.includeCustom
0123 onChosen: unicode => root.chosen(unicode)
0124 header: categories
0125 Keys.forwardTo: searchField
0126 stickers: root.selectedType === 1
0127 onStickerChosen: stickerModel.postSticker(emoticonFilterModel.mapToSource(emoticonFilterModel.index(index, 0)).row)
0128 }
0129
0130 Kirigami.Separator {
0131 visible: showQuickReaction
0132 Layout.fillWidth: true
0133 Layout.preferredHeight: 1
0134 }
0135
0136 QQC2.ScrollView {
0137 visible: showQuickReaction
0138 Layout.fillWidth: true
0139 Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height
0140 QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0
0141
0142 ListView {
0143 id: quickReactions
0144 Layout.fillWidth: true
0145
0146 model: ["👍", "👎", "😄", "🎉", "😕", "❤", "🚀", "👀"]
0147
0148 delegate: EmojiDelegate {
0149 emoji: modelData
0150
0151 height: root.categoryIconSize
0152 width: height
0153
0154 onClicked: root.chosen(modelData)
0155 }
0156
0157 orientation: Qt.Horizontal
0158 }
0159 }
0160
0161 ImagePacksModel {
0162 id: stickerPackModel
0163 room: root.currentRoom
0164 showStickers: true
0165 showEmoticons: false
0166 }
0167
0168 StickerModel {
0169 id: stickerModel
0170 model: stickerPackModel
0171 packIndex: 0
0172 room: root.currentRoom
0173 }
0174
0175 EmoticonFilterModel {
0176 id: emoticonFilterModel
0177 sourceModel: stickerModel
0178 showStickers: true
0179 }
0180
0181 Component {
0182 id: emojiDelegate
0183 Kirigami.NavigationTabButton {
0184 width: root.categoryIconSize
0185 height: width
0186 checked: categories.currentIndex === model.index
0187 text: modelData ? modelData.emoji : ""
0188 QQC2.ToolTip.text: modelData ? modelData.name : ""
0189 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0190 QQC2.ToolTip.visible: hovered
0191 onClicked: {
0192 categories.currentIndex = index;
0193 categories.focus = true;
0194 }
0195 }
0196 }
0197
0198 Component {
0199 id: stickerDelegate
0200 Kirigami.NavigationTabButton {
0201 width: root.categoryIconSize
0202 height: width
0203 checked: stickerModel.packIndex === model.index
0204 contentItem: Image {
0205 source: model.avatarUrl
0206 }
0207 QQC2.ToolTip.text: model.name
0208 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0209 QQC2.ToolTip.visible: hovered && !!model.name
0210 onClicked: stickerModel.packIndex = model.index
0211 }
0212 }
0213
0214 function clearSearchField() {
0215 searchField.text = "";
0216 }
0217 }