diff --git a/sandbox/controls/ListItems.qml b/sandbox/controls/ListItems.qml index 32c2d83a..0de9e62e 100644 --- a/sandbox/controls/ListItems.qml +++ b/sandbox/controls/ListItems.qml @@ -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" diff --git a/sandbox/main.qml b/sandbox/main.qml index 0bd1fb34..608f01b5 100644 --- a/sandbox/main.qml +++ b/sandbox/main.qml @@ -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); + } } } } diff --git a/sandbox/pages/StatusColorSelectorGridPage.qml b/sandbox/pages/StatusColorSelectorGridPage.qml new file mode 100644 index 00000000..e1d73255 --- /dev/null +++ b/sandbox/pages/StatusColorSelectorGridPage.qml @@ -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 + } +} diff --git a/sandbox/pages/StatusInputPage.qml b/sandbox/pages/StatusInputPage.qml index 2be5b7d3..6c16f5aa 100644 --- a/sandbox/pages/StatusInputPage.qml +++ b/sandbox/pages/StatusInputPage.qml @@ -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 + } + } } diff --git a/src/StatusQ/Components/StatusChatList.qml b/src/StatusQ/Components/StatusChatList.qml index a5152506..6ac009e8 100644 --- a/src/StatusQ/Components/StatusChatList.qml +++ b/src/StatusQ/Components/StatusChatList.qml @@ -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 diff --git a/src/StatusQ/Components/StatusChatListItem.qml b/src/StatusQ/Components/StatusChatListItem.qml index 51f2bf22..b27a232c 100644 --- a/src/StatusQ/Components/StatusChatListItem.qml +++ b/src/StatusQ/Components/StatusChatListItem.qml @@ -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 { diff --git a/src/StatusQ/Components/StatusLetterIdenticon.qml b/src/StatusQ/Components/StatusLetterIdenticon.qml index a31336b8..26a0ae74 100644 --- a/src/StatusQ/Components/StatusLetterIdenticon.qml +++ b/src/StatusQ/Components/StatusLetterIdenticon.qml @@ -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 } diff --git a/src/StatusQ/Components/StatusSmartIdenticon.qml b/src/StatusQ/Components/StatusSmartIdenticon.qml index ecef87cc..c915f048 100644 --- a/src/StatusQ/Components/StatusSmartIdenticon.qml +++ b/src/StatusQ/Components/StatusSmartIdenticon.qml @@ -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 } diff --git a/src/StatusQ/Controls/StatusBaseInput.qml b/src/StatusQ/Controls/StatusBaseInput.qml index 7a649c2e..a14df161 100644 --- a/src/StatusQ/Controls/StatusBaseInput.qml +++ b/src/StatusQ/Controls/StatusBaseInput.qml @@ -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 diff --git a/src/StatusQ/Controls/StatusColorRadioButton.qml b/src/StatusQ/Controls/StatusColorRadioButton.qml new file mode 100644 index 00000000..489b8b12 --- /dev/null +++ b/src/StatusQ/Controls/StatusColorRadioButton.qml @@ -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 + } + } +} + diff --git a/src/StatusQ/Controls/StatusColorSelectorGrid.qml b/src/StatusQ/Controls/StatusColorSelectorGrid.qml new file mode 100644 index 00000000..fcdd599c --- /dev/null +++ b/src/StatusQ/Controls/StatusColorSelectorGrid.qml @@ -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] + } + } + } + } + } +} diff --git a/src/StatusQ/Controls/StatusInput.qml b/src/StatusQ/Controls/StatusInput.qml index ef2af1ec..2fe235d2 100644 --- a/src/StatusQ/Controls/StatusInput.qml +++ b/src/StatusQ/Controls/StatusInput.qml @@ -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 { diff --git a/src/StatusQ/Controls/qmldir b/src/StatusQ/Controls/qmldir index 20971b9b..f4512cf5 100644 --- a/src/StatusQ/Controls/qmldir +++ b/src/StatusQ/Controls/qmldir @@ -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 diff --git a/src/StatusQ/Core/StatusIconSettings.qml b/src/StatusQ/Core/StatusIconSettings.qml index 53b9f3e2..4898a66a 100644 --- a/src/StatusQ/Core/StatusIconSettings.qml +++ b/src/StatusQ/Core/StatusIconSettings.qml @@ -13,5 +13,6 @@ QtObject { property int rotation property bool isLetterIdenticon property int letterSize + property string emoji property StatusIconBackgroundSettings background: StatusIconBackgroundSettings {} } diff --git a/src/StatusQ/Core/Utils/Emoji.qml b/src/StatusQ/Core/Utils/Emoji.qml index a989a774..b5738970 100644 --- a/src/StatusQ/Core/Utils/Emoji.qml +++ b/src/StatusQ/Core/Utils/Emoji.qml @@ -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) + ' ' + } } diff --git a/src/StatusQ/Core/Utils/Utils.qml b/src/StatusQ/Core/Utils/Utils.qml index f82f2f90..e46a33f6 100644 --- a/src/StatusQ/Core/Utils/Utils.qml +++ b/src/StatusQ/Core/Utils/Utils.qml @@ -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)) + } }