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) emojiGrid.focus = true 0077 Keys.onEnterPressed: if (emojiGrid.count > 0) emojiGrid.focus = true 0078 0079 KeyNavigation.down: emojiGrid.count > 0 ? emojiGrid : categories 0080 KeyNavigation.tab: emojiGrid.count > 0 ? emojiGrid : categories 0081 0082 keyNavigationEnabled: true 0083 keyNavigationWraps: true 0084 Keys.forwardTo: searchField 0085 interactive: width !== contentWidth 0086 0087 model: root.selectedType === 0 ? root.currentEmojiModel : stickerPackModel 0088 Component.onCompleted: categories.forceActiveFocus() 0089 0090 delegate: root.selectedType === 0 ? emojiDelegate : stickerDelegate 0091 } 0092 } 0093 0094 Kirigami.Separator { 0095 Layout.fillWidth: true 0096 Layout.preferredHeight: 1 0097 } 0098 0099 Kirigami.SearchField { 0100 id: searchField 0101 Layout.margins: Kirigami.Units.smallSpacing 0102 Layout.fillWidth: true 0103 visible: selectedType === 0 0104 0105 /** 0106 * The focus is manged by the parent and we don't want to use the standard 0107 * shortcut as it could block other SearchFields from using it. 0108 */ 0109 focusSequence: "" 0110 } 0111 0112 EmojiGrid { 0113 id: emojiGrid 0114 targetIconSize: root.currentCategory === EmojiModel.Custom ? Kirigami.Units.gridUnit * 3 : root.categoryIconSize // Custom emojis are bigger 0115 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)) 0116 Layout.fillWidth: true 0117 Layout.fillHeight: true 0118 withCustom: root.includeCustom 0119 onChosen: unicode => root.chosen(unicode) 0120 header: categories 0121 Keys.forwardTo: searchField 0122 stickers: root.selectedType === 1 0123 onStickerChosen: stickerModel.postSticker(emoticonFilterModel.mapToSource(emoticonFilterModel.index(index, 0)).row) 0124 } 0125 0126 Kirigami.Separator { 0127 visible: showQuickReaction 0128 Layout.fillWidth: true 0129 Layout.preferredHeight: 1 0130 } 0131 0132 QQC2.ScrollView { 0133 visible: showQuickReaction 0134 Layout.fillWidth: true 0135 Layout.preferredHeight: root.categoryIconSize + QQC2.ScrollBar.horizontal.height 0136 QQC2.ScrollBar.horizontal.height: QQC2.ScrollBar.horizontal.visible ? QQC2.ScrollBar.horizontal.implicitHeight : 0 0137 0138 ListView { 0139 id: quickReactions 0140 Layout.fillWidth: true 0141 0142 model: ["👍", "👎", "😄", "🎉", "😕", "❤", "🚀", "👀"] 0143 0144 delegate: EmojiDelegate { 0145 emoji: modelData 0146 0147 height: root.categoryIconSize 0148 width: height 0149 0150 onClicked: root.chosen(modelData) 0151 } 0152 0153 orientation: Qt.Horizontal 0154 } 0155 } 0156 0157 ImagePacksModel { 0158 id: stickerPackModel 0159 room: root.currentRoom 0160 showStickers: true 0161 showEmoticons: false 0162 } 0163 0164 StickerModel { 0165 id: stickerModel 0166 model: stickerPackModel 0167 packIndex: 0 0168 room: root.currentRoom 0169 } 0170 0171 EmoticonFilterModel { 0172 id: emoticonFilterModel 0173 sourceModel: stickerModel 0174 showStickers: true 0175 } 0176 0177 Component { 0178 id: emojiDelegate 0179 Kirigami.NavigationTabButton { 0180 width: root.categoryIconSize 0181 height: width 0182 checked: categories.currentIndex === model.index 0183 text: modelData ? modelData.emoji : "" 0184 QQC2.ToolTip.text: modelData ? modelData.name : "" 0185 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay 0186 QQC2.ToolTip.visible: hovered 0187 onClicked: { 0188 categories.currentIndex = index; 0189 categories.focus = true; 0190 } 0191 } 0192 } 0193 0194 Component { 0195 id: stickerDelegate 0196 Kirigami.NavigationTabButton { 0197 width: root.categoryIconSize 0198 height: width 0199 checked: stickerModel.packIndex === model.index 0200 contentItem: Image { 0201 source: model.avatarUrl 0202 } 0203 QQC2.ToolTip.text: model.name 0204 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay 0205 QQC2.ToolTip.visible: hovered && !!model.name 0206 onClicked: stickerModel.packIndex = model.index 0207 } 0208 } 0209 0210 function clearSearchField() { 0211 searchField.text = "" 0212 } 0213 }