diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 2961f7c..da474a4 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -64,6 +64,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/js/functions.js \ qml/pages/ChatInformationPage.qml \ qml/pages/ChatPage.qml \ + qml/pages/ChatSelectionPage.qml \ qml/pages/CoverPage.qml \ qml/pages/InitializationPage.qml \ qml/pages/OverviewPage.qml \ diff --git a/images/icon-m-copy.svg b/images/icon-m-copy.svg new file mode 100644 index 0000000..ae927d1 --- /dev/null +++ b/images/icon-m-copy.svg @@ -0,0 +1,41 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml index 0e4abcc..b584d00 100644 --- a/qml/components/ChatListViewItem.qml +++ b/qml/components/ChatListViewItem.qml @@ -7,7 +7,7 @@ import "../js/functions.js" as Functions PhotoTextsListItem { id: listItem pictureThumbnail { - photoData: photo_small + photoData: photo_small || ({}) } property int ownUserId property url emojiBase: "../js/emoji/" diff --git a/qml/components/MessageListViewItem.qml b/qml/components/MessageListViewItem.qml index 5acd458..65393b8 100644 --- a/qml/components/MessageListViewItem.qml +++ b/qml/components/MessageListViewItem.qml @@ -31,16 +31,31 @@ ListItem { readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme.primaryColor readonly property int textAlign: isOwnMessage ? Text.AlignRight : Text.AlignLeft readonly property Page page: precalculatedValues.page - + readonly property bool isSelected: messageListItem.precalculatedValues.pageIsSelecting && page.selectedMessages.some(function(existingMessage) { + return existingMessage.id === myMessage.id; + }); readonly property bool isOwnMessage: page.myUserId === myMessage.sender_user_id readonly property string extraContentComponentName: typeof myMessage.content !== "undefined" && typeof chatView.contentComponentNames[myMessage.content['@type']] !== "undefined" ? chatView.contentComponentNames[myMessage.content['@type']] : "" readonly property ObjectModel additionalContextItems: ObjectModel {} + highlighted: down || isSelected + openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting + + onClicked: { + if(messageListItem.precalculatedValues.pageIsSelecting) { + page.toggleMessageSelection(myMessage); + } + } onPressAndHold: { - contextMenuLoader.active = true; + if(messageListItem.precalculatedValues.pageIsSelecting) { + page.selectedMessages = []; + page.state = "" + } else { + contextMenuLoader.active = true; + } } Loader { id: contextMenuLoader @@ -80,6 +95,12 @@ ListItem { } text: qsTr("Copy Message to Clipboard") } + MenuItem { + onClicked: { + page.toggleMessageSelection(myMessage); + } + text: qsTr("Select Message") + } MenuItem { onClicked: { var chatId = page.chatInformation.id; @@ -171,13 +192,14 @@ ListItem { sourceComponent: Component { ProfileThumbnail { id: messagePictureThumbnail - photoData: (typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : "" + photoData: (typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : ({}) replacementStringHint: userText.text width: Theme.itemSizeSmall height: Theme.itemSizeSmall visible: precalculatedValues.showUserInfo MouseArea { anchors.fill: parent + enabled: !messageListItem.precalculatedValues.pageIsSelecting onClicked: { tdLibWrapper.createPrivateChat(messageListItem.userInformation.id); } @@ -234,6 +256,7 @@ ListItem { visible: precalculatedValues.showUserInfo MouseArea { anchors.fill: parent + enabled: !messageListItem.precalculatedValues.pageIsSelecting onClicked: { tdLibWrapper.createPrivateChat(messageListItem.userInformation.id); } @@ -272,11 +295,11 @@ ListItem { Component.onCompleted: { if (myMessage.forward_info.origin["@type"] === "messageForwardOriginChannel") { var otherChatInformation = tdLibWrapper.getChat(myMessage.forward_info.origin.chat_id); - forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : ""; + forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : {}; forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall); } else if (myMessage.forward_info.origin["@type"] === "messageForwardOriginUser") { var otherUserInformation = tdLibWrapper.getUserInformation(myMessage.forward_info.origin.sender_user_id); - forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : ""; + forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : {}; forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall); } else { forwardedChannelText.text = Emoji.emojify(myMessage.forward_info.origin.sender_name, Theme.fontSizeExtraSmall); @@ -405,6 +428,7 @@ ListItem { text: getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed) MouseArea { anchors.fill: parent + enabled: !messageListItem.precalculatedValues.pageIsSelecting onClicked: { messageDateText.useElapsed = !messageDateText.useElapsed; messageDateText.text = getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed); diff --git a/qml/js/functions.js b/qml/js/functions.js index 5a71999..0576433 100644 --- a/qml/js/functions.js +++ b/qml/js/functions.js @@ -367,3 +367,30 @@ function getVideoHeight(videoWidth, videoData) { function replaceUrlsWithLinks(string) { return string.replace(/((\w+):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, "$1"); } + +function sortMessagesArrayByDate(messages) { + messages.sort(function(a, b) { + return a.date - b.date; + }); +} + +function getMessagesArrayIds(messages) { + sortMessagesArrayByDate(messages); + return messages.map(function(message){return message.id.toString()}); +} + +function getMessagesArrayText(messages) { + sortMessagesArrayByDate(messages); + var lastSenderName = ""; + var lines = []; + for(var i = 0; i < messages.length; i += 1) { + var senderName = getUserName(tdLibWrapper.getUserInformation(messages[i].sender_user_id)); + if(senderName !== lastSenderName) { + lines.push(senderName); + } + lastSenderName = senderName; + lines.push(getMessageText(messages[i], true, false)); + lines.push(""); + } + return lines.join("\n"); +} diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 1ed395e..f773afc 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -49,6 +49,55 @@ Page { || (chatGroupInformation.status["@type"] === "chatMemberStatusRestricted" && chatGroupInformation.status.is_member) || (chatGroupInformation.status["@type"] === "chatMemberStatusCreator" && chatGroupInformation.status.is_member) ) + property var selectedMessages: [] + states: [ + State { + name: "selectMessages" + when: selectedMessages.length > 0 + PropertyChanges { + target: newMessageColumn + visible: false + opacity: 0 + } + PropertyChanges { + target: chatNameText + text: qsTr("Select Messages") + } + PropertyChanges { + target: chatStatusText + text: qsTr("%n messages selected", "number of messages selected", chatPage.selectedMessages.length).arg(chatPage.selectedMessages.length) + } + PropertyChanges { + target: selectedMessagesActions + height: Theme.itemSizeMedium + active: true + opacity: 1.0//selectedMessages.length > 0 ? 1.0 : 0.5 + } + PropertyChanges { + target: newMessageTextField + focus: false + } + } + + ] + function toggleMessageSelection(message) { + var selectionArray = selectedMessages; + var foundIndex = -1 + if(selectionArray.length > 0) { + for(var i = 0; i < selectionArray.length; i += 1) { + if(selectionArray[i].id === message.id) { + foundIndex = i; + continue; + } + } + } + if(foundIndex > -1) { + selectionArray.splice(foundIndex, 1); + } else { + selectionArray.push(message); + } + selectedMessages = selectionArray; + } function updateChatPartnerStatusText() { var statusText = Functions.getChatPartnerStatusText(chatPartnerInformation.status['@type'], chatPartnerInformation.status.was_online); @@ -211,6 +260,26 @@ Page { newMessageTextField.cursorPosition = newIndex; lostFocusTimer.start(); } + function forwardMessages(fromChatId, messageIds) { + forwardMessagesTimer.fromChatId = fromChatId; + forwardMessagesTimer.messageIds = messageIds; + forwardMessagesTimer.start(); + } + Timer { + id: forwardMessagesTimer + interval: 200 + + property string fromChatId + property var messageIds + onTriggered: { + if(chatPage.loading) { + forwardMessagesTimer.start() + } else { + var forwardedToSecretChat = chatInformation.type["@type"] === "chatTypeSecret"; + tdLibWrapper.forwardMessages(chatInformation.id, fromChatId, messageIds, forwardedToSecretChat, false); + } + } + } Component.onCompleted: { initializePage(); @@ -430,19 +499,22 @@ Page { height: headerRow.height width: parent.width onClicked: { - pageStack.push(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); + if(chatPage.state === "selectMessages") { + chatPage.selectedMessages = []; + } else { + pageStack.push(Qt.resolvedUrl("../pages/ChatInformationPage.qml"), { "chatInformation" : chatInformation, "privateChatUserInformation": chatPartnerInformation, "groupInformation": chatGroupInformation, "chatOnlineMemberCount": chatOnlineMemberCount}); + } } } Column { id: chatColumn width: parent.width height: parent.height - spacing: Theme.paddingSmall Row { id: headerRow width: parent.width - (3 * Theme.horizontalPageMargin) - height: chatOverviewColumn.height + Theme.paddingLarge + height: chatOverviewColumn.height + Theme.paddingLarge + Theme.paddingSmall anchors.horizontalCenter: parent.horizontalCenter spacing: Theme.paddingMedium @@ -491,7 +563,7 @@ Page { Item { id: chatViewItem width: parent.width - height: parent.height - headerRow.height - Theme.paddingSmall - ( chatPage.isChannel ? 0 : ( newMessageColumn.height + Theme.paddingSmall ) ) + height: parent.height - headerRow.height - newMessageColumn.height - selectedMessagesActions.height property int previousHeight; @@ -522,7 +594,7 @@ Page { anchors.fill: parent opacity: chatPage.loading ? 0 : 1 - Behavior on opacity { NumberAnimation {} } + Behavior on opacity { FadeAnimation {} } clip: true highlightMoveDuration: 0 highlightResizeDuration: 0 @@ -542,6 +614,8 @@ Page { readonly property int textColumnWidth: backgroundWidth - Theme.horizontalPageMargin readonly property int messageInReplyToHeight: Theme.fontSizeExtraSmall * 2.571428571 + Theme.paddingSmall; readonly property int webPagePreviewHeight: ( (textColumnWidth * 2 / 3) + (6 * Theme.fontSizeExtraSmall) + ( 7 * Theme.paddingSmall) ) + readonly property bool pageIsSelecting: chatPage.state === "selectMessages" + } function handleScrollPositionChanged() { @@ -725,10 +799,12 @@ Page { Column { id: newMessageColumn spacing: Theme.paddingSmall - + topPadding: Theme.paddingSmall width: parent.width - ( 2 * Theme.horizontalPageMargin ) anchors.horizontalCenter: parent.horizontalCenter visible: !chatPage.isChannel + height: visible ? implicitHeight : 0 + Behavior on opacity { FadeAnimation {} } property string replyToMessageId: "0"; property string editMessageId: "0"; @@ -1050,6 +1126,103 @@ Page { } } } + Loader { + id: selectedMessagesActions + asynchronous: true + active: false + height: 0 + opacity: 0 + width: parent.width - Theme.horizontalPageMargin + Behavior on opacity { FadeAnimation {} } + sourceComponent: Component { + Item { + clip: true + + IconButton { + id: cancelSelectionButton + anchors { + left: parent.left + leftMargin: Theme.horizontalPageMargin + verticalCenter: parent.verticalCenter + } + icon.source: "image://theme/icon-m-cancel" + onClicked: { + chatPage.selectedMessages = []; + } + } + + IconButton { + id: messagesCopyButton + anchors { + right: messagesForwardButton.left + leftMargin: Theme.paddingSmall + verticalCenter: parent.verticalCenter + } + icon.source: "../../images/icon-m-copy.svg" + icon.sourceSize { + width: Theme.iconSizeMedium + height: Theme.iconSizeMedium + } + onClicked: { + Clipboard.text = Functions.getMessagesArrayText(chatPage.selectedMessages); + appNotification.show(qsTr("%n messages have been copied", "", selectedMessages.length).arg(selectedMessages.length)); + chatPage.selectedMessages = []; + } + } + + IconButton { + id: messagesForwardButton + + anchors { + right: messagesDeleteButton.left + leftMargin: visible ? Theme.paddingSmall : 0 + verticalCenter: parent.verticalCenter + } + visible: chatPage.chatInformation.can_be_forwarded && selectedMessages.every(function(message){ + return message.can_be_forwarded + }) + width: visible ? Theme.itemSizeMedium : 0 + icon.source: "image://theme/icon-m-forward" + onClicked: { + var ids = Functions.getMessagesArrayIds(chatPage.selectedMessages); + + var chatId = chatInformation.id; + + pageStack.push(Qt.resolvedUrl("../pages/ChatSelectionPage.qml"), { + headerDescription: qsTr("Forward %n messages", "dialog header", ids.length).arg(ids.length), + payload: {fromChatId: chatId, messageIds:ids}, + state: "forwardMessages" + }); + } + + } + IconButton { + id: messagesDeleteButton + anchors { + right: parent.right + leftMargin: visible ? Theme.paddingSmall : 0 + verticalCenter: parent.verticalCenter + } + + icon.source: "image://theme/icon-m-delete" + visible: chatInformation.id === chatPage.myUserId || selectedMessages.every(function(message){ + return message.can_be_deleted_for_all_users + }) + width: visible ? Theme.itemSizeMedium : 0 + onClicked: { + var ids = Functions.getMessagesArrayIds(selectedMessages); + var chatId = chatInformation.id + var wrapper = tdLibWrapper; + Remorse.popupAction(chatPage, qsTr("%n Messages deleted", "", ids.length).arg(ids.length), function() { + wrapper.deleteMessages(chatId, ids); + }); + chatPage.selectedMessages = []; + } + } + } + } + } + } } diff --git a/qml/pages/ChatSelectionPage.qml b/qml/pages/ChatSelectionPage.qml new file mode 100644 index 0000000..4dec379 --- /dev/null +++ b/qml/pages/ChatSelectionPage.qml @@ -0,0 +1,88 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../components" + +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions + +Dialog { + id: chatSelectionPage + allowedOrientations: Orientation.All + canAccept: false + acceptDestinationAction: PageStackAction.Replace + acceptDestinationReplaceTarget: pageStack.find( function(page){ return(page._depth === 0)} ) + property alias headerTitle: pageHeader.title + property alias headerDescription: pageHeader.description + property var payload: ({}) + + onAccepted: { + switch(chatSelectionPage.state) { + case "forwardMessages": + acceptDestinationInstance.forwardMessages(payload.fromChatId, payload.messageIds) + break; + } + } + + PageHeader { + id: pageHeader + title: qsTr("Select Chat") + width: parent.width + } + + SilicaListView { + id: chatListView + + anchors { + top: pageHeader.bottom + bottom: parent.bottom + left: parent.left + right: parent.right + } + + clip: true + + model: chatListModel + delegate: ChatListViewItem { + ownUserId: overviewPage.ownUserId + + onClicked: { + var chat = tdLibWrapper.getChat(display.id); + switch(chatSelectionPage.state) { + case "forwardMessages": + chatSelectionPage.acceptDestinationProperties = { "chatInformation" : chat}; + chatSelectionPage.acceptDestination = Qt.resolvedUrl("../pages/ChatPage.qml"); + break; + } + chatSelectionPage.canAccept = true; + chatSelectionPage.accept(); + } + } + + ViewPlaceholder { + enabled: chatListView.count === 0 + text: qsTr("You don't have any chats yet.") + } + + VerticalScrollDecorator {} + } + + +} diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index a7ed828..28a18d9 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -433,6 +433,20 @@ void TDLibWrapper::sendPollMessage(const QString &chatId, const QString &questio this->sendRequest(requestObject); } +void TDLibWrapper::forwardMessages(const QString &chatId, const QString &fromChatId, const QVariantList &messageIds, const bool sendCopy, const bool removeCaption) +{ + LOG("Forwarding messages" << chatId << fromChatId << messageIds); + QVariantMap requestObject; + requestObject.insert(_TYPE, "forwardMessages"); + requestObject.insert("chat_id", chatId); + requestObject.insert("from_chat_id", fromChatId); + requestObject.insert("message_ids", messageIds); + requestObject.insert("send_copy", sendCopy); + requestObject.insert("remove_caption", removeCaption); + + this->sendRequest(requestObject); +} + void TDLibWrapper::getMessage(const QString &chatId, const QString &messageId) { LOG("Retrieving message" << chatId << messageId); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index a03e837..ce63261 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -128,6 +128,7 @@ public: Q_INVOKABLE void sendDocumentMessage(const QString &chatId, const QString &filePath, const QString &message, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendStickerMessage(const QString &chatId, const QString &fileId, const QString &replyToMessageId = "0"); Q_INVOKABLE void sendPollMessage(const QString &chatId, const QString &question, const QVariantList &options, const bool &anonymous, const int &correctOption, const bool &multiple, const QString &replyToMessageId = "0"); + Q_INVOKABLE void forwardMessages(const QString &chatId, const QString &fromChatId, const QVariantList &messageIds, const bool sendCopy, const bool removeCaption); Q_INVOKABLE void getMessage(const QString &chatId, const QString &messageId); Q_INVOKABLE void setOptionInteger(const QString &optionName, int optionValue); Q_INVOKABLE void setChatNotificationSettings(const QString &chatId, const QVariantMap ¬ificationSettings); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 464503a..e171b9d 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -313,6 +313,51 @@ You joined the chat %1 Sie sind dem Chat %1 beigetreten. + + Select Messages + Nachrichtenauswahl + + + %n Messages deleted + + %n Nachrichten gelöscht + + + + + %n messages have been copied + + %n Nachrichten wurden kopiert + + + + + %n messages selected + number of messages selected + + %n Nachricht ausgewählt + %n Nachrichten ausgewählt + + + + Forward %n messages + dialog header + + %n Nachricht weiterleiten + %n Nachrichten weiterleiten + + + + + ChatSelectionPage + + Select Chat + Chat auswählen + + + You don't have any chats yet. + Sie haben noch keine Chats. + CoverPage @@ -790,6 +835,10 @@ Forwarded Message Weitergeleitete Nachricht + + Select Message + Nachricht auswählen + MessageListViewItemSimple @@ -1052,7 +1101,7 @@ Show background for stickers and align them centrally like images - Hintergrund für Sticker anzeigen und sie wie Bilder mittig platzieren. + Hintergrund für Sticker anzeigen und sie wie Bilder mittig platzieren Notification feedback diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 31f588a..8e2c148 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -313,6 +313,47 @@ You joined the chat %1 Te uniste a charla + + Select Messages + + + + %n Messages deleted + + + + + + %n messages have been copied + + + + + + %n messages selected + number of messages selected + + + + + + Forward %n messages + dialog header + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + No hay todavía ninguna charla. + CoverPage @@ -790,6 +831,10 @@ Forwarded Message Mensaje reenviado + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 8b22cc1..242b0cf 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -313,6 +313,51 @@ You joined the chat %1 Liityit keskusteluun %1 + + Select Messages + + + + %n Messages deleted + + + + + + + %n messages have been copied + + + + + + + %n messages selected + number of messages selected + + + + + + + Forward %n messages + dialog header + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + Sinulla ei ole vielä keskusteluja. + CoverPage @@ -791,6 +836,10 @@ Forwarded Message Välitetty viesti + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 2f53bd1..c21807c 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -313,6 +313,47 @@ You joined the chat %1 + + Select Messages + + + + %n Messages deleted + + + + + + %n messages have been copied + + + + + + %n messages selected + number of messages selected + + + + + + Forward %n messages + dialog header + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + + CoverPage @@ -790,6 +831,10 @@ Forwarded Message + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 3438ce5..8253169 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -313,6 +313,51 @@ You joined the chat %1 Sei entrato nella chat %1 + + Select Messages + + + + %n Messages deleted + + + + + + + %n messages have been copied + + + + + + + %n messages selected + number of messages selected + + + + + + + Forward %n messages + dialog header + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + Non hai nessuna chat. + CoverPage @@ -790,6 +835,10 @@ Forwarded Message Messaggio inoltrato + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index a455839..d5f4697 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -313,6 +313,55 @@ You joined the chat %1 + + Select Messages + + + + %n Messages deleted + + + + + + + + %n messages have been copied + + + + + + + + %n messages selected + number of messages selected + + + + + + + + Forward %n messages + dialog header + + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + Nie masz jeszcze żadnych czatów. + CoverPage @@ -790,6 +839,10 @@ Forwarded Message + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 1f4e1ab..9fb40ef 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -313,6 +313,55 @@ You joined the chat %1 Вы зашли в чат «%1» + + Select Messages + + + + %n Messages deleted + + + + + + + + %n messages have been copied + + + + + + + + %n messages selected + number of messages selected + + + + + + + + Forward %n messages + dialog header + + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + Тут пока ничего нет + CoverPage @@ -790,6 +839,10 @@ Forwarded Message Пересланное сообщение + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 8d1d2bc..4b704b7 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -313,6 +313,51 @@ You joined the chat %1 Du anslöt till chatten %1 + + Select Messages + + + + %n Messages deleted + + + + + + + %n messages have been copied + + + + + + + %n messages selected + number of messages selected + + + + + + + Forward %n messages + dialog header + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + Du har inga chattar än. + CoverPage @@ -790,6 +835,10 @@ Forwarded Message Vidarebefordrat meddelande + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 9885cb8..78d7364 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -313,6 +313,47 @@ You joined the chat %1 你已加入对话 %1 + + Select Messages + + + + %n Messages deleted + + + + + + %n messages have been copied + + + + + + %n messages selected + number of messages selected + + + + + + Forward %n messages + dialog header + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + 你还没有任何对话。 + CoverPage @@ -790,6 +831,10 @@ Forwarded Message 转发消息 + + Select Message + + MessageListViewItemSimple diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index fc853ed..c2f3861 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -313,6 +313,51 @@ You joined the chat %1 + + Select Messages + + + + %n Messages deleted + + + + + + + %n messages have been copied + + + + + + + %n messages selected + number of messages selected + + + + + + + Forward %n messages + dialog header + + + + + + + + ChatSelectionPage + + Select Chat + + + + You don't have any chats yet. + + CoverPage @@ -790,6 +835,10 @@ Forwarded Message + + Select Message + + MessageListViewItemSimple @@ -892,6 +941,7 @@ Question (%n1 characters left) + @@ -907,6 +957,7 @@ Answer (%n1 characters left) + @@ -955,6 +1006,7 @@ number of total votes + @@ -981,6 +1033,7 @@ number of total votes + @@ -998,6 +1051,7 @@ number of votes for option + @@ -1015,6 +1069,7 @@ number of votes for option +