feat: Add emoji support (#575)
* feat: Add emoji support 1. StatusChatListItem (only updated parts already done by Jo) 2. StatusListItem 3. StatusInput * feat(StatusColorSelectorGrid): Added new widget for color selection as needed in wallet * fix(StatusInput): on reset, valid should be set to true else error mode is shown even though the user hasnt entered a value * fix(StatusLetterIdenticon): Removed the clicked event out from the LetterIdenticon and added it to the StatusBaseInput as other places that use the letterIdenticon dont need the mouse area is not needed
This commit is contained in:
parent
ae3bb01c10
commit
0b4941966e
|
@ -67,7 +67,7 @@ GridLayout {
|
|||
StatusChatListItem {
|
||||
name: "community-channel-emoji"
|
||||
type: StatusChatListItem.Type.CommunityChat
|
||||
emoji: "😁"
|
||||
icon.emoji: "😁"
|
||||
}
|
||||
|
||||
StatusChatListItem {
|
||||
|
@ -338,6 +338,15 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
|||
}
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
title: "List Item with Emoji"
|
||||
subTitle: "Emoji"
|
||||
icon.emoji: "😁"
|
||||
icon.color: "yellow"
|
||||
icon.letterSize: 14
|
||||
icon.isLetterIdenticon: true
|
||||
}
|
||||
|
||||
StatusDescriptionListItem {
|
||||
title: "Title"
|
||||
subTitle: "Subtitle"
|
||||
|
|
|
@ -293,6 +293,11 @@ StatusWindow {
|
|||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusColorSelectorGrid"
|
||||
selected: viewLoader.source.toString().includes(title)
|
||||
onClicked: mainPageView.page(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 800
|
||||
height: 100
|
||||
|
||||
Row {
|
||||
id: selectedColor
|
||||
anchors.top: parent.top
|
||||
anchors.left: colorSelectionGrid.left
|
||||
spacing: 10
|
||||
StatusBaseText {
|
||||
text: "SelectedColor is"
|
||||
}
|
||||
Rectangle {
|
||||
width: 100
|
||||
height: 20
|
||||
radius: width/2
|
||||
color: colorSelectionGrid.selectedColor
|
||||
}
|
||||
}
|
||||
|
||||
StatusColorSelectorGrid {
|
||||
id: colorSelectionGrid
|
||||
anchors.top: selectedColor.bottom
|
||||
anchors.topMargin: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
titleText: "COLOR"
|
||||
selectedColorIndex: 2
|
||||
}
|
||||
}
|
|
@ -130,4 +130,27 @@ Column {
|
|||
input.minimumHeight: 80
|
||||
input.maximumHeight: 200
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
label: "Input with emoji icon"
|
||||
input.placeholderText: "Enter Name"
|
||||
input.icon.emoji: "😁"
|
||||
input.icon.color: "blue"
|
||||
input.isIconSelectable: true
|
||||
onIconClicked: {
|
||||
// launch emoji popup
|
||||
}
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
label: "Input with selectable icon which is not an emoji"
|
||||
input.placeholderText: "Enter Name"
|
||||
input.icon.emoji: ""
|
||||
input.icon.name: "filled-account"
|
||||
input.icon.color: "blue"
|
||||
input.isIconSelectable: true
|
||||
onIconClicked: {
|
||||
// launch emoji popup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ Column {
|
|||
chatId: model.itemId
|
||||
categoryId: model.parentItemId? model.parentItemId : ""
|
||||
name: model.name
|
||||
emoji: model.emoji
|
||||
icon.emoji: model.emoji
|
||||
type: !!model.type ? model.type : StatusChatListItem.Type.CommunityChat
|
||||
muted: model.muted
|
||||
hasUnreadMessages: model.hasUnreadMessages
|
||||
|
|
|
@ -16,7 +16,6 @@ Rectangle {
|
|||
property string chatId: ""
|
||||
property string categoryId: ""
|
||||
property string name: ""
|
||||
property string emoji: ""
|
||||
property alias badge: statusBadge
|
||||
property bool hasUnreadMessages: false
|
||||
property int notificationsCount: 0
|
||||
|
@ -30,6 +29,7 @@ Rectangle {
|
|||
height: 24
|
||||
color: Theme.palette.miscColor5
|
||||
letterSize: emoji ? 14 : 15
|
||||
emoji: ""
|
||||
}
|
||||
property int type: StatusChatListItem.Type.PublicChat
|
||||
property bool highlighted: false
|
||||
|
@ -86,7 +86,6 @@ Rectangle {
|
|||
image: statusChatListItem.image
|
||||
icon: statusChatListItem.icon
|
||||
name: statusChatListItem.name
|
||||
emoji: statusChatListItem.emoji
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
|
|
|
@ -21,7 +21,10 @@ Rectangle {
|
|||
id: identiconText
|
||||
text: {
|
||||
if (emoji) {
|
||||
return Emoji.parse(emoji)
|
||||
if(Utils.isHtml(emoji))
|
||||
return emoji
|
||||
else
|
||||
return Emoji.parse(emoji)
|
||||
}
|
||||
return (((statusLetterIdenticon.name.charAt(0) === "#")
|
||||
|| (statusLetterIdenticon.name.charAt(0) === "@") ?
|
||||
|
@ -31,6 +34,9 @@ Rectangle {
|
|||
font.weight: Font.Bold
|
||||
font.pixelSize: statusLetterIdenticon.letterSize
|
||||
color: Qt.rgba(255, 255, 255, 0.7)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.alignWhenCentered: false
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ Loader {
|
|||
|
||||
property string name: ""
|
||||
property int charCount: 1
|
||||
property string emoji: ""
|
||||
property int dZ: 100
|
||||
|
||||
// Badge color properties must be set if badgeItem.visible = true
|
||||
|
@ -85,7 +84,7 @@ Loader {
|
|||
height: statusSmartIdenticon.icon.height
|
||||
color: statusSmartIdenticon.icon.color
|
||||
name: statusSmartIdenticon.name
|
||||
emoji: statusSmartIdenticon.emoji
|
||||
emoji: statusSmartIdenticon.icon.emoji
|
||||
letterSize: statusSmartIdenticon.icon.letterSize
|
||||
charCount: statusSmartIdenticon.charCount
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.14
|
|||
|
||||
import QtQuick.Controls 2.14 as QC
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
@ -49,16 +50,26 @@ Item {
|
|||
property bool dirty: false
|
||||
property bool pending: false
|
||||
property bool leftIcon: true
|
||||
property bool isIconSelectable: false
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
name: ""
|
||||
color: Theme.palette.baseColor1
|
||||
emoji: ""
|
||||
letterSize: 14
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 30
|
||||
height: 30
|
||||
color: Theme.palette.indirectColor1
|
||||
}
|
||||
}
|
||||
|
||||
property Item component
|
||||
|
||||
signal iconClicked()
|
||||
|
||||
onClearableChanged: {
|
||||
if (clearable && !component) {
|
||||
clearButtonLoader.active = true
|
||||
|
@ -109,6 +120,29 @@ Item {
|
|||
edit.forceActiveFocus()
|
||||
}
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: emoji
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon.width: !statusBaseInput.icon.emoji ? 20 : 30
|
||||
icon.height: !statusBaseInput.icon.emoji ? 20 : 30
|
||||
icon.background: statusBaseInput.icon.background
|
||||
icon.color: statusBaseInput.icon.color
|
||||
icon.letterSize: statusBaseInput.icon.letterSize
|
||||
icon.emoji: statusBaseInput.icon.emoji
|
||||
icon.name: !statusBaseInput.icon.emoji ? statusBaseInput.icon.name : ""
|
||||
visible: (!!statusBaseInput.icon.emoji || !!statusBaseInput.icon.name) && statusBaseInput.isIconSelectable
|
||||
MouseArea {
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
enabled: emoji.visible
|
||||
onClicked: statusBaseInput.iconClicked()
|
||||
}
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
anchors.topMargin: 10
|
||||
|
@ -121,7 +155,7 @@ Item {
|
|||
width: statusBaseInput.icon.width
|
||||
height: statusBaseInput.icon.height
|
||||
color: statusBaseInput.icon.color
|
||||
visible: !!statusBaseInput.icon.name
|
||||
visible: !!statusBaseInput.icon.name && !statusBaseInput.isIconSelectable
|
||||
}
|
||||
|
||||
Flickable {
|
||||
|
@ -129,7 +163,7 @@ Item {
|
|||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: (statusIcon.visible && statusBaseInput.leftIcon) ?
|
||||
statusIcon.right : parent.left
|
||||
statusIcon.right : emoji.visible ? emoji.right: parent.left
|
||||
anchors.right: {
|
||||
if (!!statusBaseInput.component) {
|
||||
return statusBaseInputComponentSlot.left
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
RadioButton {
|
||||
id: control
|
||||
|
||||
property string radioButtonColor: ""
|
||||
property string selectionColor: StatusColors.colors['white']
|
||||
|
||||
implicitWidth: 48
|
||||
implicitHeight: 48
|
||||
|
||||
indicator: Rectangle {
|
||||
implicitWidth: 48
|
||||
implicitHeight: 48
|
||||
radius: width/2
|
||||
color: radioButtonColor
|
||||
|
||||
Rectangle {
|
||||
width: 20
|
||||
height: 20
|
||||
radius: width/2
|
||||
color: selectionColor
|
||||
border.color: StatusColors.colors['grey3']
|
||||
visible: control.checked
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import QtQuick 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import "./"
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
property alias titleText: title.text
|
||||
property alias title: title
|
||||
|
||||
property int selectedColorIndex: 0
|
||||
property string selectedColor: ""
|
||||
property var model: [StatusColors.colors['black'],
|
||||
StatusColors.colors['grey'],
|
||||
StatusColors.colors['blue2'],
|
||||
StatusColors.colors['purple'],
|
||||
StatusColors.colors['cyan'],
|
||||
StatusColors.colors['violet'],
|
||||
StatusColors.colors['red2'],
|
||||
StatusColors.colors['yellow'],
|
||||
StatusColors.colors['green2'],
|
||||
StatusColors.colors['moss'],
|
||||
StatusColors.colors['brown'],
|
||||
StatusColors.colors['brown2']]
|
||||
|
||||
spacing: 16
|
||||
|
||||
StatusBaseText {
|
||||
id: title
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
Grid {
|
||||
columns: 6
|
||||
rowSpacing: 16
|
||||
columnSpacing: 32
|
||||
Repeater {
|
||||
model: root.model
|
||||
delegate: StatusColorRadioButton {
|
||||
checked: index === selectedColorIndex
|
||||
radioButtonColor: root.model[index] || "transparent"
|
||||
onCheckedChanged: {
|
||||
if(checked) {
|
||||
selectedColorIndex = index
|
||||
selectedColor = root.model[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,8 @@ Item {
|
|||
|
||||
property var pendingValidators: []
|
||||
|
||||
signal iconClicked()
|
||||
|
||||
enum ValidationMode {
|
||||
OnlyWhenDirty, // validates input only after it has become dirty
|
||||
Always // validates input even before it has become dirty
|
||||
|
@ -49,7 +51,7 @@ Item {
|
|||
property var asyncErrors: ({})
|
||||
|
||||
function reset() {
|
||||
statusBaseInput.valid = false
|
||||
statusBaseInput.valid = true
|
||||
statusBaseInput.pristine = true
|
||||
statusBaseInput.text = ""
|
||||
root.errorMessage = ""
|
||||
|
@ -189,6 +191,7 @@ Item {
|
|||
onTextChanged: root.validate()
|
||||
|
||||
Keys.forwardTo: [root]
|
||||
onIconClicked: root.iconClicked()
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
|
|
|
@ -33,3 +33,4 @@ StatusSwitchTabBar 0.1 StatusSwitchTabBar.qml
|
|||
StatusSelectableText 0.1 StatusSelectableText.qml
|
||||
StatusWalletColorButton 0.1 StatusWalletColorButton.qml
|
||||
StatusWalletColorSelect 0.1 StatusWalletColorSelect.qml
|
||||
StatusColorSelectorGrid 0.1 StatusColorSelectorGrid.qml
|
||||
|
|
|
@ -13,5 +13,6 @@ QtObject {
|
|||
property int rotation
|
||||
property bool isLetterIdenticon
|
||||
property int letterSize
|
||||
property string emoji
|
||||
property StatusIconBackgroundSettings background: StatusIconBackgroundSettings {}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import QtQuick 2.13
|
|||
|
||||
//import shared.status 1.0
|
||||
import "../../../assets/twemoji/twemoji.js" as Twemoji
|
||||
import "./emojiList.js" as EmojiJSON
|
||||
|
||||
QtObject {
|
||||
readonly property var size: {
|
||||
|
@ -94,4 +95,24 @@ QtObject {
|
|||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function getRandomEmoji() {
|
||||
var randomEmoji = EmojiJSON.emoji_json[Math.floor(Math.random() * EmojiJSON.emoji_json.length)]
|
||||
|
||||
const extenstionIndex = randomEmoji.unicode.lastIndexOf('.');
|
||||
let iconCodePoint = randomEmoji.unicode
|
||||
if (extenstionIndex > -1) {
|
||||
iconCodePoint = iconCodePoint.substring(0, extenstionIndex)
|
||||
}
|
||||
|
||||
// Split the unicode 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(`0x${codePoint}`)
|
||||
})
|
||||
const encodedIcon = String.fromCodePoint(...codePointParts);
|
||||
|
||||
return Emoji.parse(encodedIcon) + ' '
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,10 @@ QtObject {
|
|||
}
|
||||
return strNumber.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1')
|
||||
}
|
||||
|
||||
function isHtml(text) {
|
||||
return (/<\/?[a-z][\s\S]*>/i.test(text))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue