Merge pull request #159 from jgibbon/feature/messageActions

multiple message selection
This commit is contained in:
Sebastian Wolf 2020-11-15 17:00:05 +01:00 committed by GitHub
commit 955ebfc853
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 874 additions and 13 deletions

View file

@ -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 \

41
images/icon-m-copy.svg Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg6"
version="1.1"
width="64"
height="64">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<rect
y="97.898308"
x="-2.4406779"
id="icon-m-tablet_1_"
style="opacity:0;fill:#ffffff"
width="64"
height="64" />
<path
id="path5-6-5"
d="m 16.145764,42.08553 h -3.315187 c -1.625,0 -2.946,-1.322 -2.946,-2.946 v -22.072 c 0,-1.625 1.321,-2.946 2.946,-2.946 h 30.073 c 1.624,0 2.946,1.321 2.946,2.946 v 2.8388 h -1.965 v -2.8388 c 0,-0.542 -0.44,-0.982 -0.981,-0.982 h -30.073 c -0.542,0 -0.982,0.44 -0.982,0.982 v 22.072 c 0,0.541 0.44,0.981 0.982,0.981 h 3.315187 z"
style="opacity:0.6;fill:#ffffff" />
<path
id="path5-5-2"
d="m 51.169423,49.87847 h -30.073 c -1.625,0 -2.946,-1.322 -2.946,-2.946 v -22.072 c 0,-1.625 1.321,-2.946 2.946,-2.946 h 30.073 c 1.624,0 2.946,1.321 2.946,2.946 v 22.072 c 0,1.624 -1.322,2.946 -2.946,2.946 z m -30.073,-26 c -0.542,0 -0.982,0.44 -0.982,0.982 v 22.072 c 0,0.541 0.44,0.981 0.982,0.981 h 30.073 c 0.541,0 0.981,-0.44 0.981,-0.981 v -22.072 c 0,-0.542 -0.44,-0.982 -0.981,-0.982 z"
style="fill:#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -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/"

View file

@ -31,17 +31,32 @@ 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: {
if(messageListItem.precalculatedValues.pageIsSelecting) {
page.selectedMessages = [];
page.state = ""
} else {
contextMenuLoader.active = true;
}
}
Loader {
id: contextMenuLoader
active: false
@ -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);

View file

@ -367,3 +367,30 @@ function getVideoHeight(videoWidth, videoData) {
function replaceUrlsWithLinks(string) {
return string.replace(/((\w+):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, "<a href=\"$1\">$1</a>");
}
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");
}

View file

@ -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: {
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 = [];
}
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 {}
}
}

View file

@ -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);

View file

@ -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 &notificationSettings);

View file

@ -313,6 +313,51 @@
<source>You joined the chat %1</source>
<translation>Sie sind dem Chat %1 beigetreten.</translation>
</message>
<message>
<source>Select Messages</source>
<translation>Nachrichtenauswahl</translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation>
<numerusform>%n Nachrichten gelöscht</numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation>
<numerusform>%n Nachrichten wurden kopiert</numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation>
<numerusform>%n Nachricht ausgewählt</numerusform>
<numerusform>%n Nachrichten ausgewählt</numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation>
<numerusform>%n Nachricht weiterleiten</numerusform>
<numerusform>%n Nachrichten weiterleiten</numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation>Chat auswählen</translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation>Sie haben noch keine Chats.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +835,10 @@
<source>Forwarded Message</source>
<translation>Weitergeleitete Nachricht</translation>
</message>
<message>
<source>Select Message</source>
<translation>Nachricht auswählen</translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>
@ -1052,7 +1101,7 @@
</message>
<message>
<source>Show background for stickers and align them centrally like images</source>
<translation>Hintergrund für Sticker anzeigen und sie wie Bilder mittig platzieren.</translation>
<translation>Hintergrund für Sticker anzeigen und sie wie Bilder mittig platzieren</translation>
</message>
<message>
<source>Notification feedback</source>

View file

@ -313,6 +313,47 @@
<source>You joined the chat %1</source>
<translation>Te uniste a charla</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">No hay todavía ninguna charla.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +831,10 @@
<source>Forwarded Message</source>
<translation>Mensaje reenviado</translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,51 @@
<source>You joined the chat %1</source>
<translation>Liityit keskusteluun %1</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">Sinulla ei ole vielä keskusteluja.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -791,6 +836,10 @@
<source>Forwarded Message</source>
<translation>Välitetty viesti</translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,47 @@
<source>You joined the chat %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +831,10 @@
<source>Forwarded Message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,51 @@
<source>You joined the chat %1</source>
<translation>Sei entrato nella chat %1</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">Non hai nessuna chat.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +835,10 @@
<source>Forwarded Message</source>
<translation>Messaggio inoltrato</translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,55 @@
<source>You joined the chat %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">Nie masz jeszcze żadnych czatów.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +839,10 @@
<source>Forwarded Message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,55 @@
<source>You joined the chat %1</source>
<translation>Вы зашли в чат «%1»</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">Тут пока ничего нет</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +839,10 @@
<source>Forwarded Message</source>
<translation>Пересланное сообщение</translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,51 @@
<source>You joined the chat %1</source>
<translation>Du anslöt till chatten %1</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished">Du har inga chattar än.</translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +835,10 @@
<source>Forwarded Message</source>
<translation>Vidarebefordrat meddelande</translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,47 @@
<source>You joined the chat %1</source>
<translation> %1</translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +831,10 @@
<source>Forwarded Message</source>
<translation></translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>

View file

@ -313,6 +313,51 @@
<source>You joined the chat %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Messages</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>%n Messages deleted</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages have been copied</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n messages selected</source>
<comment>number of messages selected</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>Forward %n messages</source>
<comment>dialog header</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ChatSelectionPage</name>
<message>
<source>Select Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>You don&apos;t have any chats yet.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CoverPage</name>
@ -790,6 +835,10 @@
<source>Forwarded Message</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select Message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MessageListViewItemSimple</name>
@ -892,6 +941,7 @@
<source>Question (%n1 characters left)</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
@ -907,6 +957,7 @@
<source>Answer (%n1 characters left)</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
@ -955,6 +1006,7 @@
<comment>number of total votes</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
@ -981,6 +1033,7 @@
<comment>number of total votes</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
@ -998,6 +1051,7 @@
<comment>number of votes for option</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
@ -1015,6 +1069,7 @@
<comment>number of votes for option</comment>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>