matrixion/qml/emoji/EmojiPicker.qml

283 lines
11 KiB
QML
Raw Normal View History

2021-03-05 02:35:15 +03:00
// SPDX-FileCopyrightText: 2021 Nheko Contributors
// SPDX-FileCopyrightText: 2022 Nheko Contributors
2021-03-05 02:35:15 +03:00
// SPDX-License-Identifier: GPL-3.0-or-later
2020-10-08 22:11:21 +03:00
import "../"
import QtQuick 2.9
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Window 2.15
import im.nheko
Menu {
2020-10-08 22:11:21 +03:00
id: emojiPopup
2020-07-20 01:42:48 +03:00
2020-11-16 20:41:29 +03:00
property var callback
property var colors
property string emojiCategory: "people"
2022-04-11 05:18:16 +03:00
property real highlightHue: timelineRoot.palette.highlight.hslHue
property real highlightLight: timelineRoot.palette.highlight.hslLightness
2022-04-16 03:13:01 +03:00
property real highlightSat: timelineRoot.palette.highlight.hslSaturation
property alias model: gridView.model
property var textArea
2020-11-16 20:41:29 +03:00
function show(showAt, callback) {
console.debug("Showing emojiPicker");
emojiPopup.callback = callback;
popup(showAt ? showAt : null);
2020-10-08 22:11:21 +03:00
}
2020-05-14 03:19:15 +03:00
bottomPadding: 1
2022-04-16 03:13:01 +03:00
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
focus: true
2020-05-14 03:19:15 +03:00
leftPadding: 1
2022-04-16 03:13:01 +03:00
margins: 0
modal: true
2022-04-16 03:13:01 +03:00
rightPadding: 1
2021-07-03 23:45:36 +03:00
//height: columnView.implicitHeight + 4
//width: columnView.implicitWidth
width: 7 * 52 + 20
Rectangle {
2022-04-11 05:18:16 +03:00
color: timelineRoot.palette.window
2021-07-03 23:45:36 +03:00
height: columnView.implicitHeight + 4
width: 7 * 52 + 20
ColumnLayout {
id: columnView
anchors.bottom: parent.bottom
anchors.left: parent.left
2022-04-16 03:13:01 +03:00
anchors.leftMargin: 3
2021-07-03 23:45:36 +03:00
anchors.right: parent.right
2022-04-16 03:13:01 +03:00
anchors.rightMargin: 3
2021-07-03 23:45:36 +03:00
anchors.topMargin: 2
2022-04-16 03:13:01 +03:00
spacing: 0
2021-07-03 23:45:36 +03:00
// Search field
TextField {
id: emojiSearch
Layout.preferredWidth: 7 * 52 + 20 - 6
2022-04-16 03:13:01 +03:00
Layout.topMargin: 3
2021-07-03 23:45:36 +03:00
background: null
2022-04-11 05:18:16 +03:00
color: timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
palette: timelineRoot.palette
2021-07-03 23:45:36 +03:00
placeholderText: qsTr("Search")
2022-04-16 03:13:01 +03:00
placeholderTextColor: timelineRoot.palette.placeholderText
2021-07-03 23:45:36 +03:00
rightPadding: clearSearch.width
2022-04-16 03:13:01 +03:00
selectByMouse: true
2021-07-03 23:45:36 +03:00
onTextChanged: searchTimer.restart()
onVisibleChanged: {
if (visible)
forceActiveFocus();
else
clear();
2021-07-03 23:45:36 +03:00
}
2021-07-03 23:45:36 +03:00
Timer {
id: searchTimer
interval: 350 // tweak as needed?
2022-04-16 03:13:01 +03:00
2021-07-03 23:45:36 +03:00
onTriggered: {
emojiPopup.model.searchString = emojiSearch.text;
emojiPopup.model.category = Emoji.Category.Search;
}
}
2021-07-03 23:45:36 +03:00
ToolButton {
id: clearSearch
2022-04-16 03:13:01 +03:00
background: null
2021-07-03 23:45:36 +03:00
focusPolicy: Qt.NoFocus
hoverEnabled: true
2022-04-16 03:13:01 +03:00
icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.placeholderText)
visible: emojiSearch.text !== ''
onClicked: emojiSearch.clear()
2021-07-03 23:45:36 +03:00
anchors {
right: parent.right
2022-04-16 03:13:01 +03:00
verticalCenter: parent.verticalCenter
2021-07-03 23:45:36 +03:00
}
// clear the default hover effects.
Image {
height: parent.height - 2 * Nheko.paddingSmall
2022-04-15 06:53:41 +03:00
source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.placeholderText)
2022-04-16 03:13:01 +03:00
width: height
2021-07-03 23:45:36 +03:00
anchors {
margins: Nheko.paddingSmall
2022-04-16 03:13:01 +03:00
right: parent.right
verticalCenter: parent.verticalCenter
2021-07-03 23:45:36 +03:00
}
}
}
}
2021-07-03 23:45:36 +03:00
// emoji grid
GridView {
id: gridView
2022-04-16 03:13:01 +03:00
Layout.leftMargin: 4
2021-07-03 23:45:36 +03:00
Layout.preferredHeight: cellHeight * 5
Layout.preferredWidth: 7 * 52 + 20
boundsBehavior: Flickable.StopAtBounds
2022-04-16 03:13:01 +03:00
cacheBuffer: 500
cellHeight: 52
cellWidth: 52
2021-07-03 23:45:36 +03:00
clip: true
currentIndex: -1 // prevent sorting from stealing focus
2020-10-08 22:11:21 +03:00
2022-04-16 03:13:01 +03:00
ScrollBar.vertical: ScrollBar {
id: emojiScroll
}
2022-01-27 03:14:18 +03:00
2021-07-03 23:45:36 +03:00
// Individual emoji
delegate: AbstractButton {
ToolTip.text: model.shortName
ToolTip.visible: hovered
2022-04-16 03:13:01 +03:00
height: 48
hoverEnabled: true
width: 48
background: Rectangle {
anchors.fill: parent
color: hovered ? timelineRoot.palette.highlight : 'transparent'
radius: 5
2021-07-03 23:45:36 +03:00
}
// give the emoji a little oomf
2022-01-27 03:14:18 +03:00
// DropShadow {
// width: parent.width
// height: parent.height
// horizontalOffset: 3
// verticalOffset: 3
// radius: 8
// samples: 17
// color: "#80000000"
// source: parent.contentItem
// }
2021-07-03 23:45:36 +03:00
contentItem: Text {
2022-04-16 03:13:01 +03:00
color: timelineRoot.palette.text
2021-07-03 23:45:36 +03:00
font.family: Settings.emojiFont
font.pixelSize: 36
2022-04-16 03:13:01 +03:00
horizontalAlignment: Text.AlignHCenter
text: model.unicode.replace('\ufe0f', '')
2022-04-16 03:13:01 +03:00
verticalAlignment: Text.AlignVCenter
2021-07-03 23:45:36 +03:00
}
2022-04-16 03:13:01 +03:00
// TODO: maybe add favorites at some point?
onClicked: {
console.debug("Picked " + model.unicode);
emojiPopup.close();
callback(model.unicode);
2021-07-03 23:45:36 +03:00
}
}
}
2021-07-03 23:45:36 +03:00
// Separator
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: emojiPopup.Nheko.theme.separator
2022-04-16 03:13:01 +03:00
visible: emojiSearch.text === ''
2020-10-08 22:11:21 +03:00
}
2021-07-03 23:45:36 +03:00
// Category picker row
RowLayout {
2022-04-16 03:13:01 +03:00
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
2021-07-03 23:45:36 +03:00
Layout.bottomMargin: 0
Layout.preferredHeight: 42
implicitHeight: 42
2022-04-16 03:13:01 +03:00
visible: emojiSearch.text === ''
2021-07-03 23:45:36 +03:00
// Display the normal categories
Repeater {
model: [
2021-07-03 23:45:36 +03:00
// TODO: Would like to get 'simple' icons for the categories
{
2022-04-16 03:13:01 +03:00
"image": ":/icons/icons/emoji-categories/people.svg",
"category": Emoji.Category.People
}, {
"image": ":/icons/icons/emoji-categories/nature.svg",
"category": Emoji.Category.Nature
}, {
"image": ":/icons/icons/emoji-categories/foods.svg",
"category": Emoji.Category.Food
}, {
"image": ":/icons/icons/emoji-categories/activity.svg",
"category": Emoji.Category.Activity
}, {
"image": ":/icons/icons/emoji-categories/travel.svg",
"category": Emoji.Category.Travel
}, {
"image": ":/icons/icons/emoji-categories/objects.svg",
"category": Emoji.Category.Objects
}, {
"image": ":/icons/icons/emoji-categories/symbols.svg",
"category": Emoji.Category.Symbols
}, {
"image": ":/icons/icons/emoji-categories/flags.svg",
"category": Emoji.Category.Flags
}]
2020-10-08 22:11:21 +03:00
2021-07-03 23:45:36 +03:00
delegate: AbstractButton {
Layout.preferredHeight: 36
2022-04-16 03:13:01 +03:00
Layout.preferredWidth: 36
2021-07-03 23:45:36 +03:00
ToolTip.text: {
switch (modelData.category) {
2021-07-03 23:45:36 +03:00
case Emoji.Category.People:
return qsTr('People');
case Emoji.Category.Nature:
return qsTr('Nature');
case Emoji.Category.Food:
return qsTr('Food');
case Emoji.Category.Activity:
return qsTr('Activity');
case Emoji.Category.Travel:
return qsTr('Travel');
case Emoji.Category.Objects:
return qsTr('Objects');
case Emoji.Category.Symbols:
return qsTr('Symbols');
case Emoji.Category.Flags:
return qsTr('Flags');
}
}
ToolTip.visible: hovered
2022-04-16 03:13:01 +03:00
hoverEnabled: true
2022-04-16 03:13:01 +03:00
background: Rectangle {
2021-07-03 23:45:36 +03:00
anchors.fill: parent
2022-04-16 03:13:01 +03:00
border.color: emojiPopup.model.category === modelData.category ? timelineRoot.palette.highlight : 'transparent'
color: emojiPopup.model.category === modelData.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : 'transparent'
radius: 5
2020-10-08 22:11:21 +03:00
}
2021-07-03 23:45:36 +03:00
contentItem: Image {
fillMode: Image.Pad
2022-01-03 00:13:15 +03:00
height: 32
2022-04-16 03:13:01 +03:00
horizontalAlignment: Image.AlignHCenter
2022-01-03 00:13:15 +03:00
mipmap: true
2022-04-16 03:13:01 +03:00
smooth: true
2022-04-15 06:53:41 +03:00
source: "image://colorimage/" + modelData.image + "?" + (hovered ? timelineRoot.palette.highlight : timelineRoot.palette.placeholderText)
2022-04-16 03:13:01 +03:00
sourceSize.height: 32 * Screen.devicePixelRatio
sourceSize.width: 32 * Screen.devicePixelRatio
verticalAlignment: Image.AlignVCenter
width: 32
2021-07-03 23:45:36 +03:00
}
2022-04-16 03:13:01 +03:00
onClicked: {
//emojiPopup.model.category = model.category;
gridView.positionViewAtIndex(emojiPopup.model.sourceModel.categoryToIndex(modelData.category), GridView.Beginning);
2021-07-03 23:45:36 +03:00
}
2022-04-16 03:13:01 +03:00
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
2022-04-16 03:13:01 +03:00
onPressed: mouse.accepted = false
}
}
2020-05-14 03:19:15 +03:00
}
}
}
}
}