Compare commits

...

25 commits

Author SHA1 Message Date
Sebastian Wolf
ab647e6e4d
Switch to gh tool for release creation, see https://github.com/actions/runner-images/issues/8362 2023-12-03 14:30:57 +01:00
Sebastian Wolf
4af73184b2
Prepare 0.17 release 2023-12-03 13:22:45 +01:00
Sebastian Wolf
c1ab982cb1
Restore content width in landscape as per discussion in #540 2023-12-03 12:59:41 +01:00
Slava Monich
b2363af36f
Tweaked the logic of moving reactions into the view (#543)
There's no need to reposition list items if reactions bar are already
fully visible.
2023-12-03 12:53:32 +01:00
free software
47ee85915d
Update harbour-fernschreiber-es.ts (#542) 2023-12-03 10:48:20 +01:00
Sebastian Wolf
4ed9495376
Highlight message that was jumped to 2023-12-03 00:48:41 +01:00
mbarashkov
2dd1d2c380
Jump to post from quote (#538)
* Jump to post from quote

* Add a setting to go to quoted message.

---------

Co-authored-by: Mikhail Barashkov <git@mbarashkov.ru>
2023-12-03 00:46:47 +01:00
Sebastian Wolf
bba4a6468c
Not only tablets have widescreen ;) 2023-12-02 23:50:13 +01:00
mbarashkov
64479f0dd3
Improve chat UI on tablets by making messages narrower and limiting content items width as well. (#540)
Co-authored-by: Mikhail Barashkov <git@mbarashkov.ru>
2023-12-02 23:44:14 +01:00
Slava Monich
8eda82da18
Fix broken signal-slot connection (#541)
QObject::connect: No such signal TDLibWrapper::chatAvailableReactionsUpdated(qlonglong, QString) in src/chatlistmodel.cpp:410
2023-12-02 23:12:52 +01:00
Sebastian Wolf
07fdabc178
Handle event updateChatAvailableReactions 2023-12-01 00:23:23 +01:00
Sebastian Wolf
80ecf50e74
Only one star per list, restore users in poll results 2023-11-29 23:47:59 +01:00
Sebastian Wolf
8258867407
Open URLs without prefix 2023-11-27 21:29:43 +01:00
Sebastian Wolf
61faf0f407
More tweaks for reactions 2023-11-26 23:36:29 +01:00
Sebastian Wolf
24edb17347
Animate new reaction button 2023-11-26 20:53:09 +01:00
Sebastian Wolf
98f067cda8
Tweak reactions again... 2023-11-26 20:36:30 +01:00
Peter G
57017e8bff
[Trivial]: Don't own bindir (#534)
* [Trivial]: Don't own bindir

This may seem like nitpicking, but the package should not own /usr/bin

* Update rpm/harbour-fernschreiber.spec

Co-authored-by: Sebastian Wolf <sebastian@ygriega.de>

---------

Co-authored-by: nephros <nemo@pgxperiiia10>
Co-authored-by: Sebastian Wolf <sebastian@ygriega.de>
2023-11-26 20:12:47 +01:00
Slava Monich
84594e4c2c
Allow to remove a reaction (#536) 2023-11-26 18:05:51 +01:00
Patrick Hervieux
2ae4e2eb05
Update French translation (#532)
Co-authored-by: Patrick Hervieux <patrick.hervieux+git@pherjung.ch>
2023-11-24 23:13:18 +01:00
free software
bada6fb3e2
Update harbour-fernschreiber-es.ts (#531) 2023-11-24 23:11:41 +01:00
Sebastian Wolf
16bcef3c78
Interaction hint for new reactions behavior 2023-11-22 22:53:17 +01:00
Sebastian Wolf
02b6dd2e6d
Show reactions on double-click 2023-11-21 21:55:08 +01:00
Slava Monich
256514e55d
Added "unread mention" indicator to the chat list (#530)
It's displayed in place of the "unread reaction" indicator. In case
if there are both unread mentions and reactions, "unread mention"
takes precedence.
2023-11-21 21:34:10 +01:00
free software
4b9732b64f
Update harbour-fernschreiber-es.ts (#529)
* Update harbour-fernschreiber-es.ts

* Update harbour-fernschreiber-es.ts
2023-11-21 21:31:41 +01:00
Slava Monich
75bf146154
Updated Russian translation (#528) 2023-11-21 21:31:23 +01:00
35 changed files with 874 additions and 309 deletions

View file

@ -84,7 +84,7 @@ jobs:
assets+=("-a" "$asset") assets+=("-a" "$asset")
done done
tag_name="${GITHUB_REF##*/}" tag_name="${GITHUB_REF##*/}"
hub release create "${assets[@]}" -m "$tag_name" "$tag_name" gh release create "$tag_name" "${assets[@]}"
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -97,6 +97,6 @@ jobs:
assets+=("-a" "$asset") assets+=("-a" "$asset")
done done
tag_name="${GITHUB_REF##*/}" tag_name="${GITHUB_REF##*/}"
hub release create -p "${assets[@]}" -m "$tag_name" -m "This is a pre-release for testing purposes only. It may or may not be unstable." -m "Join the Telegram group to help out: https://github.com/Wunderfitz/harbour-fernschreiber/issues/162" "$tag_name" gh release create "$tag_name" -p -n "This is a pre-release for testing purposes only. It may or may not be unstable." "${assets[@]}"
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -14,7 +14,11 @@ Fernschreiber wouldn't be the same without all the people helping in making it b
- Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories, bot support, github build: [jgibbon](https://github.com/jgibbon) - Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories, bot support, github build: [jgibbon](https://github.com/jgibbon)
- Copy message to clipboard: [Christian Stemmle](https://github.com/chstem) - Copy message to clipboard: [Christian Stemmle](https://github.com/chstem)
- Hide send message button if send-by-enter is switched on, focus text input on entering a chat: [santhoshmanikandan](https://github.com/santhoshmanikandan) - Hide send message button if send-by-enter is switched on, focus text input on entering a chat: [santhoshmanikandan](https://github.com/santhoshmanikandan)
- Integration of logout and sesison options to settings page: [Peter G.](https://github.com/nephros) - Integration of logout and sesison options to settings page, search results optimization, highlight unread conversations: [Peter G.](https://github.com/nephros)
- Option to always append last message in notifications: [Johannes Bachmann](https://github.com/dscheinah)
- Option to jump to quoted message, widescreen UI adjustments: [Mikhail Barashkov](https://github.com/mbarashkov)
This list might not be complete. In case I forgot something/somebody, please let me know or create a PR, thanks! :)
### Logo/Icon ### Logo/Icon
- Designed by [Matteo](https://github.com/iamnomeutente), adjustments by [Slava Monich](https://github.com/monich) - Designed by [Matteo](https://github.com/iamnomeutente), adjustments by [Slava Monich](https://github.com/monich)
@ -48,7 +52,7 @@ const char TDLIB_API_HASH[] = "1234567890abcdef1234567890abcdef";
You get the Telegram API ID and hash as soon as you've registered your own application on [https://my.telegram.org](https://my.telegram.org). You get the Telegram API ID and hash as soon as you've registered your own application on [https://my.telegram.org](https://my.telegram.org).
Moreover, you need to have a compiled version of [TDLib 1.8.3](https://github.com/tdlib/td) or higher in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`. Moreover, you need to have a compiled version of [TDLib 1.8.21](https://github.com/tdlib/td) or higher in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`.
You may just want to download the [tdlib.zip from our fork](https://github.com/Wunderfitz/td/releases) to just use the exact version of the latest official Fernschreiber release. To use it, you need to extract it into your local `tdlib/` folder as described above. If so, you're done and can compile Fernschreiber using the Sailfish SDK. If you want to build TDLib for yourself, please keep on reading. You may just want to download the [tdlib.zip from our fork](https://github.com/Wunderfitz/td/releases) to just use the exact version of the latest official Fernschreiber release. To use it, you need to extract it into your local `tdlib/` folder as described above. If so, you're done and can compile Fernschreiber using the Sailfish SDK. If you want to build TDLib for yourself, please keep on reading.

View file

@ -47,6 +47,7 @@ ListItem {
readonly property bool canDeleteMessage: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId) readonly property bool canDeleteMessage: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId)
property bool hasContentComponent property bool hasContentComponent
property bool additionalOptionsOpened property bool additionalOptionsOpened
property bool wasNavigatedTo: false
readonly property var additionalItemsModel: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ? readonly property var additionalItemsModel: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ?
extraContentLoader.item.extraContextMenuItems : 0 extraContentLoader.item.extraContextMenuItems : 0
@ -67,7 +68,7 @@ ListItem {
property var chatReactions property var chatReactions
property var messageReactions property var messageReactions
highlighted: (down || isSelected || additionalOptionsOpened) && !menuOpen highlighted: (down || isSelected || additionalOptionsOpened || wasNavigatedTo) && !menuOpen
openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting
signal replyToMessage() signal replyToMessage()
@ -115,6 +116,23 @@ ListItem {
return interactionText; return interactionText;
} }
function openReactions() {
if (messageListItem.chatReactions) {
Debug.log("Using chat reactions")
messageListItem.messageReactions = chatReactions
showItemCompletelyTimer.requestedIndex = index;
showItemCompletelyTimer.start();
} else {
Debug.log("Obtaining message reactions")
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
}
selectReactionBubble.visible = false;
}
function getContentWidthMultiplier() {
return Functions.isWidescreen(appWindow) ? 0.4 : 1.0
}
onClicked: { onClicked: {
if (messageListItem.precalculatedValues.pageIsSelecting) { if (messageListItem.precalculatedValues.pageIsSelecting) {
page.toggleMessageSelection(myMessage); page.toggleMessageSelection(myMessage);
@ -132,18 +150,18 @@ ListItem {
if (messageListItem.messageReactions) { if (messageListItem.messageReactions) {
messageListItem.messageReactions = null; messageListItem.messageReactions = null;
} else if (messageListItem.chatReactions) { selectReactionBubble.visible = false;
Debug.log("Using chat reactions")
messageListItem.messageReactions = chatReactions
showItemCompletelyTimer.requestedIndex = index;
showItemCompletelyTimer.start();
} else { } else {
Debug.log("Obtaining message reactions") selectReactionBubble.visible = !selectReactionBubble.visible;
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId); elementSelected(index);
} }
} }
} }
onDoubleClicked: {
openReactions();
}
onPressAndHold: { onPressAndHold: {
if (openMenuOnPressAndHold) { if (openMenuOnPressAndHold) {
openContextMenu() openContextMenu()
@ -167,6 +185,25 @@ ListItem {
} }
} }
Connections {
target: chatPage
onResetElements: {
messageListItem.messageReactions = null;
selectReactionBubble.visible = false;
}
onElementSelected: {
if (elementIndex !== index) {
selectReactionBubble.visible = false;
}
}
onNavigatedTo: {
if (targetIndex === index) {
messageListItem.wasNavigatedTo = true;
restoreNormalityTimer.start();
}
}
}
Loader { Loader {
id: contextMenuLoader id: contextMenuLoader
active: false active: false
@ -271,6 +308,9 @@ ListItem {
messageListItem.messageReactions = null; messageListItem.messageReactions = null;
} }
} }
onReactionsUpdated: {
chatReactions = tdLibWrapper.getChatReactions(page.chatInformation.id);
}
} }
Timer { Timer {
@ -285,15 +325,32 @@ ListItem {
onTriggered: { onTriggered: {
Debug.log("Show item completely timer triggered, requested index: " + requestedIndex + ", current index: " + index) Debug.log("Show item completely timer triggered, requested index: " + requestedIndex + ", current index: " + index)
if (requestedIndex === index) { if (requestedIndex === index) {
chatView.highlightMoveDuration = -1; var p = chatView.contentItem.mapFromItem(reactionsColumn, 0, 0)
chatView.highlightResizeDuration = -1; if (chatView.contentY > p.y || p.y + reactionsColumn.height > chatView.contentY + chatView.height) {
chatView.scrollToIndex(requestedIndex); Debug.log("Moving reactions for item at", requestedIndex, "info the view")
chatView.highlightMoveDuration = 0; chatView.highlightMoveDuration = -1
chatView.highlightResizeDuration = 0; chatView.highlightResizeDuration = -1
chatView.scrollToIndex(requestedIndex, height <= chatView.height ? ListView.Contain : ListView.End)
chatView.highlightMoveDuration = 0
chatView.highlightResizeDuration = 0
}
} }
} }
} }
Timer {
id: restoreNormalityTimer
repeat: false
running: false
interval: 1000
triggeredOnStart: false
onTriggered: {
Debug.log("Restore normality for index " + index);
messageListItem.wasNavigatedTo = false;
}
}
Component.onCompleted: { Component.onCompleted: {
delegateComponentLoadingTimer.start(); delegateComponentLoadingTimer.start();
if (myMessage.reply_to_message_id) { if (myMessage.reply_to_message_id) {
@ -336,8 +393,10 @@ ListItem {
id: messageTextRow id: messageTextRow
spacing: Theme.paddingSmall spacing: Theme.paddingSmall
width: precalculatedValues.entryWidth width: precalculatedValues.entryWidth
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: Functions.isWidescreen(appWindow) ? undefined : parent.horizontalCenter
anchors.left: Functions.isWidescreen(appWindow) ? parent.left : undefined
y: Theme.paddingSmall y: Theme.paddingSmall
anchors.leftMargin: Functions.isWidescreen(appWindow) ? Theme.paddingMedium : undefined
Loader { Loader {
id: profileThumbnailLoader id: profileThumbnailLoader
@ -454,8 +513,12 @@ ListItem {
page.toggleMessageSelection(myMessage) page.toggleMessageSelection(myMessage)
} else { } else {
messageOptionsDrawer.open = false messageOptionsDrawer.open = false
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage if(appSettings.goToQuotedMessage) {
messageOverlayLoader.active = true chatPage.showMessage(messageInReplyToRow.inReplyToMessage.id, true)
} else {
messageOverlayLoader.active = true
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage
}
} }
} }
onPressAndHold: { onPressAndHold: {
@ -567,7 +630,7 @@ ListItem {
id: webPagePreviewLoader id: webPagePreviewLoader
active: false active: false
asynchronous: true asynchronous: true
width: parent.width width: parent.width * getContentWidthMultiplier()
height: (status === Loader.Ready) ? item.implicitHeight : myMessage.content.web_page ? precalculatedValues.webPagePreviewHeight : 0 height: (status === Loader.Ready) ? item.implicitHeight : myMessage.content.web_page ? precalculatedValues.webPagePreviewHeight : 0
sourceComponent: Component { sourceComponent: Component {
@ -581,7 +644,7 @@ ListItem {
Loader { Loader {
id: extraContentLoader id: extraContentLoader
width: parent.width width: parent.width * getContentWidthMultiplier()
asynchronous: true asynchronous: true
height: item ? item.height : (messageListItem.hasContentComponent ? chatView.getContentComponentHeight(model.content_type, myMessage.content, width) : 0) height: item ? item.height : (messageListItem.hasContentComponent ? chatView.getContentComponentHeight(model.content_type, myMessage.content, width) : 0)
} }
@ -648,12 +711,50 @@ ListItem {
textFormat: Text.StyledText textFormat: Text.StyledText
maximumLineCount: 1 maximumLineCount: 1
elide: Text.ElideRight elide: Text.ElideRight
MouseArea {
anchors.fill: parent
onClicked: {
if (messageListItem.messageReactions) {
messageListItem.messageReactions = null;
selectReactionBubble.visible = false;
} else {
openReactions();
}
}
}
} }
} }
} }
} }
Rectangle {
id: selectReactionBubble
visible: false
opacity: visible ? 0.5 : 0.0
Behavior on opacity { NumberAnimation {} }
anchors {
horizontalCenter: messageListItem.isOwnMessage ? messageBackground.left : messageBackground.right
verticalCenter: messageBackground.verticalCenter
}
height: Theme.itemSizeExtraSmall
width: Theme.itemSizeExtraSmall
color: Theme.primaryColor
radius: parent.width / 2
}
IconButton {
id: selectReactionButton
visible: selectReactionBubble.visible
opacity: visible ? 1.0 : 0.0
Behavior on opacity { NumberAnimation {} }
icon.source: "image://theme/icon-s-favorite"
anchors.centerIn: selectReactionBubble
onClicked: {
openReactions();
}
}
} }
} }
@ -662,7 +763,7 @@ ListItem {
id: reactionsColumn id: reactionsColumn
width: parent.width - ( 2 * Theme.horizontalPageMargin ) width: parent.width - ( 2 * Theme.horizontalPageMargin )
anchors.top: messageTextRow.bottom anchors.top: messageTextRow.bottom
anchors.topMargin: Theme.paddingSmall anchors.topMargin: Theme.paddingMedium
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? true : false ) : false visible: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? true : false ) : false
opacity: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? 1 : 0 ) : 0 opacity: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? 1 : 0 ) : 0
@ -671,7 +772,7 @@ ListItem {
Flickable { Flickable {
width: parent.width width: parent.width
height: reactionsResultRow.height + Theme.paddingSmall height: reactionsResultRow.height + 2 * Theme.paddingMedium
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
contentWidth: reactionsResultRow.width contentWidth: reactionsResultRow.width
clip: true clip: true
@ -687,13 +788,13 @@ ListItem {
Row { Row {
id: singleReactionRow id: singleReactionRow
spacing: Theme.paddingSmall spacing: Theme.paddingMedium
Image { Image {
id: emojiPicture id: emojiPicture
source: Emoji.getEmojiPath(modelData) source: Emoji.getEmojiPath(modelData)
width: status === Image.Ready ? Theme.fontSizeLarge : 0 width: status === Image.Ready ? Theme.fontSizeExtraLarge : 0
height: Theme.fontSizeLarge height: Theme.fontSizeExtraLarge
} }
} }
@ -701,12 +802,26 @@ ListItem {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
tdLibWrapper.setMessageReaction(messageListItem.chatId, messageListItem.messageId, modelData); for (var i = 0; i < reactions.length; i++) {
messageListItem.messageReactions = null; var reaction = reactions[i]
var reactionText = reaction.reaction ? reaction.reaction : (reaction.type && reaction.type.emoji) ? reaction.type.emoji : ""
if (reactionText === modelData) {
if (reaction.is_chosen) {
// Reaction is already selected
tdLibWrapper.removeMessageReaction(chatId, messageId, reactionText)
messageReactions = null
return
}
break
}
}
// Reaction is not yet selected
tdLibWrapper.addMessageReaction(chatId, messageId, modelData)
messageReactions = null
selectReactionBubble.visible = false
} }
} }
} }
} }
} }
} }

View file

@ -108,27 +108,38 @@ ListItem {
} }
Rectangle { Rectangle {
id: chatUnreadReactionCountBackground
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
width: Theme.fontSizeLarge width: Theme.fontSizeLarge
height: Theme.fontSizeLarge height: Theme.fontSizeLarge
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
radius: parent.width / 2 radius: parent.width / 2
visible: chatListViewItem.unreadReactionCount > 0 visible: chatListViewItem.unreadReactionCount > 0 || chatListViewItem.unreadMentionCount > 0
}
Icon { Icon {
source: "image://theme/icon-s-favorite" source: "image://theme/icon-s-favorite"
height: Theme.iconSizeExtraSmall height: Theme.iconSizeExtraSmall
width: Theme.iconSizeExtraSmall width: Theme.iconSizeExtraSmall
highlighted: chatListViewItem.highlighted highlighted: chatListViewItem.highlighted
anchors.centerIn: chatUnreadReactionCountBackground anchors.centerIn: parent
visible: chatListViewItem.unreadReactionCount > 0 visible: chatListViewItem.unreadReactionCount > 0 && !chatListViewItem.unreadMentionCount
} }
Text {
font {
pixelSize: Theme.iconSizeExtraSmall
bold: true
}
color: Theme.primaryColor
anchors.centerIn: parent
visible: chatListViewItem.unreadMentionCount > 0
opacity: isMuted ? Theme.opacityHigh : 1.0
text: "@"
}
}
} }
} }
Column { Column {
id: contentColumn id: contentColumn
anchors { anchors {

View file

@ -19,9 +19,10 @@
import QtQuick 2.6 import QtQuick 2.6
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import "../../js/functions.js" as Functions
Grid { Grid {
width: parent.width - ( 2 * x ) width: parent.width - ( 2 * x )
columns: (appWindow.deviceOrientation & Orientation.LandscapeMask) || Screen.sizeCategory === Screen.Large || Screen.sizeCategory === Screen.ExtraLarge ? 2 : 1 columns: Functions.isWidescreen(appWindow) ? 2 : 1
readonly property real columnWidth: width/columns readonly property real columnWidth: width/columns
} }

View file

@ -103,6 +103,17 @@ AccordionItem {
} }
} }
TextSwitch {
width: parent.columnWidth
checked: appSettings.goToQuotedMessage
text: qsTr("Go to quoted message")
description: qsTr("When tapping a quoted message, open it in chat instead of showing it in an overlay.")
automaticCheck: false
onClicked: {
appSettings.goToQuotedMessage = !checked
}
}
ComboBox { ComboBox {
id: feedbackComboBox id: feedbackComboBox
width: parent.columnWidth width: parent.columnWidth

View file

@ -448,7 +448,12 @@ function handleLink(link) {
} else if (link.indexOf(tMePrefixHttp) === 0) { } else if (link.indexOf(tMePrefixHttp) === 0) {
handleTMeLink(link, tMePrefixHttp); handleTMeLink(link, tMePrefixHttp);
} else { } else {
Qt.openUrlExternally(link); Debug.log("Trying to open URL externally: " + link)
if (link.indexOf("://") === -1) {
Qt.openUrlExternally("https://" + link)
} else {
Qt.openUrlExternally(link);
}
} }
} }
} }
@ -535,3 +540,7 @@ function getMessagesNeededForwardPermissions(messages) {
} }
return neededPermissions return neededPermissions
} }
function isWidescreen(appWindow) {
return (appWindow.deviceOrientation & Silica.Orientation.LandscapeMask) || Silica.Screen.sizeCategory === Silica.Screen.Large || Silica.Screen.sizeCategory === Silica.Screen.ExtraLarge
}

