1// SPDX-FileCopyrightText: 2021 Nheko Contributors 2// 3// SPDX-License-Identifier: GPL-3.0-or-later 4 5import "../" 6import QtGraphicalEffects 1.0 7import QtQuick 2.9 8import QtQuick.Controls 2.3 9import QtQuick.Layouts 1.3 10import im.nheko 1.0 11import im.nheko.EmojiModel 1.0 12 13Menu { 14 id: stickerPopup 15 16 property var callback 17 property var colors 18 property string roomid 19 property alias model: gridView.model 20 property var textArea 21 property real highlightHue: Nheko.colors.highlight.hslHue 22 property real highlightSat: Nheko.colors.highlight.hslSaturation 23 property real highlightLight: Nheko.colors.highlight.hslLightness 24 readonly property int stickerDim: 128 25 readonly property int stickerDimPad: 128 + Nheko.paddingSmall 26 readonly property int stickersPerRow: 3 27 28 function show(showAt, roomid_, callback) { 29 console.debug("Showing sticker picker"); 30 roomid = roomid_; 31 stickerPopup.callback = callback; 32 popup(showAt ? showAt : null); 33 } 34 35 margins: 0 36 bottomPadding: 1 37 leftPadding: 1 38 rightPadding: 1 39 modal: true 40 focus: true 41 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside 42 width: stickersPerRow * stickerDimPad + 20 43 44 Rectangle { 45 color: Nheko.colors.window 46 height: columnView.implicitHeight + 4 47 width: stickersPerRow * stickerDimPad + 20 48 49 ColumnLayout { 50 id: columnView 51 52 spacing: 0 53 anchors.leftMargin: 3 54 anchors.rightMargin: 3 55 anchors.bottom: parent.bottom 56 anchors.left: parent.left 57 anchors.right: parent.right 58 anchors.topMargin: 2 59 60 // Search field 61 TextField { 62 id: emojiSearch 63 64 Layout.topMargin: 3 65 Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 - 6 66 palette: Nheko.colors 67 background: null 68 placeholderTextColor: Nheko.colors.buttonText 69 color: Nheko.colors.text 70 placeholderText: qsTr("Search") 71 selectByMouse: true 72 rightPadding: clearSearch.width 73 onTextChanged: searchTimer.restart() 74 onVisibleChanged: { 75 if (visible) 76 forceActiveFocus(); 77 78 } 79 80 Timer { 81 id: searchTimer 82 83 interval: 350 // tweak as needed? 84 onTriggered: stickerPopup.model.searchString = emojiSearch.text 85 } 86 87 ToolButton { 88 id: clearSearch 89 90 visible: emojiSearch.text !== '' 91 icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) 92 focusPolicy: Qt.NoFocus 93 onClicked: emojiSearch.clear() 94 hoverEnabled: true 95 background: null 96 97 anchors { 98 verticalCenter: parent.verticalCenter 99 right: parent.right 100 } 101 // clear the default hover effects. 102 103 Image { 104 height: parent.height - 2 * Nheko.paddingSmall 105 width: height 106 source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText) 107 108 anchors { 109 verticalCenter: parent.verticalCenter 110 right: parent.right 111 margins: Nheko.paddingSmall 112 } 113 114 } 115 116 } 117 118 } 119 120 // emoji grid 121 GridView { 122 id: gridView 123 124 model: roomid ? TimelineManager.completerFor("stickers", roomid) : null 125 Layout.preferredHeight: cellHeight * 3.5 126 Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 127 Layout.leftMargin: 4 128 cellWidth: stickerDimPad 129 cellHeight: stickerDimPad 130 boundsBehavior: Flickable.StopAtBounds 131 clip: true 132 currentIndex: -1 // prevent sorting from stealing focus 133 cacheBuffer: 500 134 135 ScrollHelper { 136 flickable: parent 137 anchors.fill: parent 138 enabled: !Settings.mobileMode 139 } 140 141 // Individual emoji 142 delegate: AbstractButton { 143 width: stickerDim 144 height: stickerDim 145 hoverEnabled: true 146 ToolTip.text: ":" + model.shortcode + ": - " + model.body 147 ToolTip.visible: hovered 148 // TODO: maybe add favorites at some point? 149 onClicked: { 150 console.debug("Picked " + model.shortcode); 151 stickerPopup.close(); 152 callback(model.originalRow); 153 } 154 155 contentItem: Image { 156 height: stickerDim 157 width: stickerDim 158 source: model.url.replace("mxc://", "image://MxcImage/") 159 fillMode: Image.PreserveAspectFit 160 } 161 162 background: Rectangle { 163 anchors.fill: parent 164 color: hovered ? Nheko.colors.highlight : 'transparent' 165 radius: 5 166 } 167 168 } 169 170 ScrollBar.vertical: ScrollBar { 171 id: emojiScroll 172 } 173 174 } 175 176 } 177 178 } 179 180} 181