mirror of
https://github.com/overte-org/overte.git
synced 2025-05-07 04:50:00 +02:00
299 lines
No EOL
9.8 KiB
QML
299 lines
No EOL
9.8 KiB
QML
//
|
|
// SimplifiedEmoji.qml
|
|
//
|
|
// Created by Milad Nazeri on 2019-08-03
|
|
// Copyright 2019 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
import QtQuick 2.12
|
|
import QtQuick.Controls 2.4
|
|
import QtGraphicalEffects 1.12
|
|
import stylesUit 1.0 as HifiStylesUit
|
|
import TabletScriptingInterface 1.0
|
|
import hifi.simplifiedUI.simplifiedControls 1.0 as SimplifiedControls
|
|
import hifi.simplifiedUI.simplifiedConstants 1.0 as SimplifiedConstants
|
|
import "../../resources/modules/emojiList.js" as EmojiList
|
|
import "../../resources/modules/customEmojiList.js" as CustomEmojiList
|
|
import "./ProgressCircle"
|
|
|
|
Rectangle {
|
|
id: root
|
|
color: simplifiedUI.colors.darkBackground
|
|
anchors.fill: parent
|
|
|
|
// Used for the indicator picture
|
|
readonly property string emojiBaseURL: "../../resources/images/emojis/1024px/"
|
|
readonly property string emoji52BaseURL: "../../resources/images/emojis/52px/"
|
|
// Capture the selected code to handle which emoji to show
|
|
property string currentCode: ""
|
|
// if this is true, then hovering doesn't allow showing other icons
|
|
property bool isSelected: false
|
|
|
|
// Update the selected emoji image whenever the code property is changed.
|
|
onCurrentCodeChanged: {
|
|
mainEmojiImage.source = emojiBaseURL + currentCode;
|
|
}
|
|
|
|
SimplifiedConstants.SimplifiedConstants {
|
|
id: simplifiedUI
|
|
}
|
|
|
|
focus: true
|
|
|
|
ListModel {
|
|
id: mainModel
|
|
}
|
|
|
|
ListModel {
|
|
id: filteredModel
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
emojiSearchTextField.forceActiveFocus();
|
|
/*
|
|
MILAD NOTE:
|
|
The emoji list we have is a node transformed list of all the UTF emojis with meta info.
|
|
To cut down on the list, this is a good place to start as they will be 90% of the emojis anyone would
|
|
want to use.
|
|
|
|
To save some space, we should probably remove any images from the current ones that aren't the below emojis.
|
|
Let's make a separate ticket for this as this is going to need a little work in the current node app. Not much
|
|
but I didn't want to focus on it for this sprint.
|
|
|
|
I can also prune that large emoji json as well to have only the ones we want listed. That can be added to that
|
|
ticket as well. This is something I can probably knock out on the plane to Italy becaues I don't want those large
|
|
files to be in the repo or loading that big config.json file.
|
|
*/
|
|
EmojiList.emojiList
|
|
.filter(emoji => {
|
|
return emoji.mainCategory === "Smileys & Emotion" ||
|
|
emoji.mainCategory === "People & Body" ||
|
|
emoji.mainCategory === "Animals & Nature" ||
|
|
emoji.mainCategory === "Food & Drink";
|
|
})
|
|
// Convert the filtered list to seed our QML Model used for our view
|
|
.forEach(function(item, index){
|
|
item.code = { utf: item.code[0] }
|
|
item.keywords = { keywords: item.keywords }
|
|
mainModel.append(item);
|
|
filteredModel.append(item);
|
|
});
|
|
CustomEmojiList.customEmojiList
|
|
.forEach(function(item, index){
|
|
item.code = { utf: item.name }
|
|
item.keywords = { keywords: item.keywords }
|
|
mainModel.append(item);
|
|
filteredModel.append(item);
|
|
});
|
|
|
|
root.currentCode = filteredModel.get(0).code.utf;
|
|
}
|
|
|
|
Rectangle {
|
|
id: emojiIndicatorContainer
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 200
|
|
clip: true
|
|
color: simplifiedUI.colors.darkBackground
|
|
|
|
Image {
|
|
id: mainEmojiLowOpacity
|
|
width: 180
|
|
height: 180
|
|
anchors.centerIn: parent
|
|
source: mainEmojiImage.source
|
|
opacity: 0.5
|
|
fillMode: Image.PreserveAspectFit
|
|
visible: true
|
|
mipmap: true
|
|
}
|
|
|
|
Image {
|
|
id: mainEmojiImage
|
|
width: 180
|
|
height: 180
|
|
anchors.centerIn: parent
|
|
source: ""
|
|
fillMode: Image.PreserveAspectFit
|
|
visible: false
|
|
mipmap: true
|
|
}
|
|
|
|
// The overlay used during the pie timeout
|
|
ProgressCircle {
|
|
id: progressCircle
|
|
animationDuration: 7000 // Must match `TOTAL_EMOJI_DURATION_MS` in `simplifiedEmoji.js`
|
|
anchors.centerIn: mainEmojiImage
|
|
size: mainEmojiImage.width * 2
|
|
opacity: 0.5
|
|
colorCircle: "#FFFFFF"
|
|
colorBackground: "#E6E6E6"
|
|
showBackground: false
|
|
isPie: true
|
|
arcBegin: 0
|
|
arcEnd: 360
|
|
visible: false
|
|
}
|
|
|
|
OpacityMask {
|
|
anchors.fill: mainEmojiImage
|
|
source: mainEmojiImage
|
|
maskSource: progressCircle
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: emojiIconListContainer
|
|
anchors.top: emojiIndicatorContainer.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: emojiSearchContainer.top
|
|
clip: true
|
|
color: simplifiedUI.colors.darkBackground
|
|
|
|
GridView {
|
|
id: grid
|
|
anchors.fill: parent
|
|
anchors.leftMargin: 30
|
|
anchors.rightMargin: 24
|
|
cellWidth: 60
|
|
cellHeight: 60
|
|
model: filteredModel
|
|
delegate: Image {
|
|
width: 52
|
|
height: 52
|
|
source: emoji52BaseURL + model.code.utf
|
|
fillMode: Image.PreserveAspectFit
|
|
MouseArea {
|
|
hoverEnabled: enabled
|
|
anchors.fill: parent
|
|
onEntered: {
|
|
grid.currentIndex = index
|
|
// don't allow a hover image change of the main emoji image
|
|
if (root.isSelected) {
|
|
return;
|
|
}
|
|
// Updates the selected image
|
|
root.currentCode = model.code.utf;
|
|
}
|
|
onClicked: {
|
|
sendToScript({
|
|
"source": "SimplifiedEmoji.qml",
|
|
"method": "selectedEmoji",
|
|
"code": code.utf
|
|
});
|
|
root.isSelected = true;
|
|
root.currentCode = model.code.utf;
|
|
}
|
|
}
|
|
}
|
|
cacheBuffer: 400
|
|
focus: true
|
|
highlight: Rectangle { color: Qt.rgba(1, 1, 1, 0.4); radius: 0 }
|
|
}
|
|
|
|
SimplifiedControls.VerticalScrollBar {
|
|
parent: grid
|
|
anchors.rightMargin: -grid.anchors.rightMargin + 2
|
|
}
|
|
}
|
|
|
|
|
|
Item {
|
|
id: emojiSearchContainer
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
height: 40
|
|
|
|
SimplifiedControls.TextField {
|
|
id: emojiSearchTextField
|
|
placeholderText: "Search"
|
|
maximumLength: 100
|
|
clip: true
|
|
selectByMouse: true
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 16
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 16
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
onTextChanged: {
|
|
if (text.length === 0) {
|
|
root.filterEmoji(emojiSearchTextField.text);
|
|
} else {
|
|
waitForMoreInputTimer.restart();
|
|
}
|
|
}
|
|
onAccepted: {
|
|
root.filterEmoji(emojiSearchTextField.text);
|
|
}
|
|
onFocusChanged: {
|
|
emojiSearchTextField.autoScroll = focus;
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: waitForMoreInputTimer
|
|
repeat: false
|
|
running: false
|
|
triggeredOnStart: false
|
|
interval: 300
|
|
|
|
onTriggered: {
|
|
root.filterEmoji(emojiSearchTextField.text);
|
|
}
|
|
}
|
|
}
|
|
|
|
function filterEmoji(filterText) {
|
|
filteredModel.clear();
|
|
|
|
if (filterText.length === 0) {
|
|
for (var i = 0; i < mainModel.count; i++) {
|
|
filteredModel.append(mainModel.get(i));
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < mainModel.count; i++) {
|
|
var currentObject = mainModel.get(i);
|
|
var currentKeywords = currentObject.keywords.keywords;
|
|
for (var j = 0; j < currentKeywords.length; j++) {
|
|
if ((currentKeywords[j].toLowerCase()).indexOf(filterText.toLowerCase()) > -1) {
|
|
filteredModel.append(mainModel.get(i));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
signal sendToScript(var message);
|
|
|
|
function fromScript(message) {
|
|
if (message.source !== "simplifiedEmoji.js") {
|
|
return;
|
|
}
|
|
|
|
switch(message.method) {
|
|
case "beginCountdownTimer":
|
|
progressCircle.endAnimation = true;
|
|
progressCircle.arcEnd = 0;
|
|
root.isSelected = true;
|
|
break;
|
|
case "clearCountdownTimer":
|
|
progressCircle.endAnimation = false;
|
|
progressCircle.arcEnd = 360;
|
|
progressCircle.endAnimation = true;
|
|
root.isSelected = false;
|
|
break;
|
|
default:
|
|
console.log("Message not recognized from simplifiedEmoji.js", JSON.stringify(message));
|
|
}
|
|
}
|
|
} |