2020-07-02 17:48:06 +00:00
import QtQuick 2.13
import QtQuick . Controls 2.13
import QtQuick . Layouts 1.3
import QtGraphicalEffects 1.0
import "../../../../imports"
import "../../../../shared"
import "../ChatColumn/samples"
import "./emojiList.js" as EmojiJSON
Popup {
2020-07-02 18:49:02 +00:00
property var addToChat: function ( ) { }
2020-07-28 20:10:38 +00:00
property var categories: [ ]
2020-07-29 17:16:21 +00:00
property string searchString: searchBox . text
2020-07-02 18:49:02 +00:00
2020-07-02 17:48:06 +00:00
id: popup
modal: false
2020-07-28 20:10:38 +00:00
width: 360
2020-07-02 17:48:06 +00:00
closePolicy: Popup . CloseOnEscape | Popup . CloseOnPressOutsideParent
background: Rectangle {
2020-07-22 20:16:06 +00:00
radius: Style . current . radius
color: Style . current . background
border.color: Style . current . border
2020-07-02 17:48:06 +00:00
layer.enabled: true
layer.effect: DropShadow {
verticalOffset: 3
radius: 8
samples: 15
fast: true
cached: true
color: "#22000000"
}
}
2020-07-29 19:03:10 +00:00
function addEmoji ( emoji ) {
const MAX_EMOJI_NUMBER = 36
const extenstionIndex = emoji . filename . lastIndexOf ( '.' ) ;
let iconCodePoint = emoji . filename
if ( extenstionIndex > - 1 ) {
iconCodePoint = iconCodePoint . substring ( 0 , extenstionIndex )
}
// Split the filename to get all the parts and then encode them from hex to utf8
const splitCodePoint = iconCodePoint . split ( '-' )
let codePointParts = [ ]
splitCodePoint . forEach ( function ( codePoint ) {
codePointParts . push ( ` 0 x $ { codePoint } ` )
} )
const encodedIcon = String . fromCodePoint ( . . . codePointParts ) ;
// Add at the start of the list
appSettings . recentEmojis . unshift ( emoji )
// Remove duplicates
appSettings . recentEmojis = appSettings . recentEmojis . filter ( function ( e , index ) {
return ! appSettings . recentEmojis . some ( function ( e2 , index2 ) {
return index2 < index && e2 . filename === e . filename
} )
} )
if ( appSettings . recentEmojis . length > MAX_EMOJI_NUMBER ) {
//remove last one
appSettings . recentEmojis . splice ( MAX_EMOJI_NUMBER - 1 )
}
emojiSectionsRepeater . itemAt ( 0 ) . allEmojis = appSettings . recentEmojis
2020-07-31 21:30:55 +00:00
popup . addToChat ( Emoji . parse ( encodedIcon , "26x26" ) + ' ' ) // Adding a space because otherwise, some emojis would fuse since it's just an emoji is just a string
2020-07-29 19:03:10 +00:00
popup . close ( )
2020-07-31 21:30:55 +00:00
chatInput . textInput . forceActiveFocus ( )
2020-07-29 19:03:10 +00:00
}
2020-07-02 17:48:06 +00:00
Component.onCompleted: {
2020-07-28 20:10:38 +00:00
var categoryNames = { "recent" : 0 }
var newCategories = [ [ ] ]
2020-07-02 17:48:06 +00:00
EmojiJSON . emoji_json . forEach ( function ( emoji ) {
2020-07-28 20:10:38 +00:00
if ( ! categoryNames [ emoji . category ] && categoryNames [ emoji . category ] !== 0 ) {
categoryNames [ emoji . category ] = newCategories . length
newCategories . push ( [ ] )
}
2020-07-29 19:03:10 +00:00
newCategories [ categoryNames [ emoji . category ] ] . push ( Object . assign ( { } , emoji , { filename: emoji . unicode + '.png' } ) )
2020-07-02 17:48:06 +00:00
} )
2020-07-29 19:03:10 +00:00
// Add recent
appSettings . recentEmojis . forEach ( function ( emoji ) {
newCategories [ categoryNames . recent ] . push ( Object . assign ( { } , emoji , { category: "recent" } ) )
} )
2020-07-28 20:10:38 +00:00
if ( newCategories [ categoryNames . recent ] . length === 0 ) {
newCategories [ categoryNames . recent ] . push ( {
category: "recent" ,
empty: true
} )
}
categories = newCategories
2020-07-02 17:48:06 +00:00
}
2020-07-29 17:16:21 +00:00
onOpened: {
searchBox . forceActiveFocus ( Qt . MouseFocusReason )
}
2020-07-02 17:48:06 +00:00
contentItem: ColumnLayout {
anchors.fill: parent
spacing: 0
Item {
2020-07-28 20:10:38 +00:00
property int headerMargin: 8
id: emojiHeader
Layout.fillWidth: true
height: searchBox . height + emojiHeader . headerMargin
SearchBox {
id: searchBox
anchors.right: skinToneEmoji . left
anchors.rightMargin: emojiHeader . headerMargin
anchors.top: parent . top
anchors.topMargin: emojiHeader . headerMargin
anchors.left: parent . left
anchors.leftMargin: emojiHeader . headerMargin
}
SVGImage {
id: skinToneEmoji
width: 22
height: 22
anchors.verticalCenter: searchBox . verticalCenter
anchors.right: parent . right
anchors.rightMargin: emojiHeader . headerMargin
source: "../../../../imports/twemoji/26x26/1f590.png"
MouseArea {
cursorShape: Qt . PointingHandCursor
anchors.fill: parent
onClicked: function ( ) {
console . log ( 'Change skin tone' )
}
}
}
}
ScrollView {
property ScrollBar vScrollBar: ScrollBar . vertical
property var categrorySectionHeightRatios: [ ]
property int activeCategory: 0
id: scrollView
topPadding: Style . current . smallPadding
leftPadding: Style . current . smallPadding
rightPadding: Style . current . smallPadding / 2
2020-07-02 17:48:06 +00:00
Layout.fillWidth: true
2020-07-28 20:10:38 +00:00
Layout.rightMargin: Style . current . smallPadding / 2
Layout.topMargin: Style . current . smallPadding
2020-07-02 17:48:06 +00:00
Layout.alignment: Qt . AlignTop | Qt . AlignLeft
2020-07-28 20:10:38 +00:00
Layout.preferredHeight: 400 - Style . current . smallPadding - emojiHeader . height
clip: true
ScrollBar.vertical.policy: ScrollBar . AlwaysOn
ScrollBar.horizontal.policy: ScrollBar . AlwaysOff
ScrollBar.vertical.onPositionChanged: function ( ) {
if ( vScrollBar . position < categrorySectionHeightRatios [ scrollView . activeCategory - 1 ] ) {
scrollView . activeCategory --
} else if ( vScrollBar . position > categrorySectionHeightRatios [ scrollView . activeCategory ] ) {
scrollView . activeCategory ++
}
}
function scrollToCategory ( category ) {
if ( category === 0 ) {
return vScrollBar . setPosition ( 0 )
}
vScrollBar . setPosition ( categrorySectionHeightRatios [ category - 1 ] )
}
contentHeight: {
var totalHeight = 0
var categoryHeights = [ ]
for ( let i = 0 ; i < emojiSectionsRepeater . count ; i ++ ) {
totalHeight += emojiSectionsRepeater . itemAt ( i ) . height + Style . current . padding
categoryHeights . push ( totalHeight )
}
var ratios = [ ]
categoryHeights . forEach ( function ( catHeight ) {
ratios . push ( catHeight / totalHeight )
} )
categrorySectionHeightRatios = ratios
return totalHeight + Style . current . padding
}
Repeater {
id: emojiSectionsRepeater
model: popup . categories
2020-07-29 17:16:21 +00:00
EmojiSection {
searchString: popup . searchString
2020-07-29 19:03:10 +00:00
addEmoji: popup . addEmoji
2020-07-29 17:16:21 +00:00
}
2020-07-28 20:10:38 +00:00
}
}
Row {
Layout.fillWidth: true
height: 40
leftPadding: Style . current . smallPadding / 2
rightPadding: Style . current . smallPadding / 2
spacing: 0
Repeater {
model: EmojiJSON . emojiCategories
EmojiCategoryButton {
source: ` . . / . . / . . / img / emojiCategories / $ { modelData } . svg `
active: index === scrollView . activeCategory
changeCategory: function ( ) {
scrollView . activeCategory = index
scrollView . scrollToCategory ( index )
2020-07-02 17:48:06 +00:00
}
}
}
}
}
}
/ * # # ^ # #
Designer {
D { i: 0 ; formeditorColor: "#ffffff" ; height: 440 ; width: 360 }
}
# # ^ # # * /