diff --git a/.gitignore b/.gitignore index fbb2bbb..043d60a 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ tdlibsecrets.h #Convinience scripts *.sh + +#vscode +.vscode diff --git a/db/emojis.db b/db/emojis.db index 2b47472..602b83d 100644 Binary files a/db/emojis.db and b/db/emojis.db differ diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 0a72651..d70eb3a 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -65,6 +65,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/PollPreview.qml \ qml/components/PressEffect.qml \ qml/components/ProfilePictureList.qml \ + qml/components/ReactionButton.qml \ qml/components/ReplyMarkupButtons.qml \ qml/components/StickerPicker.qml \ qml/components/PhotoTextsListItem.qml \ diff --git a/qml/components/MessageListViewItem.qml b/qml/components/MessageListViewItem.qml index b066bcb..5b597f6 100644 --- a/qml/components/MessageListViewItem.qml +++ b/qml/components/MessageListViewItem.qml @@ -39,7 +39,7 @@ ListItem { readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_id.user_id) property QtObject precalculatedValues: ListView.view.precalculatedValues readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme.primaryColor - readonly property int textAlign: Text.AlignLeft + readonly property int textAlign: isOwnMessage ? Text.AlignRight : Text.AlignLeft readonly property Page page: precalculatedValues.page readonly property bool isSelected: messageListItem.precalculatedValues.pageIsSelecting && page.selectedMessages.some(function(existingMessage) { return existingMessage.id === messageId @@ -446,15 +446,13 @@ ListItem { anchors { left: parent.left - leftMargin: page.isPrivateChat ? (messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0) : 0 //левый марджин для собственных сообщений в приватных чатах. В остальных на полную ширину + leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0 verticalCenter: parent.verticalCenter } height: messageTextColumn.height + precalculatedValues.paddingMediumDouble width: precalculatedValues.backgroundWidth - property bool isUnread: messageIndex > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage" - color: Theme.colorScheme === Theme.LightOnDark ? (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor)) : (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.backgroundGlowColor : Theme.overlayBackgroundColor)) - + color: Theme.colorScheme === Theme.LightOnDark ? (isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor) : (isUnread ? Theme.backgroundGlowColor : Theme.overlayBackgroundColor) radius: parent.width / 50 opacity: isUnread ? 0.5 : 0.2 visible: appSettings.showStickersAsImages || (myMessage.content['@type'] !== "messageSticker" && myMessage.content['@type'] !== "messageAnimatedEmoji") @@ -489,7 +487,7 @@ ListItem { truncationMode: TruncationMode.Fade textFormat: Text.StyledText horizontalAlignment: messageListItem.textAlign - visible: messageListItem.isOwnMessage ? false : (precalculatedValues.showUserInfo || myMessage['@type'] === "sponsoredMessage") + visible: precalculatedValues.showUserInfo || myMessage['@type'] === "sponsoredMessage" MouseArea { anchors.fill: parent enabled: !(messageListItem.precalculatedValues.pageIsSelecting || messageListItem.isAnonymous) diff --git a/qml/components/ReactionButton.qml b/qml/components/ReactionButton.qml new file mode 100644 index 0000000..06bc908 --- /dev/null +++ b/qml/components/ReactionButton.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 +import Sailfish.Silica 1.0 + +Rectangle { + id: button + + height: Theme.itemSizeExtraSmall + width: Theme.itemSizeExtraSmall + color: Theme.rgba(Theme.primaryColor, 0.4) + radius: width / 2 + + signal clicked() + + IconButton { + icon.source: "image://theme/icon-s-favorite" + anchors.centerIn: parent + onClicked: button.clicked() + } +} diff --git a/qml/components/settingsPage/SettingsBehavior.qml b/qml/components/settingsPage/SettingsBehavior.qml index c1d15ab..ae197a0 100644 --- a/qml/components/settingsPage/SettingsBehavior.qml +++ b/qml/components/settingsPage/SettingsBehavior.qml @@ -21,6 +21,8 @@ import QtQuick 2.6 import Sailfish.Silica 1.0 import WerkWolf.Fernschreiber 1.0 +import ".." + AccordionItem { text: qsTr("Behavior") Component { @@ -114,6 +116,31 @@ AccordionItem { } } + TextSwitch { + width: parent.columnWidth + checked: appSettings.showReactionButton + text: qsTr("Show reaction button on tap") + description: qsTr("The reaction button may appear when you tap the message bubble, to make access to the reactions even easier.") + automaticCheck: false + onClicked: { + appSettings.showReactionButton = !checked + } + + ReactionButton { + Behavior on opacity { FadeAnimation {} } + opacity: appSettings.showReactionButton ? 1 : 0 + visible: opacity > 0 + anchors { + right: parent.right + rightMargin: parent.rightMargin + verticalCenter: parent.verticalCenter + } + onClicked: { + appSettings.showReactionButton = !parent.checked + } + } + } + ComboBox { id: feedbackComboBox width: parent.columnWidth diff --git a/qml/js/emoji/1f426-200d-2b1b.svg b/qml/js/emoji/1f426-200d-2b1b.svg new file mode 100644 index 0000000..0790872 --- /dev/null +++ b/qml/js/emoji/1f426-200d-2b1b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1f6dc.svg b/qml/js/emoji/1f6dc.svg new file mode 100644 index 0000000..364a68e --- /dev/null +++ b/qml/js/emoji/1f6dc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fa75.svg b/qml/js/emoji/1fa75.svg new file mode 100644 index 0000000..5a72101 --- /dev/null +++ b/qml/js/emoji/1fa75.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fa76.svg b/qml/js/emoji/1fa76.svg new file mode 100644 index 0000000..56e3ef1 --- /dev/null +++ b/qml/js/emoji/1fa76.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fa77.svg b/qml/js/emoji/1fa77.svg new file mode 100644 index 0000000..a372dcc --- /dev/null +++ b/qml/js/emoji/1fa77.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fa87.svg b/qml/js/emoji/1fa87.svg new file mode 100644 index 0000000..fd8c53a --- /dev/null +++ b/qml/js/emoji/1fa87.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fa88.svg b/qml/js/emoji/1fa88.svg new file mode 100644 index 0000000..633fa4c --- /dev/null +++ b/qml/js/emoji/1fa88.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faad.svg b/qml/js/emoji/1faad.svg new file mode 100644 index 0000000..5036323 --- /dev/null +++ b/qml/js/emoji/1faad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faae.svg b/qml/js/emoji/1faae.svg new file mode 100644 index 0000000..e8ad033 --- /dev/null +++ b/qml/js/emoji/1faae.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faaf.svg b/qml/js/emoji/1faaf.svg new file mode 100644 index 0000000..bfaceb5 --- /dev/null +++ b/qml/js/emoji/1faaf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fabb.svg b/qml/js/emoji/1fabb.svg new file mode 100644 index 0000000..3cae81a --- /dev/null +++ b/qml/js/emoji/1fabb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fabc.svg b/qml/js/emoji/1fabc.svg new file mode 100644 index 0000000..cb8c4ee --- /dev/null +++ b/qml/js/emoji/1fabc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fabd.svg b/qml/js/emoji/1fabd.svg new file mode 100644 index 0000000..9effe33 --- /dev/null +++ b/qml/js/emoji/1fabd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fabf.svg b/qml/js/emoji/1fabf.svg new file mode 100644 index 0000000..7c0f6a6 --- /dev/null +++ b/qml/js/emoji/1fabf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1face.svg b/qml/js/emoji/1face.svg new file mode 100644 index 0000000..f419d66 --- /dev/null +++ b/qml/js/emoji/1face.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1facf.svg b/qml/js/emoji/1facf.svg new file mode 100644 index 0000000..030b0bd --- /dev/null +++ b/qml/js/emoji/1facf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fada.svg b/qml/js/emoji/1fada.svg new file mode 100644 index 0000000..2094a77 --- /dev/null +++ b/qml/js/emoji/1fada.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fadb.svg b/qml/js/emoji/1fadb.svg new file mode 100644 index 0000000..e68a96d --- /dev/null +++ b/qml/js/emoji/1fadb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1fae8.svg b/qml/js/emoji/1fae8.svg new file mode 100644 index 0000000..02ab52d --- /dev/null +++ b/qml/js/emoji/1fae8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7-1f3fb.svg b/qml/js/emoji/1faf7-1f3fb.svg new file mode 100644 index 0000000..5df3bd1 --- /dev/null +++ b/qml/js/emoji/1faf7-1f3fb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7-1f3fc.svg b/qml/js/emoji/1faf7-1f3fc.svg new file mode 100644 index 0000000..6633504 --- /dev/null +++ b/qml/js/emoji/1faf7-1f3fc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7-1f3fd.svg b/qml/js/emoji/1faf7-1f3fd.svg new file mode 100644 index 0000000..752c49b --- /dev/null +++ b/qml/js/emoji/1faf7-1f3fd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7-1f3fe.svg b/qml/js/emoji/1faf7-1f3fe.svg new file mode 100644 index 0000000..d4aaefc --- /dev/null +++ b/qml/js/emoji/1faf7-1f3fe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7-1f3ff.svg b/qml/js/emoji/1faf7-1f3ff.svg new file mode 100644 index 0000000..6735ce3 --- /dev/null +++ b/qml/js/emoji/1faf7-1f3ff.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf7.svg b/qml/js/emoji/1faf7.svg new file mode 100644 index 0000000..1237887 --- /dev/null +++ b/qml/js/emoji/1faf7.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8-1f3fb.svg b/qml/js/emoji/1faf8-1f3fb.svg new file mode 100644 index 0000000..3a28a11 --- /dev/null +++ b/qml/js/emoji/1faf8-1f3fb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8-1f3fc.svg b/qml/js/emoji/1faf8-1f3fc.svg new file mode 100644 index 0000000..544719e --- /dev/null +++ b/qml/js/emoji/1faf8-1f3fc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8-1f3fd.svg b/qml/js/emoji/1faf8-1f3fd.svg new file mode 100644 index 0000000..607bcf2 --- /dev/null +++ b/qml/js/emoji/1faf8-1f3fd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8-1f3fe.svg b/qml/js/emoji/1faf8-1f3fe.svg new file mode 100644 index 0000000..378fa2e --- /dev/null +++ b/qml/js/emoji/1faf8-1f3fe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8-1f3ff.svg b/qml/js/emoji/1faf8-1f3ff.svg new file mode 100644 index 0000000..b3cccfc --- /dev/null +++ b/qml/js/emoji/1faf8-1f3ff.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/emoji/1faf8.svg b/qml/js/emoji/1faf8.svg new file mode 100644 index 0000000..fadecd8 --- /dev/null +++ b/qml/js/emoji/1faf8.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/qml/js/twemoji.js b/qml/js/twemoji.js index 044a067..0825c58 100644 --- a/qml/js/twemoji.js +++ b/qml/js/twemoji.js @@ -8,7 +8,7 @@ // RegExp based on emoji's official Unicode standards // http://www.unicode.org/Public/UNIDATA/EmojiSources.txt -var re = /(?:\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83e\udef1\ud83c\udffb\u200d\ud83e\udef2\ud83c[\udffc-\udfff]|\ud83e\udef1\ud83c\udffc\u200d\ud83e\udef2\ud83c[\udffb\udffd-\udfff]|\ud83e\udef1\ud83c\udffd\u200d\ud83e\udef2\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\udef1\ud83c\udffe\u200d\ud83e\udef2\ud83c[\udffb-\udffd\udfff]|\ud83e\udef1\ud83c\udfff\u200d\ud83e\udef2\ud83c[\udffb-\udffe]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d\udc8f\ud83c[\udffb-\udfff]|\ud83d\udc91\ud83c[\udffb-\udfff]|\ud83e\udd1d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d\udc8f\udc91]|\ud83e\udd1d)|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd4\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83d\ude36\u200d\ud83c\udf2b\ufe0f|\u2764\ufe0f\u200d\ud83d\udd25|\u2764\ufe0f\u200d\ud83e\ude79|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83d\ude2e\u200d\ud83d\udca8|\ud83d\ude35\u200d\ud83d\udcab|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd\udec3-\udec5\udef0-\udef6]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udc8e\udc90\udc92-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udedd-\udedf\udeeb\udeec\udef4-\udefc\udfe0-\udfeb\udff0]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78-\uddb4\uddb7\uddba\uddbc-\uddcc\uddd0\uddde-\uddff\ude70-\ude74\ude78-\ude7c\ude80-\ude86\ude90-\udeac\udeb0-\udeba\udec0-\udec2\uded0-\uded9\udee0-\udee7]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g, +var re = /(?:\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83d\udc68\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc68\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83d\udc69\ud83c[\udffb-\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffc-\udfff]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffd-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffd\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\u2764\ufe0f\u200d\ud83e\uddd1\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83e\udef1\ud83c\udffb\u200d\ud83e\udef2\ud83c[\udffc-\udfff]|\ud83e\udef1\ud83c\udffc\u200d\ud83e\udef2\ud83c[\udffb\udffd-\udfff]|\ud83e\udef1\ud83c\udffd\u200d\ud83e\udef2\ud83c[\udffb\udffc\udffe\udfff]|\ud83e\udef1\ud83c\udffe\u200d\ud83e\udef2\ud83c[\udffb-\udffd\udfff]|\ud83e\udef1\ud83c\udfff\u200d\ud83e\udef2\ud83c[\udffb-\udffe]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d\udc8f\ud83c[\udffb-\udfff]|\ud83d\udc91\ud83c[\udffb-\udfff]|\ud83e\udd1d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d\udc8f\udc91]|\ud83e\udd1d)|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd4\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83d\ude36\u200d\ud83c\udf2b\ufe0f|\u2764\ufe0f\u200d\ud83d\udd25|\u2764\ufe0f\u200d\ud83e\ude79|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83d\ude2e\u200d\ud83d\udca8|\ud83d\ude35\u200d\ud83d\udcab|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b|\ud83d\udc26\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|\ud83e\udef0|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd\udec3-\udec5\udef1-\udef8]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udc8e\udc90\udc92-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udedc-\udedf\udeeb\udeec\udef4-\udefc\udfe0-\udfeb\udff0]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78-\uddb4\uddb7\uddba\uddbc-\uddcc\uddd0\uddde-\uddff\ude70-\ude7c\ude80-\ude88\ude90-\udebd\udebf-\udec2\udece-\udedb\udee0-\udee8]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g, // avoid runtime RegExp creation for not so smart, // not JIT based, and old browsers / engines diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index d20a373..6d4ecf0 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -417,7 +417,7 @@ Page { chatPage.messageIdToScrollTo = messageId } if (chatPage.messageIdToScrollTo && chatPage.messageIdToScrollTo != "") { - var index = chatModel.getMessageIndex(chatPage.messageIdToScrollTo); + var index = chatModel.getDisplayedMessageIndex(chatPage.messageIdToScrollTo); if(index !== -1) { chatPage.messageIdToScrollTo = ""; chatView.scrollToIndex(index); @@ -796,7 +796,7 @@ Page { NamedAction { visible: messageOptionsDrawer.showCopyMessageToClipboardMenuItem name: qsTr("Copy Message to Clipboard") - action: messageOptionsDrawer.myMessage.copyMessageToClipboard + action: messageOptionsDrawer.sourceItem.copyMessageToClipboard }, NamedAction { visible: messageOptionsDrawer.showForwardMessageMenuItem && messageOptionsDrawer.myMessage.can_be_forwarded @@ -1922,7 +1922,7 @@ Page { Image { id: emojiPicture - source: "../js/emoji/" + modelData.file_name + source: "../js/emoji/" + modelData.file_name +".svg" width: Theme.fontSizeLarge height: Theme.fontSizeLarge } diff --git a/rpm/harbour-fernschreiber.spec b/rpm/harbour-fernschreiber.spec index 41e8918..4188b01 100644 --- a/rpm/harbour-fernschreiber.spec +++ b/rpm/harbour-fernschreiber.spec @@ -9,6 +9,7 @@ Name: harbour-fernschreiber # << macros %define __provides_exclude_from ^%{_datadir}/.*$ %define __requires_exclude ^lib(tdjson|ssl|crypto).*$ +%define _binary_payload w6.xzdio Summary: Fernschreiber is a Telegram client for Aurora OS Version: 0.17 @@ -17,7 +18,6 @@ Group: Qt/Qt License: LICENSE URL: http://werkwolf.eu/ Source0: %{name}-%{version}.tar.bz2 -Source100: harbour-fernschreiber.yaml Requires: sailfishsilica-qt5 >= 0.10.9 #Requires: nemo-qml-plugin-contacts-qt5 BuildRequires: pkgconfig(sailfishapp) >= 1.0.2 diff --git a/rpm/harbour-fernschreiber.yaml b/rpm/harbour-fernschreiber.yaml new file mode 100644 index 0000000..368792c --- /dev/null +++ b/rpm/harbour-fernschreiber.yaml @@ -0,0 +1,56 @@ +Name: harbour-fernschreiber +Summary: Fernschreiber is a Telegram client for Sailfish OS +Version: 0.17 +Release: 12 +# The contents of the Group field should be one of the groups listed here: +# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS +Group: Qt/Qt +URL: http://werkwolf.eu/ +License: LICENSE +# This must be generated before uploading a package to a remote build service. +# Usually this line does not need to be modified. +Sources: +- '%{name}-%{version}.tar.bz2' +Description: | + Fernschreiber is a Telegram client for Sailfish OS +Configure: none +Builder: qmake5 + +# This section specifies build dependencies that are resolved using pkgconfig. +# This is the preferred way of specifying build dependencies for your package. +PkgConfigBR: + - sailfishapp >= 1.0.2 + - Qt5Core + - Qt5Qml + - Qt5Quick + - Qt5DBus + - Qt5Sql + - Qt5Multimedia + - Qt5Positioning + - nemonotifications-qt5 + - openssl + +# NB: spectacle has a bug where it will remove custom "#<< macros" lines, so define them here: +Macros: + - '__provides_exclude_from;^%{_datadir}/.*$' + - '__requires_exclude;^libtdjson.*$' + - '_binary_payload;w6.xzdio' + +# Build dependencies without a pkgconfig setup can be listed here +PkgBR: + - gperf + +# Runtime dependencies which are not automatically detected +Requires: + - sailfishsilica-qt5 >= 0.10.9 + - nemo-qml-plugin-contacts-qt5 + +# All installed files +Files: + - '%{_bindir}/%{name}' + - '%{_datadir}/%{name}' + - '%{_datadir}/applications/%{name}.desktop' + - '%{_datadir}/icons/hicolor/*/apps/%{name}.png' + +# For more information about yaml and what's supported in Sailfish OS +# build system, please see https://wiki.merproject.org/wiki/Spectacle diff --git a/src/appsettings.cpp b/src/appsettings.cpp index e1a92ad..e9a9ea3 100644 --- a/src/appsettings.cpp +++ b/src/appsettings.cpp @@ -42,6 +42,7 @@ namespace { const QString KEY_FOCUS_TEXTAREA_ON_CHAT_OPEN("focusTextAreaOnChatOpen"); const QString KEY_SPONSORED_MESS("sponsoredMess"); const QString KEY_HIGHLIGHT_UNREADCONVS("highlightUnreadConversations"); + const QString KEY_SHOW_REACTION_BUTTON("showReactionButton"); } AppSettings::AppSettings(QObject *parent) : QObject(parent), settings(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/org.ygriega/fernschreiber/settings.conf", QSettings::NativeFormat) @@ -329,6 +330,20 @@ void AppSettings::setFocusTextAreaOnChatOpen(bool focusTextAreaOnChatOpen) } } +bool AppSettings::showReactionButton() const +{ + return settings.value(KEY_SHOW_REACTION_BUTTON, true).toBool(); +} + +void AppSettings::setShowReactionButton(bool enable) +{ + if (showReactionButton() != enable) { + LOG(KEY_SHOW_REACTION_BUTTON << enable); + settings.setValue(KEY_SHOW_REACTION_BUTTON, enable); + emit showReactionButtonChanged(); + } +} + AppSettings::SponsoredMess AppSettings::getSponsoredMess() const { return (SponsoredMess) settings.value(KEY_SPONSORED_MESS, (int) diff --git a/src/appsettings.h b/src/appsettings.h index acc38b2..9382fee 100644 --- a/src/appsettings.h +++ b/src/appsettings.h @@ -43,8 +43,9 @@ class AppSettings : public QObject { Q_PROPERTY(bool onlineOnlyMode READ onlineOnlyMode WRITE setOnlineOnlyMode NOTIFY onlineOnlyModeChanged) Q_PROPERTY(bool delayMessageRead READ delayMessageRead WRITE setDelayMessageRead NOTIFY delayMessageReadChanged) Q_PROPERTY(bool focusTextAreaOnChatOpen READ getFocusTextAreaOnChatOpen WRITE setFocusTextAreaOnChatOpen NOTIFY focusTextAreaOnChatOpenChanged) - Q_PROPERTY(SponsoredMess sponsoredMess READ getSponsoredMess WRITE setSponsoredMess NOTIFY sponsoredMessChanged) Q_PROPERTY(bool highlightUnreadConversations READ highlightUnreadConversations WRITE setHighlightUnreadConversations NOTIFY highlightUnreadConversationsChanged) + Q_PROPERTY(bool showReactionButton READ showReactionButton WRITE setShowReactionButton NOTIFY showReactionButtonChanged) + Q_PROPERTY(SponsoredMess sponsoredMess READ getSponsoredMess WRITE setSponsoredMess NOTIFY sponsoredMessChanged) public: enum SponsoredMess { @@ -121,12 +122,15 @@ public: bool getFocusTextAreaOnChatOpen() const; void setFocusTextAreaOnChatOpen(bool focusTextAreaOnChatOpen); - SponsoredMess getSponsoredMess() const; - void setSponsoredMess(SponsoredMess sponsoredMess); - bool highlightUnreadConversations() const; void setHighlightUnreadConversations(bool enable); + bool showReactionButton() const; + void setShowReactionButton(bool enable); + + SponsoredMess getSponsoredMess() const; + void setSponsoredMess(SponsoredMess sponsoredMess); + signals: void sendByEnterChanged(); void focusTextAreaAfterSendChanged(); @@ -147,8 +151,9 @@ signals: void onlineOnlyModeChanged(); void delayMessageReadChanged(); void focusTextAreaOnChatOpenChanged(); - void sponsoredMessChanged(); void highlightUnreadConversationsChanged(); + void showReactionButtonChanged(); + void sponsoredMessChanged(); private: QSettings settings; diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index a361c18..7edfcb4 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -91,6 +91,7 @@ public: QVector updateLastMessage(const QVariantMap &message); QVector updateGroup(const TDLibWrapper::Group *group); QVector updateSecretChat(const QVariantMap &secretChatDetails); + ChatData* clone(); TDLibWrapper *tdLibWrapper; public: @@ -384,6 +385,24 @@ QVector ChatListModel::ChatData::updateSecretChat(const QVariantMap &secret return changedRoles; } +ChatListModel::ChatData* ChatListModel::ChatData::clone() { + QVariantMap clonedChatData; + + QList keys = chatData.keys(); + for(int i = 0; i < keys.count(); i++) { + clonedChatData.insert(keys[i], QVariant(chatData[keys[i]])); + } + ChatData* res = new ChatData(tdLibWrapper, clonedChatData); + res->chatId = chatId; + res->order = order; + res->groupId = groupId; + res->verified = verified; + res->chatType = chatType; + res->memberStatus = memberStatus; + res->secretChatState = secretChatState; + return res; +} + ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper, AppSettings *appSettings) : showHiddenChats(false) { this->tdLibWrapper = tdLibWrapper; @@ -426,6 +445,15 @@ ChatListModel::~ChatListModel() qDeleteAll(hiddenChats.values()); } +ChatListModel* ChatListModel::clone() { + ChatListModel* res = new ChatListModel(tdLibWrapper, appSettings); + res->relativeTimeRefreshTimer->stop(); + for(int i = 0; i < chatList.count(); i++) { + res->chatList.append(chatList.at(i)->clone()); + } + return res; +} + void ChatListModel::reset() { chatList.clear(); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index af875df..f40cd12 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -75,6 +75,7 @@ public: bool showAllChats() const; void setShowAllChats(bool showAll); + ChatListModel* clone(); private slots: void handleChatDiscovered(const QString &chatId, const QVariantMap &chatInformation); diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index 7dad231..2c54827 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -472,13 +472,24 @@ QVariantMap ChatModel::getMessage(int index) return QVariantMap(); } -int ChatModel::getMessageIndex(qlonglong messageId) +int ChatModel::getDisplayedMessageIndex(qlonglong messageId) { if (messages.size() == 0) { return -1; } if (messageIndexMap.contains(messageId)) { - return messageIndexMap.value(messageId); + int rawIndex = messageIndexMap.value(messageId); + // We need to substract number of albums which are shown before this item, because that's the index it's displayed on screen at. + int realIndex = rawIndex; + for(int i = 0; i < rawIndex; i++) { + MessageData *message = messages.at(i); + if(message->albumMessageIds.count() > 0) { + realIndex -= (message->albumMessageIds.count() - 1); + } + } + if(realIndex < -1) + return -1; + return realIndex; } return -1; } diff --git a/src/chatmodel.h b/src/chatmodel.h index e2e8bbc..07753b7 100644 --- a/src/chatmodel.h +++ b/src/chatmodel.h @@ -49,7 +49,7 @@ public: Q_INVOKABLE int getLastReadMessageIndex(); Q_INVOKABLE void setSearchQuery(const QString newSearchQuery); - Q_INVOKABLE int getMessageIndex(qlonglong messageId); + Q_INVOKABLE int getDisplayedMessageIndex(qlonglong messageId); QVariantMap smallPhoto() const; qlonglong getChatId() const; diff --git a/src/chatpermissionfiltermodel.cpp b/src/chatpermissionfiltermodel.cpp index cd99678..6a53cf5 100644 --- a/src/chatpermissionfiltermodel.cpp +++ b/src/chatpermissionfiltermodel.cpp @@ -33,7 +33,9 @@ ChatPermissionFilterModel::ChatPermissionFilterModel(QObject *parent) : QSortFil void ChatPermissionFilterModel::setSource(QObject *model) { - setSourceModel(qobject_cast(model)); + ChatListModel* chatListModel = qobject_cast(model); + ChatListModel* chatListModelClone = chatListModel->clone(); + setSourceModel(chatListModelClone); } void ChatPermissionFilterModel::setSourceModel(QAbstractItemModel *model) @@ -45,6 +47,13 @@ void ChatPermissionFilterModel::setSourceModel(QAbstractItemModel *model) } } +ChatPermissionFilterModel::~ChatPermissionFilterModel() { + QAbstractItemModel* _sourceModel = sourceModel(); + if(_sourceModel != nullptr) { + delete _sourceModel; + } +} + TDLibWrapper *ChatPermissionFilterModel::getTDLibWrapper() const { return tdLibWrapper; diff --git a/src/chatpermissionfiltermodel.h b/src/chatpermissionfiltermodel.h index d77b3f6..dc4f05b 100644 --- a/src/chatpermissionfiltermodel.h +++ b/src/chatpermissionfiltermodel.h @@ -31,7 +31,7 @@ class ChatPermissionFilterModel : public QSortFilterProxyModel public: ChatPermissionFilterModel(QObject *parent = Q_NULLPTR); - + ~ChatPermissionFilterModel() override; TDLibWrapper *getTDLibWrapper() const; void setTDLibWrapper(QObject* obj); diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 44034c7..fc6d7bd 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -81,6 +81,8 @@ namespace { const QString TYPE_ANIMATED_EMOJI("animatedEmoji"); const QString TYPE_INPUT_MESSAGE_REPLY_TO_MESSAGE("inputMessageReplyToMessage"); const QString TYPE_DRAFT_MESSAGE("draftMessage"); + + const double POWERSAVING_TDLIB_REQUEST_INTERVAL = 100; } static QString getChatPositionOrder(const QVariantMap &position) @@ -191,9 +193,15 @@ void TDLibReceiver::setActive(bool active) } else { LOG("Deactivating receiver loop, this may take a while..."); } + this->powerSavingMode = false; this->isActive = active; } +void TDLibReceiver::setPowerSavingMode(bool powerSavingMode) +{ + this->powerSavingMode = powerSavingMode; +} + void TDLibReceiver::receiverLoop() { LOG("Starting receiver loop"); @@ -205,6 +213,9 @@ void TDLibReceiver::receiverLoop() VERBOSE("Raw result:" << receivedJsonDocument.toJson(QJsonDocument::Indented).constData()); processReceivedDocument(receivedJsonDocument); } + if(this->powerSavingMode) { + msleep(POWERSAVING_TDLIB_REQUEST_INTERVAL); + } } LOG("Stopping receiver loop"); } diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index 33771b6..b235461 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -35,6 +35,7 @@ class TDLibReceiver : public QThread public: explicit TDLibReceiver(void *tdLibClient, QObject *parent = nullptr); void setActive(bool active); + void setPowerSavingMode(bool active); signals: void versionDetected(const QString &version); @@ -115,6 +116,7 @@ private: QHash handlers; void *tdLibClient; bool isActive; + bool powerSavingMode; private: static const QVariantList cleanupList(const QVariantList& list, bool *updated = Q_NULLPTR); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 4d9d186..4a8b0ce 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -102,7 +103,7 @@ TDLibWrapper::TDLibWrapper(AppSettings *settings, MceInterface *mce, QObject *pa connect(this->appSettings, SIGNAL(useOpenWithChanged()), this, SLOT(handleOpenWithChanged())); connect(this->appSettings, SIGNAL(storageOptimizerChanged()), this, SLOT(handleStorageOptimizerChanged())); - + connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(handleApplicationStateChanged(Qt::ApplicationState))); connect(networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), this, SLOT(handleNetworkConfigurationChanged(QNetworkConfiguration))); this->setLogVerbosityLevel(); @@ -1573,17 +1574,17 @@ QVariantMap TDLibWrapper::getUserInformation() QVariantMap TDLibWrapper::getUserInformation(const QString &userId) { // LOG("Returning user information for ID" << userId); - return this->allUsers.value(userId).toMap(); + return this->usersById.value(userId).toMap(); } bool TDLibWrapper::hasUserInformation(const QString &userId) { - return this->allUsers.contains(userId); + return this->usersById.contains(userId); } QVariantMap TDLibWrapper::getUserInformationByName(const QString &userName) { - return this->allUserNames.value(userName).toMap(); + return this->usersByName.value(userName).toMap(); } TDLibWrapper::UserPrivacySettingRule TDLibWrapper::getUserPrivacySettingRule(TDLibWrapper::UserPrivacySetting userPrivacySetting) @@ -1812,8 +1813,8 @@ void TDLibWrapper::handleAuthorizationStateChanged(const QString &authorizationS LOG("Reloading TD Lib..."); this->basicGroups.clear(); this->superGroups.clear(); - this->allUsers.clear(); - this->allUserNames.clear(); + this->usersById.clear(); + this->usersByName.clear(); this->tdLibReceiver->setActive(false); while (this->tdLibReceiver->isRunning()) { QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); @@ -1864,18 +1865,17 @@ void TDLibWrapper::handleConnectionStateChanged(const QString &connectionState) emit connectionStateChanged(this->connectionState); } -void TDLibWrapper::handleUserUpdated(const QVariantMap &userInformation) +void TDLibWrapper::handleUserUpdated(const QVariantMap &updatedUserInformation) { - QString updatedUserId = userInformation.value(ID).toString(); + QString updatedUserId = updatedUserInformation.value(ID).toString(); if (updatedUserId == this->options.value("my_id").toString()) { LOG("Own user information updated :)"); - this->userInformation = userInformation; - emit ownUserUpdated(userInformation); + this->userInformation = updatedUserInformation; + emit ownUserUpdated(updatedUserInformation); } - LOG("User information updated:" << userInformation.value(USERNAMES).toMap().value(EDITABLE_USERNAME).toString() << userInformation.value(FIRST_NAME).toString() << userInformation.value(LAST_NAME).toString()); - this->allUsers.insert(updatedUserId, userInformation); - this->allUserNames.insert(userInformation.value(USERNAMES).toMap().value(EDITABLE_USERNAME).toString(), userInformation); - emit userUpdated(updatedUserId, userInformation); + LOG("User information updated:" << updatedUserInformation.value(USERNAMES).toMap().value(EDITABLE_USERNAME).toString() << updatedUserInformation.value(FIRST_NAME).toString() << updatedUserInformation.value(LAST_NAME).toString()); + updateUserInformation(updatedUserId, updatedUserInformation); + emit userUpdated(updatedUserId, updatedUserInformation); } void TDLibWrapper::handleUserStatusUpdated(const QString &userId, const QVariantMap &userStatusInformation) @@ -1884,14 +1884,22 @@ void TDLibWrapper::handleUserStatusUpdated(const QString &userId, const QVariant LOG("Own user status information updated :)"); this->userInformation.insert(STATUS, userStatusInformation); } + QVariantMap updatedUserInformation = this->usersById.value(userId).toMap(); + if(updatedUserInformation[STATUS] == userStatusInformation) { + return; + } LOG("User status information updated:" << userId << userStatusInformation.value(_TYPE).toString()); - QVariantMap updatedUserInformation = this->allUsers.value(userId).toMap(); updatedUserInformation.insert(STATUS, userStatusInformation); - this->allUsers.insert(userId, updatedUserInformation); - this->allUserNames.insert(userInformation.value(USERNAMES).toMap().value(EDITABLE_USERNAME).toString(), userInformation); + updateUserInformation(userId, updatedUserInformation); emit userUpdated(userId, updatedUserInformation); } +void TDLibWrapper::updateUserInformation(const QString &userId, const QVariantMap &userInformation) +{ + this->usersById.insert(userId, userInformation); + this->usersByName.insert(userInformation.value(USERNAMES).toMap().value(EDITABLE_USERNAME).toString(), userInformation); +} + void TDLibWrapper::handleFileUpdated(const QVariantMap &fileInformation) { emit fileUpdated(fileInformation.value(ID).toInt(), fileInformation); @@ -2204,6 +2212,10 @@ void TDLibWrapper::handleGetPageSourceFinished() } } +void TDLibWrapper::handleApplicationStateChanged(Qt::ApplicationState state) { + this->tdLibReceiver->setPowerSavingMode(state != Qt::ApplicationState::ApplicationActive); +} + QVariantMap& TDLibWrapper::fillTdlibParameters(QVariantMap& parameters) { parameters.insert("api_id", TDLIB_API_ID); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 2487ae5..15fd7e7 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -348,7 +348,7 @@ public slots: void handleAuthorizationStateChanged(const QString &authorizationState, const QVariantMap authorizationStateData); void handleOptionUpdated(const QString &optionName, const QVariant &optionValue); void handleConnectionStateChanged(const QString &connectionState); - void handleUserUpdated(const QVariantMap &userInformation); + void handleUserUpdated(const QVariantMap &updatedUserInformation); void handleUserStatusUpdated(const QString &userId, const QVariantMap &userStatusInformation); void handleFileUpdated(const QVariantMap &fileInformation); void handleNewChatDiscovered(const QVariantMap &chatInformation); @@ -373,6 +373,7 @@ public slots: void handleNetworkConfigurationChanged(const QNetworkConfiguration &config); void handleActiveEmojiReactionsUpdated(const QStringList& emojis); void handleGetPageSourceFinished(); + void handleApplicationStateChanged(Qt::ApplicationState state); private: void setOption(const QString &name, const QString &type, const QVariant &value); @@ -383,6 +384,7 @@ private: const Group *updateGroup(qlonglong groupId, const QVariantMap &groupInfo, QHash *groups); QVariantMap newSendMessageRequest(qlonglong chatId, qlonglong replyToMessageId); void initializeTDLibReceiver(); + void updateUserInformation(const QString &userId, const QVariantMap &userInformation); private: void *tdLibClient; @@ -399,8 +401,8 @@ private: QVariantMap options; QVariantMap userInformation; QMap userPrivacySettingRules; - QVariantMap allUsers; - QVariantMap allUserNames; + QVariantMap usersById; + QVariantMap usersByName; QVariantMap chats; QMap secretChats; QVariantMap unreadMessageInformation; diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index ef14fdf..9712a28 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -499,6 +499,13 @@ Sie haben noch keine Chats. + + ContactSync + + Could not synchronize your contacts with Telegram. + Konnte Ihre Kontakte nicht mit Telegram synchronisieren. + + CoverPage @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + %Ln Nachricht weiterleiten %Ln Nachrichten weiterleiten diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 4f9f525..4251ba4 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -499,6 +499,13 @@ You don't have any chats yet. + + ContactSync + + Could not synchronize your contacts with Telegram. + Could not synchronize your contacts with Telegram. + + CoverPage @@ -903,7 +910,7 @@ messages Forward %Ln messages dialog header - + Forward %Ln message Forward %Ln messages diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 0abb207..3754b0d 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -499,6 +499,13 @@ No hay charlas. + + ContactSync + + Could not synchronize your contacts with Telegram. + No se puede sincronizar los contactos con Telegrama. + + CoverPage @@ -880,11 +887,11 @@ sent a game myself - envió juego + envió un juego sent a game - envió juego + envió un juego sent a video note @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + Reenviar %Ln mensaje Reenviar %Ln mensajes @@ -1618,26 +1625,6 @@ When tapping a quoted message, open it in chat instead of showing it in an overlay. Al Pulsar mensaje citado, abrirá en Charla en lugar de mostrarlo en una superposición. - - Always append message preview to notifications - Agregar vista previa mensaje a notificaciones - - - In addition to showing the number of unread messages, the latest message will also be appended to notifications. - Mostrará cantidad mensajes no leídos, el último mensaje se agregará a notificaciones. - - - Highlight unread messages - Resaltar mensajes no leídos - - - Highlight Conversations with unread messages - Resaltar conversaciones a mensajes no leídos - - - Hide content in notifications - Ocultar contenido a notificaciones - SettingsPage diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 691fae8..df31ce8 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -499,6 +499,13 @@ Sinulla ei ole vielä keskusteluja. + + ContactSync + + Could not synchronize your contacts with Telegram. + Yhteystietojasi ei voitu synkronoida Telegramin kanssa. + + CoverPage @@ -902,7 +909,7 @@ Forward %Ln messages dialog header - + Välitä %Ln viesti Välitä %Ln viestiä diff --git a/translations/harbour-fernschreiber-fr.ts b/translations/harbour-fernschreiber-fr.ts index 062a5c0..5cd7743 100644 --- a/translations/harbour-fernschreiber-fr.ts +++ b/translations/harbour-fernschreiber-fr.ts @@ -499,6 +499,13 @@ Vous n'avez aucune conversation. + + ContactSync + + Could not synchronize your contacts with Telegram. + Impossible de synchroniser vos contacts avec Telegram. + + CoverPage @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + Transférer %Ln message Transférer %Ln messages @@ -1618,18 +1625,6 @@ When tapping a quoted message, open it in chat instead of showing it in an overlay. - - Highlight unread messages - Mettre en valeur les messages non-lus - - - Highlight Conversations with unread messages - Mettre en valeur les conversations avec des messages non-lus - - - Hide content in notifications - Masquer le contenu dans les notifications - SettingsPage diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 67d1bdf..cf66d21 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -499,6 +499,13 @@ Nessuna chat presente + + ContactSync + + Could not synchronize your contacts with Telegram. + Sincronizzazione contatti con Telegram non riuscita + + CoverPage @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + Inoltra %Ln messaggio Inoltra %Ln messaggi diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 261f37d..4b8d589 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -509,6 +509,13 @@ Nie masz jeszcze żadnych czatów. + + ContactSync + + Could not synchronize your contacts with Telegram. + Nie można zsynchonizaować kontaktów z Telegramem. + + CoverPage @@ -915,7 +922,7 @@ Forward %Ln messages dialog header - + Przekaż %Ln wiadomość Przekaż %Ln wiadomości Przekaż %Ln wiadomości diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index b6dcd84..6724c98 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -509,6 +509,13 @@ Тут пока ничего нет + + ContactSync + + Could not synchronize your contacts with Telegram. + Невозможно синхронизировать ваши контакты с Телеграм. + + CoverPage @@ -918,7 +925,7 @@ Forward %Ln messages dialog header - + Перенаправить %Ln сообщение Перенаправить %Ln сообщения Перенаправить %Ln сообщений @@ -1649,18 +1656,6 @@ When tapping a quoted message, open it in chat instead of showing it in an overlay. По нажатию на цитируемое сообщение, переходить к нему в чате вместо отображения во всплывающем окне. - - Highlight unread messages - Выделять непрочитанные сообщения - - - Highlight Conversations with unread messages - Помечать чаты и каналы с непрочитанными сообщениями другим шрифтом и цветом. - - - Hide content in notifications - Не показывать содержимое сообщений в уведомлениях - SettingsPage diff --git a/translations/harbour-fernschreiber-sk.ts b/translations/harbour-fernschreiber-sk.ts index 36ab490..d7105c9 100644 --- a/translations/harbour-fernschreiber-sk.ts +++ b/translations/harbour-fernschreiber-sk.ts @@ -509,6 +509,13 @@ Nemáte žiadne čety. + + ContactSync + + Could not synchronize your contacts with Telegram. + Nemožno synchonizovať kontakty s Telegramom. + + CoverPage @@ -915,7 +922,7 @@ Forward %Ln messages dialog header - + Postúpená %Ln správa Postúpené %Ln správy Postúpených %Ln správ diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 16953c3..4ed22c8 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -499,6 +499,13 @@ Du har inga chattar än. + + ContactSync + + Could not synchronize your contacts with Telegram. + Kunde inte synkronisera dina kontakter med Telegram. + + CoverPage @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + Vidarebefordra %Ln meddelande Vidarebefordra %Ln meddelanden diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 134628e..ddfce3b 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -499,6 +499,13 @@ You don't have any chats yet. + + ContactSync + + Could not synchronize your contacts with Telegram. + + + CoverPage @@ -901,7 +908,7 @@ Forward %Ln messages dialog header - + Forward %Ln message Forward %Ln messages