View file

@ -54,6 +54,7 @@ Page {
property bool iterativeInitialization: false; property bool iterativeInitialization: false;
property var messageToShow; property var messageToShow;
property string messageIdToShow; property string messageIdToShow;
property string messageIdToScrollTo;
readonly property bool userIsMember: ((isPrivateChat || isSecretChat) && chatInformation["@type"]) || // should be optimized readonly property bool userIsMember: ((isPrivateChat || isSecretChat) && chatInformation["@type"]) || // should be optimized
(isBasicGroup || isSuperGroup) && ( (isBasicGroup || isSuperGroup) && (
(chatGroupInformation.status["@type"] === "chatMemberStatusMember") (chatGroupInformation.status["@type"] === "chatMemberStatusMember")
@ -67,6 +68,9 @@ Page {
property bool doSendBotStartMessage property bool doSendBotStartMessage
property string sendBotStartMessageParameter property string sendBotStartMessageParameter
property var availableReactions property var availableReactions
signal resetElements()
signal elementSelected(int elementIndex)
signal navigatedTo(int targetIndex)
states: [ states: [
State { State {
@ -407,6 +411,24 @@ Page {
chatPage.focus = true; chatPage.focus = true;
} }
function showMessage(messageId, initialRun) {
// Means we tapped a quoted message and had to load it.
if(initialRun) {
chatPage.messageIdToScrollTo = messageId
}
if (chatPage.messageIdToScrollTo && chatPage.messageIdToScrollTo != "") {
var index = chatModel.getMessageIndex(chatPage.messageIdToScrollTo);
if(index !== -1) {
chatPage.messageIdToScrollTo = "";
chatView.scrollToIndex(index);
navigatedTo(index);
} else if(initialRun) {
// we only want to do this once.
chatModel.triggerLoadHistoryForMessage(chatPage.messageIdToScrollTo)
}
}
}
Timer { Timer {
id: forwardMessagesTimer id: forwardMessagesTimer
interval: 200 interval: 200
@ -480,7 +502,10 @@ Page {
if (pageStack.depth === 1) { if (pageStack.depth === 1) {
// Only clear chat model if navigated back to overview page. In other cases we keep the information... // Only clear chat model if navigated back to overview page. In other cases we keep the information...
chatModel.clear(); chatModel.clear();
} else {
resetElements();
} }
break; break;
} }
} }
@ -576,6 +601,9 @@ Page {
onSponsoredMessageReceived: { onSponsoredMessageReceived: {
chatPage.containsSponsoredMessages = true; chatPage.containsSponsoredMessages = true;
} }
onReactionsUpdated: {
availableReactions = tdLibWrapper.getChatReactions(chatInformation.id);
}
} }
Connections { Connections {
@ -609,6 +637,19 @@ Page {
chatViewCooldownTimer.restart(); chatViewCooldownTimer.restart();
chatViewStartupReadTimer.restart(); chatViewStartupReadTimer.restart();
/*
// Double-tap for reactions is currently disabled, let's see if we'll ever need it again
var remainingDoubleTapHints = appSettings.remainingDoubleTapHints;
Debug.log("Remaining double tap hints: " + remainingDoubleTapHints);
if (remainingDoubleTapHints > 0) {
doubleTapHintTimer.start();
tapHint.visible = true;
tapHintLabel.visible = true;
appSettings.remainingDoubleTapHints = remainingDoubleTapHints - 1;
}
*/
} }
onNewMessageReceived: { onNewMessageReceived: {
if (( chatView.manuallyScrolledToBottom && Qt.application.state === Qt.ApplicationActive ) || message.sender_id.user_id === chatPage.myUserId) { if (( chatView.manuallyScrolledToBottom && Qt.application.state === Qt.ApplicationActive ) || message.sender_id.user_id === chatPage.myUserId) {
@ -636,6 +677,8 @@ Page {
if (chatView.height > chatView.contentHeight) { if (chatView.height > chatView.contentHeight) {
Debug.log("[ChatPage] Chat content quite small..."); Debug.log("[ChatPage] Chat content quite small...");
viewMessageTimer.queueViewMessage(chatView.count - 1); viewMessageTimer.queueViewMessage(chatView.count - 1);
} else if (chatPage.messageIdToScrollTo && chatPage.messageIdToScrollTo != "") {
showMessage(chatPage.messageIdToScrollTo, false)
} }
chatViewCooldownTimer.restart(); chatViewCooldownTimer.restart();
chatViewStartupReadTimer.restart(); chatViewStartupReadTimer.restart();
@ -1198,10 +1241,9 @@ Page {
manuallyScrolledToBottom = chatView.atYEnd manuallyScrolledToBottom = chatView.atYEnd
} }
function scrollToIndex(index) { function scrollToIndex(index, mode) {
if(index > 0 && index < chatView.count) { if(index > 0 && index < chatView.count) {
positionViewAtIndex(index, ListView.Contain) positionViewAtIndex(index, (mode === undefined) ? ListView.Contain : mode)
// currentIndex = index;
if(index === chatView.count - 1) { if(index === chatView.count - 1) {
manuallyScrolledToBottom = true; manuallyScrolledToBottom = true;
} }
@ -2157,4 +2199,31 @@ Page {
} }
} }
} }
Timer {
id: doubleTapHintTimer
running: true
triggeredOnStart: false
repeat: false
interval: 6000
onTriggered: {
tapHint.visible = false;
tapHintLabel.visible = false;
}
}
TapInteractionHint {
id: tapHint
loops: Animation.Infinite
taps: 2
anchors.centerIn: parent
visible: false
}
InteractionHintLabel {
id: tapHintLabel
anchors.bottom: parent.bottom
text: qsTr("Double-tap on a message to choose a reaction")
visible: false
}
} }

View file

@ -143,10 +143,11 @@ Page {
Connections { Connections {
target: tdLibWrapper target: tdLibWrapper
onUsersReceived: { onMessageSendersReceived: {
Debug.log("Received poll users...")
if(extra === optionDelegate.usersResponseIdentifierString) { if(extra === optionDelegate.usersResponseIdentifierString) {
for(var i = 0; i < userIds.length; i += 1) { for(var i = 0; i < senders.length; i += 1) {
optionDelegate.users.append({id: userIds[i], user:tdLibWrapper.getUserInformation(userIds[i])}); optionDelegate.users.append({id: senders[i].user_id, user:tdLibWrapper.getUserInformation(senders[i].user_id)});
} }
loadUsersTimer.start(); loadUsersTimer.start();
} }

View file

@ -12,6 +12,26 @@
# * date Author's Name <author's email> version-release # * date Author's Name <author's email> version-release
# - Summary of changes # - Summary of changes
* Sun Dec 03 2023 Sebastian J. Wolf <sebastian@ygriega.de> 0.17
- Update to TDLib 1.8.21, expect some hiccups ;)
- Added contacts sync (OpenRepos builds only)
- Tweaks to reaction handling (opens now on double click or click + star)
- Option to jump to quoted message
- Option to highlight unread conversations
- Option to suppress notification previews
- Option to append last message content to notifications
- Added "unread mention" indicator to chat list
- Improve message when search yields no results
- New unread info for chats with high amount of unread messages
- Setting for session inactivity timeout
- UI improvements in landscape mode
- Fix: Restore video functionality on SFOS 4.5
- Fix: Chat list timestamp now updated more reliably
- Fix: Faster reconnect after network changes
- Fix: Some URLs couldn't be opened
- Updated translations for several languages
- Thanks to monich, nephros, arustg, jgibbon, carlosgonz0, okruhliak, dscheinah, pherjung and mbarashkov for your contributions
* Sun Jun 12 2022 Sebastian J. Wolf <sebastian@ygriega.de> 0.16 * Sun Jun 12 2022 Sebastian J. Wolf <sebastian@ygriega.de> 0.16
- Support message reactions - Support message reactions
- Support t.me/+... links - Support t.me/+... links

View file

@ -12,7 +12,7 @@ Name: harbour-fernschreiber
Summary: Fernschreiber is a Telegram client for Sailfish OS Summary: Fernschreiber is a Telegram client for Sailfish OS
Version: 0.17 Version: 0.17
Release: 4 Release: 12
Group: Qt/Qt Group: Qt/Qt
License: LICENSE License: LICENSE
URL: http://werkwolf.eu/ URL: http://werkwolf.eu/
@ -69,7 +69,7 @@ desktop-file-install --delete-original \
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_bindir} %{_bindir}/%{name}
%{_datadir}/%{name} %{_datadir}/%{name}
%{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png %{_datadir}/icons/hicolor/*/apps/%{name}.png

View file

@ -1,7 +1,7 @@
Name: harbour-fernschreiber Name: harbour-fernschreiber
Summary: Fernschreiber is a Telegram client for Sailfish OS Summary: Fernschreiber is a Telegram client for Sailfish OS
Version: 0.17 Version: 0.17
Release: 4 Release: 12
# The contents of the Group field should be one of the groups listed here: # The contents of the Group field should be one of the groups listed here:
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS # https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
Group: Qt/Qt Group: Qt/Qt
@ -46,7 +46,7 @@ Requires:
# All installed files # All installed files
Files: Files:
- '%{_bindir}' - '%{_bindir}/%{name}'
- '%{_datadir}/%{name}' - '%{_datadir}/%{name}'
- '%{_datadir}/applications/%{name}.desktop' - '%{_datadir}/applications/%{name}.desktop'
- '%{_datadir}/icons/hicolor/*/apps/%{name}.png' - '%{_datadir}/icons/hicolor/*/apps/%{name}.png'

View file

@ -32,9 +32,11 @@ namespace {
const QString KEY_NOTIFICATION_SUPPRESS_ENABLED("notificationSuppressContent"); const QString KEY_NOTIFICATION_SUPPRESS_ENABLED("notificationSuppressContent");
const QString KEY_NOTIFICATION_FEEDBACK("notificationFeedback"); const QString KEY_NOTIFICATION_FEEDBACK("notificationFeedback");
const QString KEY_NOTIFICATION_ALWAYS_SHOW_PREVIEW("notificationAlwaysShowPreview"); const QString KEY_NOTIFICATION_ALWAYS_SHOW_PREVIEW("notificationAlwaysShowPreview");
const QString KEY_GO_TO_QUOTED_MESSAGE("goToQuotedMessage");
const QString KEY_STORAGE_OPTIMIZER("useStorageOptimizer"); const QString KEY_STORAGE_OPTIMIZER("useStorageOptimizer");
const QString KEY_INLINEBOT_LOCATION_ACCESS("allowInlineBotLocationAccess"); const QString KEY_INLINEBOT_LOCATION_ACCESS("allowInlineBotLocationAccess");
const QString KEY_REMAINING_INTERACTION_HINTS("remainingInteractionHints"); const QString KEY_REMAINING_INTERACTION_HINTS("remainingInteractionHints");
const QString KEY_REMAINING_DOUBLE_TAP_HINTS("remainingDoubleTapHints");
const QString KEY_ONLINE_ONLY_MODE("onlineOnlyMode"); const QString KEY_ONLINE_ONLY_MODE("onlineOnlyMode");
const QString KEY_DELAY_MESSAGE_READ("delayMessageRead"); const QString KEY_DELAY_MESSAGE_READ("delayMessageRead");
const QString KEY_FOCUS_TEXTAREA_ON_CHAT_OPEN("focusTextAreaOnChatOpen"); const QString KEY_FOCUS_TEXTAREA_ON_CHAT_OPEN("focusTextAreaOnChatOpen");
@ -200,6 +202,20 @@ void AppSettings::setNotificationAlwaysShowPreview(bool enable)
} }
} }
bool AppSettings::goToQuotedMessage() const
{
return settings.value(KEY_GO_TO_QUOTED_MESSAGE, false).toBool();
}
void AppSettings::setGoToQuotedMessage(bool enable)
{
if (goToQuotedMessage() != enable) {
LOG(KEY_GO_TO_QUOTED_MESSAGE << enable);
settings.setValue(KEY_GO_TO_QUOTED_MESSAGE, enable);
emit goToQuotedMessageChanged();
}
}
bool AppSettings::storageOptimizer() const bool AppSettings::storageOptimizer() const
{ {
return settings.value(KEY_STORAGE_OPTIMIZER, true).toBool(); return settings.value(KEY_STORAGE_OPTIMIZER, true).toBool();
@ -243,6 +259,20 @@ void AppSettings::setRemainingInteractionHints(int remainingHints)
} }
} }
int AppSettings::remainingDoubleTapHints() const
{
return settings.value(KEY_REMAINING_DOUBLE_TAP_HINTS, 3).toInt();
}
void AppSettings::setRemainingDoubleTapHints(int remainingHints)
{
if (remainingDoubleTapHints() != remainingHints) {
LOG(KEY_REMAINING_DOUBLE_TAP_HINTS << remainingHints);
settings.setValue(KEY_REMAINING_DOUBLE_TAP_HINTS, remainingHints);
emit remainingDoubleTapHintsChanged();
}
}
bool AppSettings::onlineOnlyMode() const bool AppSettings::onlineOnlyMode() const
{ {
return settings.value(KEY_ONLINE_ONLY_MODE, false).toBool(); return settings.value(KEY_ONLINE_ONLY_MODE, false).toBool();

View file

@ -35,9 +35,11 @@ class AppSettings : public QObject {
Q_PROPERTY(bool notificationSuppressContent READ notificationSuppressContent WRITE setNotificationSuppressContent NOTIFY notificationSuppressContentChanged) Q_PROPERTY(bool notificationSuppressContent READ notificationSuppressContent WRITE setNotificationSuppressContent NOTIFY notificationSuppressContentChanged)
Q_PROPERTY(NotificationFeedback notificationFeedback READ notificationFeedback WRITE setNotificationFeedback NOTIFY notificationFeedbackChanged) Q_PROPERTY(NotificationFeedback notificationFeedback READ notificationFeedback WRITE setNotificationFeedback NOTIFY notificationFeedbackChanged)
Q_PROPERTY(bool notificationAlwaysShowPreview READ notificationAlwaysShowPreview WRITE setNotificationAlwaysShowPreview NOTIFY notificationAlwaysShowPreviewChanged) Q_PROPERTY(bool notificationAlwaysShowPreview READ notificationAlwaysShowPreview WRITE setNotificationAlwaysShowPreview NOTIFY notificationAlwaysShowPreviewChanged)
Q_PROPERTY(bool goToQuotedMessage READ goToQuotedMessage WRITE setGoToQuotedMessage NOTIFY goToQuotedMessageChanged)
Q_PROPERTY(bool storageOptimizer READ storageOptimizer WRITE setStorageOptimizer NOTIFY storageOptimizerChanged) Q_PROPERTY(bool storageOptimizer READ storageOptimizer WRITE setStorageOptimizer NOTIFY storageOptimizerChanged)
Q_PROPERTY(bool allowInlineBotLocationAccess READ allowInlineBotLocationAccess WRITE setAllowInlineBotLocationAccess NOTIFY allowInlineBotLocationAccessChanged) Q_PROPERTY(bool allowInlineBotLocationAccess READ allowInlineBotLocationAccess WRITE setAllowInlineBotLocationAccess NOTIFY allowInlineBotLocationAccessChanged)
Q_PROPERTY(int remainingInteractionHints READ remainingInteractionHints WRITE setRemainingInteractionHints NOTIFY remainingInteractionHintsChanged) Q_PROPERTY(int remainingInteractionHints READ remainingInteractionHints WRITE setRemainingInteractionHints NOTIFY remainingInteractionHintsChanged)
Q_PROPERTY(int remainingDoubleTapHints READ remainingDoubleTapHints WRITE setRemainingDoubleTapHints NOTIFY remainingDoubleTapHintsChanged)
Q_PROPERTY(bool onlineOnlyMode READ onlineOnlyMode WRITE setOnlineOnlyMode NOTIFY onlineOnlyModeChanged) Q_PROPERTY(bool onlineOnlyMode READ onlineOnlyMode WRITE setOnlineOnlyMode NOTIFY onlineOnlyModeChanged)
Q_PROPERTY(bool delayMessageRead READ delayMessageRead WRITE setDelayMessageRead NOTIFY delayMessageReadChanged) Q_PROPERTY(bool delayMessageRead READ delayMessageRead WRITE setDelayMessageRead NOTIFY delayMessageReadChanged)
Q_PROPERTY(bool focusTextAreaOnChatOpen READ getFocusTextAreaOnChatOpen WRITE setFocusTextAreaOnChatOpen NOTIFY focusTextAreaOnChatOpenChanged) Q_PROPERTY(bool focusTextAreaOnChatOpen READ getFocusTextAreaOnChatOpen WRITE setFocusTextAreaOnChatOpen NOTIFY focusTextAreaOnChatOpenChanged)
@ -95,6 +97,9 @@ public:
bool notificationAlwaysShowPreview() const; bool notificationAlwaysShowPreview() const;
void setNotificationAlwaysShowPreview(bool enable); void setNotificationAlwaysShowPreview(bool enable);
bool goToQuotedMessage() const;
void setGoToQuotedMessage(bool enable);
bool storageOptimizer() const; bool storageOptimizer() const;
void setStorageOptimizer(bool enable); void setStorageOptimizer(bool enable);
@ -104,6 +109,9 @@ public:
int remainingInteractionHints() const; int remainingInteractionHints() const;
void setRemainingInteractionHints(int remainingHints); void setRemainingInteractionHints(int remainingHints);
int remainingDoubleTapHints() const;
void setRemainingDoubleTapHints(int remainingHints);
bool onlineOnlyMode() const; bool onlineOnlyMode() const;
void setOnlineOnlyMode(bool enable); void setOnlineOnlyMode(bool enable);
@ -131,9 +139,11 @@ signals:
void notificationSuppressContentChanged(); void notificationSuppressContentChanged();
void notificationFeedbackChanged(); void notificationFeedbackChanged();
void notificationAlwaysShowPreviewChanged(); void notificationAlwaysShowPreviewChanged();
void goToQuotedMessageChanged();
void storageOptimizerChanged(); void storageOptimizerChanged();
void allowInlineBotLocationAccessChanged(); void allowInlineBotLocationAccessChanged();
void remainingInteractionHintsChanged(); void remainingInteractionHintsChanged();
void remainingDoubleTapHintsChanged();
void onlineOnlyModeChanged(); void onlineOnlyModeChanged();
void delayMessageReadChanged(); void delayMessageReadChanged();
void focusTextAreaOnChatOpenChanged(); void focusTextAreaOnChatOpenChanged();

View file

@ -44,6 +44,7 @@ namespace {
const QString UNREAD_COUNT("unread_count"); const QString UNREAD_COUNT("unread_count");
const QString UNREAD_MENTION_COUNT("unread_mention_count"); const QString UNREAD_MENTION_COUNT("unread_mention_count");
const QString UNREAD_REACTION_COUNT("unread_reaction_count"); const QString UNREAD_REACTION_COUNT("unread_reaction_count");
const QString AVAILABLE_REACTIONS("available_reactions");
const QString NOTIFICATION_SETTINGS("notification_settings"); const QString NOTIFICATION_SETTINGS("notification_settings");
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id");
@ -70,6 +71,7 @@ public:
int unreadCount() const; int unreadCount() const;
int unreadMentionCount() const; int unreadMentionCount() const;
int unreadReactionCount() const; int unreadReactionCount() const;
QVariant availableReactions() const;
QVariant photoSmall() const; QVariant photoSmall() const;
qlonglong lastReadInboxMessageId() const; qlonglong lastReadInboxMessageId() const;
qlonglong senderUserId() const; qlonglong senderUserId() const;
@ -168,6 +170,11 @@ int ChatListModel::ChatData::unreadMentionCount() const
return chatData.value(UNREAD_MENTION_COUNT).toInt(); return chatData.value(UNREAD_MENTION_COUNT).toInt();
} }
QVariant ChatListModel::ChatData::availableReactions() const
{
return chatData.value(AVAILABLE_REACTIONS);
}
int ChatListModel::ChatData::unreadReactionCount() const int ChatListModel::ChatData::unreadReactionCount() const
{ {
return chatData.value(UNREAD_REACTION_COUNT).toInt(); return chatData.value(UNREAD_REACTION_COUNT).toInt();
@ -400,6 +407,7 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper, AppSettings *appSetting
connect(tdLibWrapper, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString)), this, SLOT(handleChatDraftMessageUpdated(qlonglong, QVariantMap, QString))); connect(tdLibWrapper, SIGNAL(chatDraftMessageUpdated(qlonglong, QVariantMap, QString)), this, SLOT(handleChatDraftMessageUpdated(qlonglong, QVariantMap, QString)));
connect(tdLibWrapper, SIGNAL(chatUnreadMentionCountUpdated(qlonglong, int)), this, SLOT(handleChatUnreadMentionCountUpdated(qlonglong, int))); connect(tdLibWrapper, SIGNAL(chatUnreadMentionCountUpdated(qlonglong, int)), this, SLOT(handleChatUnreadMentionCountUpdated(qlonglong, int)));
connect(tdLibWrapper, SIGNAL(chatUnreadReactionCountUpdated(qlonglong, int)), this, SLOT(handleChatUnreadReactionCountUpdated(qlonglong, int))); connect(tdLibWrapper, SIGNAL(chatUnreadReactionCountUpdated(qlonglong, int)), this, SLOT(handleChatUnreadReactionCountUpdated(qlonglong, int)));
connect(tdLibWrapper, SIGNAL(chatAvailableReactionsUpdated(qlonglong,QVariantMap)), this, SLOT(handleChatAvailableReactionsUpdated(qlonglong,QVariantMap)));
// Don't start the timer until we have at least one chat // Don't start the timer until we have at least one chat
relativeTimeRefreshTimer = new QTimer(this); relativeTimeRefreshTimer = new QTimer(this);
@ -436,6 +444,7 @@ QHash<int,QByteArray> ChatListModel::roleNames() const
roles.insert(ChatListModel::RoleUnreadCount, "unread_count"); roles.insert(ChatListModel::RoleUnreadCount, "unread_count");
roles.insert(ChatListModel::RoleUnreadMentionCount, "unread_mention_count"); roles.insert(ChatListModel::RoleUnreadMentionCount, "unread_mention_count");
roles.insert(ChatListModel::RoleUnreadReactionCount, "unread_reaction_count"); roles.insert(ChatListModel::RoleUnreadReactionCount, "unread_reaction_count");
roles.insert(ChatListModel::RoleAvailableReactions, "available_reactions");
roles.insert(ChatListModel::RoleLastReadInboxMessageId, "last_read_inbox_message_id"); roles.insert(ChatListModel::RoleLastReadInboxMessageId, "last_read_inbox_message_id");
roles.insert(ChatListModel::RoleLastMessageSenderId, "last_message_sender_id"); roles.insert(ChatListModel::RoleLastMessageSenderId, "last_message_sender_id");
roles.insert(ChatListModel::RoleLastMessageDate, "last_message_date"); roles.insert(ChatListModel::RoleLastMessageDate, "last_message_date");
@ -472,6 +481,7 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const
case ChatListModel::RolePhotoSmall: return data->photoSmall(); case ChatListModel::RolePhotoSmall: return data->photoSmall();
case ChatListModel::RoleUnreadCount: return data->unreadCount(); case ChatListModel::RoleUnreadCount: return data->unreadCount();
case ChatListModel::RoleUnreadMentionCount: return data->unreadMentionCount(); case ChatListModel::RoleUnreadMentionCount: return data->unreadMentionCount();
case ChatListModel::RoleAvailableReactions: return data->availableReactions();
case ChatListModel::RoleUnreadReactionCount: return data->unreadReactionCount(); case ChatListModel::RoleUnreadReactionCount: return data->unreadReactionCount();
case ChatListModel::RoleLastReadInboxMessageId: return data->lastReadInboxMessageId(); case ChatListModel::RoleLastReadInboxMessageId: return data->lastReadInboxMessageId();
case ChatListModel::RoleLastMessageSenderId: return data->senderUserId(); case ChatListModel::RoleLastMessageSenderId: return data->senderUserId();
@ -1036,6 +1046,26 @@ void ChatListModel::handleChatUnreadReactionCountUpdated(qlonglong chatId, int u
} }
} }
void ChatListModel::handleChatAvailableReactionsUpdated(qlonglong chatId, const QVariantMap availableReactions)
{
if (chatIndexMap.contains(chatId)) {
LOG("Updating available reaction type for" << chatId << availableReactions);
const int chatIndex = chatIndexMap.value(chatId);
ChatData *chat = chatList.at(chatIndex);
chat->chatData.insert(AVAILABLE_REACTIONS, availableReactions);
QVector<int> changedRoles;
changedRoles.append(ChatListModel::RoleAvailableReactions);
const QModelIndex modelIndex(index(chatIndex));
emit dataChanged(modelIndex, modelIndex, changedRoles);
} else {
ChatData *chat = hiddenChats.value(chatId);
if (chat) {
LOG("Updating available reaction type for hidden chat" << chatId << availableReactions);
chat->chatData.insert(AVAILABLE_REACTIONS, availableReactions);
}
}
}
void ChatListModel::handleRelativeTimeRefreshTimer() void ChatListModel::handleRelativeTimeRefreshTimer()
{ {
LOG("Refreshing timestamps"); LOG("Refreshing timestamps");

View file

@ -42,6 +42,7 @@ public:
RoleUnreadCount, RoleUnreadCount,
RoleUnreadMentionCount, RoleUnreadMentionCount,
RoleUnreadReactionCount, RoleUnreadReactionCount,
RoleAvailableReactions,
RoleLastReadInboxMessageId, RoleLastReadInboxMessageId,
RoleLastMessageSenderId, RoleLastMessageSenderId,
RoleLastMessageDate, RoleLastMessageDate,
@ -93,6 +94,7 @@ private slots:
void handleChatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order); void handleChatDraftMessageUpdated(qlonglong chatId, const QVariantMap &draftMessage, const QString &order);
void handleChatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount); void handleChatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount);
void handleChatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount); void handleChatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount);
void handleChatAvailableReactionsUpdated(qlonglong chatId, const QVariantMap availableReactions);
void handleRelativeTimeRefreshTimer(); void handleRelativeTimeRefreshTimer();
signals: signals:

View file

@ -363,6 +363,15 @@ void ChatModel::initialize(const QVariantMap &chatInformation)
tdLibWrapper->getChatHistory(chatId, this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong()); tdLibWrapper->getChatHistory(chatId, this->chatInformation.value(LAST_READ_INBOX_MESSAGE_ID).toLongLong());
} }
void ChatModel::triggerLoadHistoryForMessage(qlonglong messageId)
{
if (!this->inIncrementalUpdate && !messages.isEmpty()) {
LOG("Trigger loading message with id..." << messageId);
this->inIncrementalUpdate = true;
this->tdLibWrapper->getChatHistory(chatId, messageId);
}
}
void ChatModel::triggerLoadMoreHistory() void ChatModel::triggerLoadMoreHistory()
{ {
if (!this->inIncrementalUpdate && !messages.isEmpty()) { if (!this->inIncrementalUpdate && !messages.isEmpty()) {
@ -400,6 +409,17 @@ QVariantMap ChatModel::getMessage(int index)
return QVariantMap(); return QVariantMap();
} }
int ChatModel::getMessageIndex(qlonglong messageId)
{
if (messages.size() == 0) {
return -1;
}
if (messageIndexMap.contains(messageId)) {
return messageIndexMap.value(messageId);
}
return -1;
}
int ChatModel::getLastReadMessageIndex() int ChatModel::getLastReadMessageIndex()
{ {
LOG("Obtaining last read message index"); LOG("Obtaining last read message index");

View file

@ -40,12 +40,14 @@ public:
Q_INVOKABLE void clear(bool contentOnly = false); Q_INVOKABLE void clear(bool contentOnly = false);
Q_INVOKABLE void initialize(const QVariantMap &chatInformation); Q_INVOKABLE void initialize(const QVariantMap &chatInformation);
Q_INVOKABLE void triggerLoadMoreHistory(); Q_INVOKABLE void triggerLoadMoreHistory();
Q_INVOKABLE void triggerLoadHistoryForMessage(qlonglong messageId);
Q_INVOKABLE void triggerLoadMoreFuture(); Q_INVOKABLE void triggerLoadMoreFuture();
Q_INVOKABLE QVariantMap getChatInformation(); Q_INVOKABLE QVariantMap getChatInformation();
Q_INVOKABLE QVariantMap getMessage(int index); Q_INVOKABLE QVariantMap getMessage(int index);
Q_INVOKABLE int getLastReadMessageIndex(); Q_INVOKABLE int getLastReadMessageIndex();
Q_INVOKABLE void setSearchQuery(const QString newSearchQuery); Q_INVOKABLE void setSearchQuery(const QString newSearchQuery);
Q_INVOKABLE int getMessageIndex(qlonglong messageId);
QVariantMap smallPhoto() const; QVariantMap smallPhoto() const;
qlonglong getChatId() const; qlonglong getChatId() const;

View file

@ -46,6 +46,7 @@ namespace {
const QString UNREAD_COUNT("unread_count"); const QString UNREAD_COUNT("unread_count");
const QString UNREAD_MENTION_COUNT("unread_mention_count"); const QString UNREAD_MENTION_COUNT("unread_mention_count");
const QString UNREAD_REACTION_COUNT("unread_reaction_count"); const QString UNREAD_REACTION_COUNT("unread_reaction_count");
const QString AVAILABLE_REACTIONS("available_reactions");
const QString TEXT("text"); const QString TEXT("text");
const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id");
const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id");
@ -123,6 +124,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("updateChatPosition", &TDLibReceiver::processUpdateChatPosition); handlers.insert("updateChatPosition", &TDLibReceiver::processUpdateChatPosition);
handlers.insert("updateChatReadInbox", &TDLibReceiver::processUpdateChatReadInbox); handlers.insert("updateChatReadInbox", &TDLibReceiver::processUpdateChatReadInbox);
handlers.insert("updateChatReadOutbox", &TDLibReceiver::processUpdateChatReadOutbox); handlers.insert("updateChatReadOutbox", &TDLibReceiver::processUpdateChatReadOutbox);
handlers.insert("updateChatAvailableReactions", &TDLibReceiver::processUpdateChatAvailableReactions);
handlers.insert("updateBasicGroup", &TDLibReceiver::processUpdateBasicGroup); handlers.insert("updateBasicGroup", &TDLibReceiver::processUpdateBasicGroup);
handlers.insert("updateSupergroup", &TDLibReceiver::processUpdateSuperGroup); handlers.insert("updateSupergroup", &TDLibReceiver::processUpdateSuperGroup);
handlers.insert("updateChatOnlineMemberCount", &TDLibReceiver::processChatOnlineMemberCountUpdated); handlers.insert("updateChatOnlineMemberCount", &TDLibReceiver::processChatOnlineMemberCountUpdated);
@ -160,6 +162,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("updateChatPinnedMessage", &TDLibReceiver::processUpdateChatPinnedMessage); handlers.insert("updateChatPinnedMessage", &TDLibReceiver::processUpdateChatPinnedMessage);
handlers.insert("updateMessageIsPinned", &TDLibReceiver::processUpdateMessageIsPinned); handlers.insert("updateMessageIsPinned", &TDLibReceiver::processUpdateMessageIsPinned);
handlers.insert("users", &TDLibReceiver::processUsers); handlers.insert("users", &TDLibReceiver::processUsers);
handlers.insert("messageSenders", &TDLibReceiver::processMessageSenders);
handlers.insert("error", &TDLibReceiver::processError); handlers.insert("error", &TDLibReceiver::processError);
handlers.insert("ok", &TDLibReceiver::ok); handlers.insert("ok", &TDLibReceiver::ok);
handlers.insert("secretChat", &TDLibReceiver::processSecretChat); handlers.insert("secretChat", &TDLibReceiver::processSecretChat);
@ -175,6 +178,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren
handlers.insert("updateMessageInteractionInfo", &TDLibReceiver::processUpdateMessageInteractionInfo); handlers.insert("updateMessageInteractionInfo", &TDLibReceiver::processUpdateMessageInteractionInfo);
handlers.insert("sessions", &TDLibReceiver::processSessions); handlers.insert("sessions", &TDLibReceiver::processSessions);
handlers.insert("availableReactions", &TDLibReceiver::processAvailableReactions); handlers.insert("availableReactions", &TDLibReceiver::processAvailableReactions);
handlers.insert("updateMessageMentionRead", &TDLibReceiver::processUpdateChatUnreadMentionCount);
handlers.insert("updateChatUnreadMentionCount", &TDLibReceiver::processUpdateChatUnreadMentionCount); handlers.insert("updateChatUnreadMentionCount", &TDLibReceiver::processUpdateChatUnreadMentionCount);
handlers.insert("updateChatUnreadReactionCount", &TDLibReceiver::processUpdateChatUnreadReactionCount); handlers.insert("updateChatUnreadReactionCount", &TDLibReceiver::processUpdateChatUnreadReactionCount);
handlers.insert("updateActiveEmojiReactions", &TDLibReceiver::processUpdateActiveEmojiReactions); handlers.insert("updateActiveEmojiReactions", &TDLibReceiver::processUpdateActiveEmojiReactions);
@ -361,6 +365,14 @@ void TDLibReceiver::processUpdateChatReadOutbox(const QVariantMap &receivedInfor
emit chatReadOutboxUpdated(chat_id, last_read_outbox_message_id); emit chatReadOutboxUpdated(chat_id, last_read_outbox_message_id);
} }
void TDLibReceiver::processUpdateChatAvailableReactions(const QVariantMap &receivedInformation)
{
const qlonglong chat_id(receivedInformation.value(CHAT_ID).toLongLong());
const QVariantMap available_reactions(receivedInformation.value(AVAILABLE_REACTIONS).toMap());
LOG("Available reactions updated for" << chat_id << "new information:" << available_reactions);
emit chatAvailableReactionsUpdated(chat_id, available_reactions);
}
void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation) void TDLibReceiver::processUpdateBasicGroup(const QVariantMap &receivedInformation)
{ {
const QVariantMap basicGroup(receivedInformation.value(BASIC_GROUP).toMap()); const QVariantMap basicGroup(receivedInformation.value(BASIC_GROUP).toMap());
@ -633,6 +645,12 @@ void TDLibReceiver::processUsers(const QVariantMap &receivedInformation)
emit usersReceived(receivedInformation.value(_EXTRA).toString(), receivedInformation.value("user_ids").toList(), receivedInformation.value(TOTAL_COUNT).toInt()); emit usersReceived(receivedInformation.value(_EXTRA).toString(), receivedInformation.value("user_ids").toList(), receivedInformation.value(TOTAL_COUNT).toInt());
} }
void TDLibReceiver::processMessageSenders(const QVariantMap &receivedInformation)
{
LOG("Received Message Senders");
emit messageSendersReceived(receivedInformation.value(_EXTRA).toString(), receivedInformation.value("senders").toList(), receivedInformation.value(TOTAL_COUNT).toInt());
}
void TDLibReceiver::processError(const QVariantMap &receivedInformation) void TDLibReceiver::processError(const QVariantMap &receivedInformation)
{ {
LOG("Received an error"); LOG("Received an error");
@ -736,6 +754,8 @@ void TDLibReceiver::processAvailableReactions(const QVariantMap &receivedInforma
void TDLibReceiver::processUpdateChatUnreadMentionCount(const QVariantMap &receivedInformation) void TDLibReceiver::processUpdateChatUnreadMentionCount(const QVariantMap &receivedInformation)
{ {
// Handles both updateMessageMentionRead and updateChatUnreadMentionCount
// They both have chat_id and unread_mention_count which is all we need
const qlonglong chatId = receivedInformation.value(CHAT_ID).toLongLong(); const qlonglong chatId = receivedInformation.value(CHAT_ID).toLongLong();
const int unreadMentionCount = receivedInformation.value(UNREAD_MENTION_COUNT).toInt(); const int unreadMentionCount = receivedInformation.value(UNREAD_MENTION_COUNT).toInt();
LOG("Chat unread mention count updated" << chatId << unreadMentionCount); LOG("Chat unread mention count updated" << chatId << unreadMentionCount);

View file

@ -52,6 +52,7 @@ signals:
void chatPinnedUpdated(qlonglong chatId, bool isPinned); void chatPinnedUpdated(qlonglong chatId, bool isPinned);
void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, int unreadCount); void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, int unreadCount);
void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void chatAvailableReactionsUpdated(const qlonglong &chatId, const QVariantMap &availableReactions);
void basicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void basicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void superGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void superGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void chatOnlineMemberCountUpdated(const QString &chatId, int onlineMemberCount); void chatOnlineMemberCountUpdated(const QString &chatId, int onlineMemberCount);
@ -88,7 +89,8 @@ signals:
void chatTitleUpdated(const QString &chatId, const QString &title); void chatTitleUpdated(const QString &chatId, const QString &title);
void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId); void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId);
void messageIsPinnedUpdated(qlonglong chatId, qlonglong messageId, bool isPinned); void messageIsPinnedUpdated(qlonglong chatId, qlonglong messageId, bool isPinned);
void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); void usersReceived(const QString &extra, const QVariantList &senders, int totalUsers);
void messageSendersReceived(const QString &extra, const QVariantList &userIds, int totalUsers);
void errorReceived(const int code, const QString &message, const QString &extra); void errorReceived(const int code, const QString &message, const QString &extra);
void secretChat(qlonglong secretChatId, const QVariantMap &secretChat); void secretChat(qlonglong secretChatId, const QVariantMap &secretChat);
void secretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void secretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat);
@ -135,6 +137,7 @@ private:
void processUpdateChatPosition(const QVariantMap &receivedInformation); void processUpdateChatPosition(const QVariantMap &receivedInformation);
void processUpdateChatReadInbox(const QVariantMap &receivedInformation); void processUpdateChatReadInbox(const QVariantMap &receivedInformation);
void processUpdateChatReadOutbox(const QVariantMap &receivedInformation); void processUpdateChatReadOutbox(const QVariantMap &receivedInformation);
void processUpdateChatAvailableReactions(const QVariantMap &receivedInformation);
void processUpdateBasicGroup(const QVariantMap &receivedInformation); void processUpdateBasicGroup(const QVariantMap &receivedInformation);
void processUpdateSuperGroup(const QVariantMap &receivedInformation); void processUpdateSuperGroup(const QVariantMap &receivedInformation);
void processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation); void processChatOnlineMemberCountUpdated(const QVariantMap &receivedInformation);
@ -173,6 +176,7 @@ private:
void processUpdateChatPinnedMessage(const QVariantMap &receivedInformation); void processUpdateChatPinnedMessage(const QVariantMap &receivedInformation);
void processUpdateMessageIsPinned(const QVariantMap &receivedInformation); void processUpdateMessageIsPinned(const QVariantMap &receivedInformation);
void processUsers(const QVariantMap &receivedInformation); void processUsers(const QVariantMap &receivedInformation);
void processMessageSenders(const QVariantMap &receivedInformation);
void processError(const QVariantMap &receivedInformation); void processError(const QVariantMap &receivedInformation);
void processSecretChat(const QVariantMap &receivedInformation); void processSecretChat(const QVariantMap &receivedInformation);
void processUpdateSecretChat(const QVariantMap &receivedInformation); void processUpdateSecretChat(const QVariantMap &receivedInformation);

View file

@ -137,6 +137,7 @@ void TDLibWrapper::initializeTDLibReceiver() {
connect(this->tdLibReceiver, SIGNAL(chatOrderUpdated(QString, QString)), this, SIGNAL(chatOrderUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(chatOrderUpdated(QString, QString)), this, SIGNAL(chatOrderUpdated(QString, QString)));
connect(this->tdLibReceiver, SIGNAL(chatReadInboxUpdated(QString, QString, int)), this, SIGNAL(chatReadInboxUpdated(QString, QString, int))); connect(this->tdLibReceiver, SIGNAL(chatReadInboxUpdated(QString, QString, int)), this, SIGNAL(chatReadInboxUpdated(QString, QString, int)));
connect(this->tdLibReceiver, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SIGNAL(chatReadOutboxUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(chatReadOutboxUpdated(QString, QString)), this, SIGNAL(chatReadOutboxUpdated(QString, QString)));
connect(this->tdLibReceiver, SIGNAL(chatAvailableReactionsUpdated(qlonglong, QVariantMap)), this, SLOT(handleAvailableReactionsUpdated(qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleBasicGroupUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(basicGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleBasicGroupUpdated(qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleSuperGroupUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(superGroupUpdated(qlonglong, QVariantMap)), this, SLOT(handleSuperGroupUpdated(qlonglong, QVariantMap)));
connect(this->tdLibReceiver, SIGNAL(chatOnlineMemberCountUpdated(QString, int)), this, SIGNAL(chatOnlineMemberCountUpdated(QString, int))); connect(this->tdLibReceiver, SIGNAL(chatOnlineMemberCountUpdated(QString, int)), this, SIGNAL(chatOnlineMemberCountUpdated(QString, int)));
@ -176,6 +177,7 @@ void TDLibWrapper::initializeTDLibReceiver() {
connect(this->tdLibReceiver, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong))); connect(this->tdLibReceiver, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)));
connect(this->tdLibReceiver, SIGNAL(messageIsPinnedUpdated(qlonglong, qlonglong, bool)), this, SLOT(handleMessageIsPinnedUpdated(qlonglong, qlonglong, bool))); connect(this->tdLibReceiver, SIGNAL(messageIsPinnedUpdated(qlonglong, qlonglong, bool)), this, SLOT(handleMessageIsPinnedUpdated(qlonglong, qlonglong, bool)));
connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SIGNAL(usersReceived(QString, QVariantList, int))); connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SIGNAL(usersReceived(QString, QVariantList, int)));
connect(this->tdLibReceiver, SIGNAL(messageSendersReceived(QString, QVariantList, int)), this, SIGNAL(messageSendersReceived(QString, QVariantList, int)));
connect(this->tdLibReceiver, SIGNAL(errorReceived(int, QString, QString)), this, SLOT(handleErrorReceived(int, QString, QString))); connect(this->tdLibReceiver, SIGNAL(errorReceived(int, QString, QString)), this, SLOT(handleErrorReceived(int, QString, QString)));
connect(this->tdLibReceiver, SIGNAL(contactsImported(QVariantList, QVariantList)), this, SIGNAL(contactsImported(QVariantList, QVariantList))); connect(this->tdLibReceiver, SIGNAL(contactsImported(QVariantList, QVariantList)), this, SIGNAL(contactsImported(QVariantList, QVariantList)));
connect(this->tdLibReceiver, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap)), this, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap)), this, SIGNAL(messageEditedUpdated(qlonglong, qlonglong, QVariantMap)));
@ -1462,9 +1464,8 @@ void TDLibWrapper::getPageSource(const QString &address)
connect(reply, SIGNAL(finished()), this, SLOT(handleGetPageSourceFinished())); connect(reply, SIGNAL(finished()), this, SLOT(handleGetPageSourceFinished()));
} }
void TDLibWrapper::setMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction) void TDLibWrapper::addMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction)
{ {
LOG("Set message reaction" << chatId << messageId << reaction);
QVariantMap requestObject; QVariantMap requestObject;
requestObject.insert(CHAT_ID, chatId); requestObject.insert(CHAT_ID, chatId);
requestObject.insert(MESSAGE_ID, messageId); requestObject.insert(MESSAGE_ID, messageId);
@ -1479,9 +1480,35 @@ void TDLibWrapper::setMessageReaction(qlonglong chatId, qlonglong messageId, con
reactionType.insert(EMOJI, reaction); reactionType.insert(EMOJI, reaction);
requestObject.insert(REACTION_TYPE, reactionType); requestObject.insert(REACTION_TYPE, reactionType);
requestObject.insert(_TYPE, "addMessageReaction"); requestObject.insert(_TYPE, "addMessageReaction");
LOG("Add message reaction" << chatId << messageId << reaction);
} else { } else {
requestObject.insert("reaction", reaction); requestObject.insert("reaction", reaction);
requestObject.insert(_TYPE, "setMessageReaction"); requestObject.insert(_TYPE, "setMessageReaction");
LOG("Toggle message reaction" << chatId << messageId << reaction);
}
this->sendRequest(requestObject);
}
void TDLibWrapper::removeMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction)
{
QVariantMap requestObject;
requestObject.insert(CHAT_ID, chatId);
requestObject.insert(MESSAGE_ID, messageId);
if (versionNumber > VERSION_NUMBER(1,8,5)) {
// "reaction_type": {
// "@type": "reactionTypeEmoji",
// "emoji": "..."
// }
QVariantMap reactionType;
reactionType.insert(_TYPE, REACTION_TYPE_EMOJI);
reactionType.insert(EMOJI, reaction);
requestObject.insert(REACTION_TYPE, reactionType);
requestObject.insert(_TYPE, "removeMessageReaction");
LOG("Remove message reaction" << chatId << messageId << reaction);
} else {
requestObject.insert("reaction", reaction);
requestObject.insert(_TYPE, "setMessageReaction");
LOG("Toggle message reaction" << chatId << messageId << reaction);
} }
this->sendRequest(requestObject); this->sendRequest(requestObject);
} }
@ -1606,12 +1633,15 @@ QVariantMap TDLibWrapper::getChat(const QString &chatId)
QStringList TDLibWrapper::getChatReactions(const QString &chatId) QStringList TDLibWrapper::getChatReactions(const QString &chatId)
{ {
LOG("Obtaining chat reactions for chat" << chatId);
const QVariant available_reactions(chats.value(chatId).toMap().value(CHAT_AVAILABLE_REACTIONS)); const QVariant available_reactions(chats.value(chatId).toMap().value(CHAT_AVAILABLE_REACTIONS));
const QVariantMap map(available_reactions.toMap()); const QVariantMap map(available_reactions.toMap());
const QString reactions_type(map.value(_TYPE).toString()); const QString reactions_type(map.value(_TYPE).toString());
if (reactions_type == CHAT_AVAILABLE_REACTIONS_ALL) { if (reactions_type == CHAT_AVAILABLE_REACTIONS_ALL) {
LOG("Chat uses all available reactions, currently available number" << activeEmojiReactions.size());
return activeEmojiReactions; return activeEmojiReactions;
} else if (reactions_type == CHAT_AVAILABLE_REACTIONS_SOME) { } else if (reactions_type == CHAT_AVAILABLE_REACTIONS_SOME) {
LOG("Chat uses reduced set of reactions");
const QVariantList reactions(map.value(REACTIONS).toList()); const QVariantList reactions(map.value(REACTIONS).toList());
const int n = reactions.count(); const int n = reactions.count();
QStringList emojis; QStringList emojis;
@ -1633,10 +1663,13 @@ QStringList TDLibWrapper::getChatReactions(const QString &chatId)
} }
} }
} }
LOG("Found emojis for this chat" << emojis.size());
return emojis; return emojis;
} else if (reactions_type.isEmpty()) { } else if (reactions_type.isEmpty()) {
LOG("No chat reaction type specified, using all reactions");
return available_reactions.toStringList(); return available_reactions.toStringList();
} else { } else {
LOG("Unknown chat reaction type" << reactions_type);
return QStringList(); return QStringList();
} }
} }
@ -1906,6 +1939,17 @@ void TDLibWrapper::handleUnreadChatCountUpdated(const QVariantMap &chatCountInfo
} }
} }
void TDLibWrapper::handleAvailableReactionsUpdated(qlonglong chatId, const QVariantMap &availableReactions)
{
LOG("Updating available reactions for chat" << chatId << availableReactions);
QString chatIdString = QString::number(chatId);
QVariantMap chatInformation = this->getChat(chatIdString);
chatInformation.insert(CHAT_AVAILABLE_REACTIONS, availableReactions);
this->chats.insert(chatIdString, chatInformation);
emit chatAvailableReactionsUpdated(chatId, availableReactions);
}
void TDLibWrapper::handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation) void TDLibWrapper::handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation)
{ {
emit basicGroupUpdated(updateGroup(groupId, groupInformation, &basicGroups)->groupId); emit basicGroupUpdated(updateGroup(groupId, groupInformation, &basicGroups)->groupId);
@ -2068,6 +2112,7 @@ void TDLibWrapper::handleActiveEmojiReactionsUpdated(const QStringList& emojis)
if (activeEmojiReactions != emojis) { if (activeEmojiReactions != emojis) {
activeEmojiReactions = emojis; activeEmojiReactions = emojis;
LOG(emojis.count() << "reaction(s) available"); LOG(emojis.count() << "reaction(s) available");
emit reactionsUpdated();
} }
} }

View file

@ -249,7 +249,8 @@ public:
Q_INVOKABLE void terminateSession(const QString &sessionId); Q_INVOKABLE void terminateSession(const QString &sessionId);
Q_INVOKABLE void getMessageAvailableReactions(qlonglong chatId, qlonglong messageId); Q_INVOKABLE void getMessageAvailableReactions(qlonglong chatId, qlonglong messageId);
Q_INVOKABLE void getPageSource(const QString &address); Q_INVOKABLE void getPageSource(const QString &address);
Q_INVOKABLE void setMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction); Q_INVOKABLE void addMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction);
Q_INVOKABLE void removeMessageReaction(qlonglong chatId, qlonglong messageId, const QString &reaction);
Q_INVOKABLE void setNetworkType(NetworkType networkType); Q_INVOKABLE void setNetworkType(NetworkType networkType);
Q_INVOKABLE void setInactiveSessionTtl(int days); Q_INVOKABLE void setInactiveSessionTtl(int days);
@ -279,6 +280,7 @@ signals:
void chatPinnedUpdated(qlonglong chatId, bool isPinned); void chatPinnedUpdated(qlonglong chatId, bool isPinned);
void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, int unreadCount); void chatReadInboxUpdated(const QString &chatId, const QString &lastReadInboxMessageId, int unreadCount);
void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId); void chatReadOutboxUpdated(const QString &chatId, const QString &lastReadOutboxMessageId);
void chatAvailableReactionsUpdated(const qlonglong &chatId, const QVariantMap &availableReactions);
void userUpdated(const QString &userId, const QVariantMap &userInformation); void userUpdated(const QString &userId, const QVariantMap &userInformation);
void ownUserUpdated(const QVariantMap &userInformation); void ownUserUpdated(const QVariantMap &userInformation);
void basicGroupUpdated(qlonglong groupId); void basicGroupUpdated(qlonglong groupId);
@ -322,6 +324,7 @@ signals:
void chatTitleUpdated(const QString &chatId, const QString &title); void chatTitleUpdated(const QString &chatId, const QString &title);
void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId); void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId);
void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers);
void messageSendersReceived(const QString &extra, const QVariantList &senders, int totalUsers);
void errorReceived(int code, const QString &message, const QString &extra); void errorReceived(int code, const QString &message, const QString &extra);
void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); void contactsImported(const QVariantList &importerCount, const QVariantList &userIds);
void messageNotFound(qlonglong chatId, qlonglong messageId); void messageNotFound(qlonglong chatId, qlonglong messageId);
@ -338,6 +341,7 @@ signals:
void chatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount); void chatUnreadMentionCountUpdated(qlonglong chatId, int unreadMentionCount);
void chatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount); void chatUnreadReactionCountUpdated(qlonglong chatId, int unreadReactionCount);
void tgUrlFound(const QString &tgUrl); void tgUrlFound(const QString &tgUrl);
void reactionsUpdated();
public slots: public slots:
void handleVersionDetected(const QString &version); void handleVersionDetected(const QString &version);
@ -351,6 +355,7 @@ public slots:
void handleChatReceived(const QVariantMap &chatInformation); void handleChatReceived(const QVariantMap &chatInformation);
void handleUnreadMessageCountUpdated(const QVariantMap &messageCountInformation); void handleUnreadMessageCountUpdated(const QVariantMap &messageCountInformation);
void handleUnreadChatCountUpdated(const QVariantMap &chatCountInformation); void handleUnreadChatCountUpdated(const QVariantMap &chatCountInformation);
void handleAvailableReactionsUpdated(qlonglong chatId, const QVariantMap &availableReactions);
void handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void handleBasicGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void handleSuperGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation); void handleSuperGroupUpdated(qlonglong groupId, const QVariantMap &groupInformation);
void handleStickerSets(const QVariantList &stickerSets); void handleStickerSets(const QVariantList &stickerSets);

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Gelöschtes Konto</translation> <translation>Gelöschtes Konto</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation>Drücke zweimal auf eine Nachricht, um eine Reaktion auszuwählen</translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1602,6 +1606,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation>Inhalte in Hinweisen verbergen</translation> <translation>Inhalte in Hinweisen verbergen</translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation>Zu zitierter Nachricht springen</translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation>Beim Tippen auf eine zitierte Nachricht zu dieser springen anstatt es in einem Overlay anzuzeigen.</translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Deleted User</translation> <translation>Deleted User</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1604,6 +1608,14 @@ messages</numerusform>
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

File diff suppressed because it is too large Load diff

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1603,6 +1607,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS> <!DOCTYPE TS>
<TS version="2.1" language="en"> <TS version="2.1" language="fr">
<context> <context>
<name>AboutPage</name> <name>AboutPage</name>
<message> <message>
@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Supprimer l&apos;utilisateur</translation> <translation>Supprimer l&apos;utilisateur</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation>Toucher deux fois sur un message pour réagir</translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1166,7 +1170,7 @@
</message> </message>
<message> <message>
<source>No contacts found.</source> <source>No contacts found.</source>
<translation type="unfinished"></translation> <translation>Aucun contact trouvé</translation>
</message> </message>
</context> </context>
<context> <context>
@ -1584,22 +1588,30 @@
</message> </message>
<message> <message>
<source>Always append message preview to notifications</source> <source>Always append message preview to notifications</source>
<translation type="unfinished"></translation> <translation>Toujours visualiser le message dans les notifications</translation>
</message> </message>
<message> <message>
<source>In addition to showing the number of unread messages, the latest message will also be appended to notifications.</source> <source>In addition to showing the number of unread messages, the latest message will also be appended to notifications.</source>
<translation type="unfinished"></translation> <translation>En plus d&apos;afficher le nombre de messages non-lus, le dernier message sera également ajouté aux notifications.</translation>
</message> </message>
<message> <message>
<source>Highlight unread messages</source> <source>Highlight unread messages</source>
<translation type="unfinished"></translation> <translation>Mettre en valeur les messages non-lus</translation>
</message> </message>
<message> <message>
<source>Highlight Conversations with unread messages</source> <source>Highlight Conversations with unread messages</source>
<translation type="unfinished"></translation> <translation>Mettre en valeur les conversations avec des messages non-lus</translation>
</message> </message>
<message> <message>
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation>Masquer le contenu dans les notifications</translation>
</message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
@ -1713,38 +1725,38 @@
</message> </message>
<message numerus="yes"> <message numerus="yes">
<source>%1 day(s)</source> <source>%1 day(s)</source>
<translation type="unfinished"> <translation>
<numerusform></numerusform> <numerusform>%1 jour(s)</numerusform>
<numerusform></numerusform> <numerusform></numerusform>
</translation> </translation>
</message> </message>
<message> <message>
<source>1 week</source> <source>1 week</source>
<translation type="unfinished"></translation> <translation>1 semaine</translation>
</message> </message>
<message> <message>
<source>1 month</source> <source>1 month</source>
<translation type="unfinished"></translation> <translation>1 mois</translation>
</message> </message>
<message> <message>
<source>3 months</source> <source>3 months</source>
<translation type="unfinished"></translation> <translation>3 mois</translation>
</message> </message>
<message> <message>
<source>6 months</source> <source>6 months</source>
<translation type="unfinished"></translation> <translation>6 mois</translation>
</message> </message>
<message> <message>
<source>1 year</source> <source>1 year</source>
<translation type="unfinished"></translation> <translation>1 année</translation>
</message> </message>
<message> <message>
<source>Session Timeout</source> <source>Session Timeout</source>
<translation type="unfinished"></translation> <translation>Délai d&apos;inactivité de session</translation>
</message> </message>
<message> <message>
<source>Inactive sessions will be terminated after this timeframe</source> <source>Inactive sessions will be terminated after this timeframe</source>
<translation type="unfinished"></translation> <translation>Sessions inactives seront terminées après ce délai</translation>
</message> </message>
</context> </context>
<context> <context>

View file

@ -473,6 +473,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1575,6 +1579,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1602,6 +1606,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -493,6 +493,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Usunięty użytkownik</translation> <translation>Usunięty użytkownik</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1629,6 +1633,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -348,11 +348,11 @@
</message> </message>
<message> <message>
<source>Leave Chat</source> <source>Leave Chat</source>
<translation>Выйти из Чата</translation> <translation>Выйти из чата</translation>
</message> </message>
<message> <message>
<source>Join Chat</source> <source>Join Chat</source>
<translation>Зайти в Чат</translation> <translation>Зайти в чат</translation>
</message> </message>
<message> <message>
<source>Leaving chat</source> <source>Leaving chat</source>
@ -427,7 +427,7 @@
</message> </message>
<message> <message>
<source>Search in Chat</source> <source>Search in Chat</source>
<translation>Найти в Чате</translation> <translation>Поиск в чате</translation>
</message> </message>
<message> <message>
<source>Search in chat...</source> <source>Search in chat...</source>
@ -493,6 +493,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Удалённый пользователь</translation> <translation>Удалённый пользователь</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1159,7 +1163,7 @@
</message> </message>
<message> <message>
<source>Secret Chat</source> <source>Secret Chat</source>
<translation>Секретный Чат</translation> <translation>Секретный чат</translation>
</message> </message>
<message> <message>
<source>End-to-end-encrypted, accessible on this device only</source> <source>End-to-end-encrypted, accessible on this device only</source>
@ -1241,7 +1245,7 @@
</message> </message>
<message> <message>
<source>New Chat</source> <source>New Chat</source>
<translation>Новый Чат</translation> <translation>Новый чат</translation>
</message> </message>
<message> <message>
<source>Filter your chats...</source> <source>Filter your chats...</source>
@ -1249,7 +1253,7 @@
</message> </message>
<message> <message>
<source>Search Chats</source> <source>Search Chats</source>
<translation>Найти Чаты</translation> <translation>Поиск чатов</translation>
</message> </message>
<message> <message>
<source>Download of %1 successful.</source> <source>Download of %1 successful.</source>
@ -1460,7 +1464,7 @@
<name>SearchChatsPage</name> <name>SearchChatsPage</name>
<message> <message>
<source>No chats found.</source> <source>No chats found.</source>
<translation>Чаты не найдены</translation> <translation>Ничего не найдено</translation>
</message> </message>
<message> <message>
<source>Searching chats...</source> <source>Searching chats...</source>
@ -1468,7 +1472,7 @@
</message> </message>
<message> <message>
<source>Private Chat</source> <source>Private Chat</source>
<translation>Приватный Чат</translation> <translation>Приватный чат</translation>
</message> </message>
<message> <message>
<source>Group</source> <source>Group</source>
@ -1496,7 +1500,7 @@
</message> </message>
<message> <message>
<source>Search Chats</source> <source>Search Chats</source>
<translation>Найти Чаты</translation> <translation>Поиск чатов</translation>
</message> </message>
<message> <message>
<source>Search a chat...</source> <source>Search a chat...</source>
@ -1614,23 +1618,31 @@
</message> </message>
<message> <message>
<source>Always append message preview to notifications</source> <source>Always append message preview to notifications</source>
<translation type="unfinished"></translation> <translation>Всегда показывать последнее сообщение на экране событий</translation>
</message> </message>
<message> <message>
<source>In addition to showing the number of unread messages, the latest message will also be appended to notifications.</source> <source>In addition to showing the number of unread messages, the latest message will also be appended to notifications.</source>
<translation type="unfinished"></translation> <translation>Включать в текст на экране событий не только количество непрочитанных сообщений, но и содержимое последнего сообщения.</translation>
</message> </message>
<message> <message>
<source>Highlight unread messages</source> <source>Highlight unread messages</source>
<translation type="unfinished"></translation> <translation>Выделять непрочитанные сообщения</translation>
</message> </message>
<message> <message>
<source>Highlight Conversations with unread messages</source> <source>Highlight Conversations with unread messages</source>
<translation type="unfinished"></translation> <translation>Помечать чаты и каналы с непрочитанными сообщениями другим шрифтом и цветом.</translation>
</message> </message>
<message> <message>
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation>Не показывать содержимое сообщений в уведомлениях</translation>
</message>
<message>
<source>Go to quoted message</source>
<translation>Переходить к цитируемому сообщению</translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation>По нажатию на цитируемое сообщение, переходить к нему в чате вместо отображения во всплывающем окне.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -1743,39 +1755,39 @@
</message> </message>
<message numerus="yes"> <message numerus="yes">
<source>%1 day(s)</source> <source>%1 day(s)</source>
<translation type="unfinished"> <translation>
<numerusform></numerusform> <numerusform>%1 день</numerusform>
<numerusform></numerusform> <numerusform>%1 дня</numerusform>
<numerusform></numerusform> <numerusform>%1 дней</numerusform>
</translation> </translation>
</message> </message>
<message> <message>
<source>1 week</source> <source>1 week</source>
<translation type="unfinished"></translation> <translation>1 неделя</translation>
</message> </message>
<message> <message>
<source>1 month</source> <source>1 month</source>
<translation type="unfinished"></translation> <translation>1 месяц</translation>
</message> </message>
<message> <message>
<source>3 months</source> <source>3 months</source>
<translation type="unfinished"></translation> <translation>3 месяца</translation>
</message> </message>
<message> <message>
<source>6 months</source> <source>6 months</source>
<translation type="unfinished"></translation> <translation>6 месяцев</translation>
</message> </message>
<message> <message>
<source>1 year</source> <source>1 year</source>
<translation type="unfinished"></translation> <translation>1 год</translation>
</message> </message>
<message> <message>
<source>Session Timeout</source> <source>Session Timeout</source>
<translation type="unfinished"></translation> <translation>Таймаут неактивности</translation>
</message> </message>
<message> <message>
<source>Inactive sessions will be terminated after this timeframe</source> <source>Inactive sessions will be terminated after this timeframe</source>
<translation type="unfinished"></translation> <translation>Неактивные сеансы будут автоматически завершены через указанное время.</translation>
</message> </message>
</context> </context>
<context> <context>

View file

@ -493,6 +493,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Odstránený používateľ</translation> <translation>Odstránený používateľ</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1629,6 +1633,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation>Tog bort användare</translation> <translation>Tog bort användare</translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1602,6 +1606,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -473,6 +473,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1576,6 +1580,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>

View file

@ -483,6 +483,10 @@
<source>Deleted User</source> <source>Deleted User</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Double-tap on a message to choose a reaction</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ChatSelectionPage</name> <name>ChatSelectionPage</name>
@ -1602,6 +1606,14 @@
<source>Hide content in notifications</source> <source>Hide content in notifications</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Go to quoted message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>When tapping a quoted message, open it in chat instead of showing it in an overlay.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SettingsPage</name> <name>SettingsPage</name>