Improvements after feedback round
This commit is contained in:
parent
de945c7846
commit
48b5e14335
22 changed files with 161 additions and 107 deletions
|
@ -13,7 +13,7 @@ PhotoTextsListItem {
|
||||||
property int ownUserId
|
property int ownUserId
|
||||||
|
|
||||||
// chat title
|
// chat title
|
||||||
primaryText.text: title ? Emoji.emojify((listItem.isSecret ? "🔒 " : "" ) + title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown")
|
primaryText.text: title ? Emoji.emojify(title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown")
|
||||||
// last user
|
// last user
|
||||||
prologSecondaryText.text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : "" )
|
prologSecondaryText.text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : "" )
|
||||||
// last message
|
// last message
|
||||||
|
|
|
@ -11,7 +11,7 @@ ListItem {
|
||||||
property alias secondaryText: secondaryText //usually last message
|
property alias secondaryText: secondaryText //usually last message
|
||||||
property alias tertiaryText: tertiaryText //usually last message date
|
property alias tertiaryText: tertiaryText //usually last message date
|
||||||
|
|
||||||
property int unreadCount
|
property int unreadCount: 0
|
||||||
property bool isSecret: false
|
property bool isSecret: false
|
||||||
property alias pictureThumbnail: pictureThumbnail
|
property alias pictureThumbnail: pictureThumbnail
|
||||||
|
|
||||||
|
@ -58,14 +58,12 @@ ListItem {
|
||||||
color: Theme.overlayBackgroundColor
|
color: Theme.overlayBackgroundColor
|
||||||
width: Theme.fontSizeExtraLarge
|
width: Theme.fontSizeExtraLarge
|
||||||
height: Theme.fontSizeExtraLarge
|
height: Theme.fontSizeExtraLarge
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
radius: parent.width / 2
|
radius: parent.width / 2
|
||||||
visible: chatListViewItem.isSecret
|
visible: chatListViewItem.isSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: chatSecretImage
|
|
||||||
source: "image://theme/icon-s-secure"
|
source: "image://theme/icon-s-secure"
|
||||||
height: Theme.fontSizeMedium
|
height: Theme.fontSizeMedium
|
||||||
width: Theme.fontSizeMedium
|
width: Theme.fontSizeMedium
|
||||||
|
@ -73,7 +71,6 @@ ListItem {
|
||||||
visible: chatListViewItem.isSecret
|
visible: chatListViewItem.isSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: chatUnreadMessagesCountBackground
|
id: chatUnreadMessagesCountBackground
|
||||||
color: Theme.highlightBackgroundColor
|
color: Theme.highlightBackgroundColor
|
||||||
|
|
|
@ -41,6 +41,15 @@ SilicaFlickable {
|
||||||
tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId);
|
tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId);
|
||||||
tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0);
|
tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0);
|
||||||
break;
|
break;
|
||||||
|
case "chatTypeSecret":
|
||||||
|
chatInformationPage.isSecretChat = true;
|
||||||
|
chatInformationPage.chatPartnerGroupId = chatInformationPage.chatInformation.type.user_id.toString();
|
||||||
|
if(!chatInformationPage.privateChatUserInformation.id) {
|
||||||
|
chatInformationPage.privateChatUserInformation = tdLibWrapper.getUserInformation(chatInformationPage.chatPartnerGroupId);
|
||||||
|
}
|
||||||
|
tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId);
|
||||||
|
tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0);
|
||||||
|
break;
|
||||||
case "chatTypeBasicGroup":
|
case "chatTypeBasicGroup":
|
||||||
chatInformationPage.isBasicGroup = true;
|
chatInformationPage.isBasicGroup = true;
|
||||||
chatInformationPage.chatPartnerGroupId = chatInformation.type.basic_group_id.toString();
|
chatInformationPage.chatPartnerGroupId = chatInformation.type.basic_group_id.toString();
|
||||||
|
@ -60,8 +69,8 @@ SilicaFlickable {
|
||||||
chatInformationPage.isChannel = chatInformationPage.groupInformation.is_channel;
|
chatInformationPage.isChannel = chatInformationPage.groupInformation.is_channel;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Debug.log("is set up", chatInformationPage.isPrivateChat, chatInformationPage.isBasicGroup, chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId)
|
Debug.log("is set up", chatInformationPage.isPrivateChat, chatInformationPage.isSecretChat, chatInformationPage.isBasicGroup, chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId)
|
||||||
if(!chatInformationPage.isPrivateChat) {
|
if(!(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)) {
|
||||||
updateGroupStatusText();
|
updateGroupStatusText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,18 +156,18 @@ SilicaFlickable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onUserFullInfoReceived: {
|
onUserFullInfoReceived: {
|
||||||
if(chatInformationPage.isPrivateChat && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) {
|
if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) {
|
||||||
chatInformationPage.chatPartnerFullInformation = userFullInfo;
|
chatInformationPage.chatPartnerFullInformation = userFullInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onUserFullInfoUpdated: {
|
onUserFullInfoUpdated: {
|
||||||
if(chatInformationPage.isPrivateChat && userId === chatInformationPage.chatPartnerGroupId) {
|
if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && userId === chatInformationPage.chatPartnerGroupId) {
|
||||||
chatInformationPage.chatPartnerFullInformation = userFullInfo;
|
chatInformationPage.chatPartnerFullInformation = userFullInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onUserProfilePhotosReceived: {
|
onUserProfilePhotosReceived: {
|
||||||
if(chatInformationPage.isPrivateChat && extra === chatInformationPage.chatPartnerGroupId) {
|
if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && extra === chatInformationPage.chatPartnerGroupId) {
|
||||||
chatInformationPage.chatPartnerProfilePhotos = photos;
|
chatInformationPage.chatPartnerProfilePhotos = photos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +189,10 @@ SilicaFlickable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
|
||||||
Component.onCompleted: {7
|
|
||||||
initializePage();
|
initializePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: membersList
|
id: membersList
|
||||||
}
|
}
|
||||||
|
@ -227,13 +232,13 @@ SilicaFlickable {
|
||||||
}
|
}
|
||||||
text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat")
|
text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat")
|
||||||
}
|
}
|
||||||
// MenuItem { //TODO Implement
|
MenuItem {
|
||||||
// visible: !userIsMember
|
visible: chatInformationPage.isPrivateChat
|
||||||
// onClicked: {
|
onClicked: {
|
||||||
// tdLibWrapper.joinChat(chatInformationPage.chatInformation.id);
|
tdLibWrapper.createNewSecretChat(chatInformationPage.chatPartnerGroupId);
|
||||||
// }
|
}
|
||||||
// text: qsTr("Join Chat")
|
text: qsTr("New Secret Chat")
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
// header
|
// header
|
||||||
PageHeader {
|
PageHeader {
|
||||||
|
@ -278,14 +283,14 @@ SilicaFlickable {
|
||||||
active: imageContainer.hasImage
|
active: imageContainer.hasImage
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
anchors.fill: chatPictureThumbnail
|
anchors.fill: chatPictureThumbnail
|
||||||
source: chatInformationPage.isPrivateChat
|
source: ( chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)
|
||||||
? "ChatInformationProfilePictureList.qml"
|
? "ChatInformationProfilePictureList.qml"
|
||||||
: "ChatInformationProfilePicture.qml"
|
: "ChatInformationProfilePicture.qml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leftMargin: imageContainer.getEased((imageContainer.minDimension + Theme.paddingMedium), 0, imageContainer.tweenFactor) + Theme.horizontalPageMargin
|
leftMargin: imageContainer.getEased((imageContainer.minDimension + Theme.paddingMedium), 0, imageContainer.tweenFactor) + Theme.horizontalPageMargin
|
||||||
title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown")
|
title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown")
|
||||||
description: chatInformationPage.isPrivateChat ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : ""
|
description: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
SilicaFlickable {
|
SilicaFlickable {
|
||||||
|
@ -350,7 +355,7 @@ SilicaFlickable {
|
||||||
|
|
||||||
ChatInformationEditArea {
|
ChatInformationEditArea {
|
||||||
visible: canEdit
|
visible: canEdit
|
||||||
canEdit: !chatInformationPage.isPrivateChat && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")
|
canEdit: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")
|
||||||
headerText: qsTr("Chat Title", "group title header")
|
headerText: qsTr("Chat Title", "group title header")
|
||||||
text: chatInformationPage.chatInformation.title
|
text: chatInformationPage.chatInformation.title
|
||||||
|
|
||||||
|
@ -375,13 +380,13 @@ SilicaFlickable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ChatInformationEditArea {
|
ChatInformationEditArea {
|
||||||
canEdit: (chatInformationPage.isPrivateChat && chatInformationPage.privateChatUserInformation.id === chatInformationPage.myUserId) || ((chatInformationPage.isBasicGroup || chatInformationPage.isSuperGroup) && chatInformationPage.groupInformation && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator"))
|
canEdit: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.id === chatInformationPage.myUserId) || ((chatInformationPage.isBasicGroup || chatInformationPage.isSuperGroup) && chatInformationPage.groupInformation && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator"))
|
||||||
emptyPlaceholderText: qsTr("There is no information text available, yet.")
|
emptyPlaceholderText: qsTr("There is no information text available, yet.")
|
||||||
headerText: qsTr("Info", "group or user infotext header")
|
headerText: qsTr("Info", "group or user infotext header")
|
||||||
multiLine: true
|
multiLine: true
|
||||||
text: (chatInformationPage.isPrivateChat ? chatInformationPage.chatPartnerFullInformation.bio : chatInformationPage.groupFullInformation.description) || ""
|
text: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? chatInformationPage.chatPartnerFullInformation.bio : chatInformationPage.groupFullInformation.description) || ""
|
||||||
onSaveButtonClicked: {
|
onSaveButtonClicked: {
|
||||||
if(chatInformationPage.isPrivateChat) { // own bio
|
if ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)) { // own bio
|
||||||
tdLibWrapper.setBio(textValue);
|
tdLibWrapper.setBio(textValue);
|
||||||
} else { // group info
|
} else { // group info
|
||||||
tdLibWrapper.setChatDescription(chatInformationPage.chatInformation.id, textValue);
|
tdLibWrapper.setChatDescription(chatInformationPage.chatInformation.id, textValue);
|
||||||
|
@ -391,7 +396,7 @@ SilicaFlickable {
|
||||||
|
|
||||||
ChatInformationTextItem {
|
ChatInformationTextItem {
|
||||||
headerText: qsTr("Phone Number", "user phone number header")
|
headerText: qsTr("Phone Number", "user phone number header")
|
||||||
text: (chatInformationPage.isPrivateChat && chatInformationPage.privateChatUserInformation.phone_number ? "+"+chatInformationPage.privateChatUserInformation.phone_number : "") || ""
|
text: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.phone_number ? "+"+chatInformationPage.privateChatUserInformation.phone_number : "") || ""
|
||||||
isLinkedLabel: true
|
isLinkedLabel: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +413,7 @@ SilicaFlickable {
|
||||||
visible: !!inviteLinkItem.text
|
visible: !!inviteLinkItem.text
|
||||||
ChatInformationTextItem {
|
ChatInformationTextItem {
|
||||||
id: inviteLinkItem
|
id: inviteLinkItem
|
||||||
text: !isPrivateChat ? chatInformationPage.groupFullInformation.invite_link : ""
|
text: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? chatInformationPage.groupFullInformation.invite_link : ""
|
||||||
width: parent.width - inviteLinkButton.width
|
width: parent.width - inviteLinkButton.width
|
||||||
}
|
}
|
||||||
IconButton {
|
IconButton {
|
||||||
|
|
|
@ -27,15 +27,15 @@ import "../../js/functions.js" as Functions
|
||||||
|
|
||||||
ChatInformationTabItemBase {
|
ChatInformationTabItemBase {
|
||||||
id: tabBase
|
id: tabBase
|
||||||
loadingText: isPrivateChat ? qsTr("Loading common chats…", "chats you have in common with a user") : qsTr("Loading group members…")
|
loadingText: (isPrivateChat || isSecretChat) ? qsTr("Loading common chats…", "chats you have in common with a user") : qsTr("Loading group members…")
|
||||||
loading: ( chatInformationPage.isSuperGroup || chatInformationPage.isPrivateChat) && !chatInformationPage.isChannel
|
loading: ( chatInformationPage.isSuperGroup || chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && !chatInformationPage.isChannel
|
||||||
loadingVisible: loading && membersView.count === 0
|
loadingVisible: loading && membersView.count === 0
|
||||||
|
|
||||||
property var chatPartnerCommonGroupsIds: ([]);
|
property var chatPartnerCommonGroupsIds: ([]);
|
||||||
|
|
||||||
SilicaListView {
|
SilicaListView {
|
||||||
id: membersView
|
id: membersView
|
||||||
model: chatInformationPage.isPrivateChat ? (chatPartnerCommonGroupsIds.length > 0 ? delegateModel : null) : pageContent.membersList
|
model: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? (chatPartnerCommonGroupsIds.length > 0 ? delegateModel : null) : pageContent.membersList
|
||||||
clip: true
|
clip: true
|
||||||
height: tabBase.height
|
height: tabBase.height
|
||||||
width: tabBase.width
|
width: tabBase.width
|
||||||
|
@ -68,7 +68,7 @@ ChatInformationTabItemBase {
|
||||||
ViewPlaceholder {
|
ViewPlaceholder {
|
||||||
y: Theme.paddingLarge
|
y: Theme.paddingLarge
|
||||||
enabled: membersView.count === 0
|
enabled: membersView.count === 0
|
||||||
text: chatInformationPage.isPrivateChat ? qsTr("You don't have any groups in common with this user.") : ( chatInformationPage.isChannel ? qsTr("Channel members are anonymous.") : qsTr("This group is empty.") )
|
text: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? qsTr("You don't have any groups in common with this user.") : ( chatInformationPage.isChannel ? qsTr("Channel members are anonymous.") : qsTr("This group is empty.") )
|
||||||
}
|
}
|
||||||
delegate: PhotoTextsListItem {
|
delegate: PhotoTextsListItem {
|
||||||
pictureThumbnail {
|
pictureThumbnail {
|
||||||
|
@ -204,7 +204,7 @@ ChatInformationTabItemBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onChatsReceived: {// common chats with user
|
onChatsReceived: {// common chats with user
|
||||||
if(isPrivateChat && chats["@extra"] === chatInformationPage.chatPartnerGroupId) {
|
if((isPrivateChat || isSecretChat) && chats["@extra"] === chatInformationPage.chatPartnerGroupId) {
|
||||||
tabBase.chatPartnerCommonGroupsIds = chats.chat_ids;
|
tabBase.chatPartnerCommonGroupsIds = chats.chat_ids;
|
||||||
delegateModel.applyFilter();
|
delegateModel.applyFilter();
|
||||||
// if we set it directly, the views start scrolling
|
// if we set it directly, the views start scrolling
|
||||||
|
@ -221,7 +221,7 @@ ChatInformationTabItemBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if(chatInformationPage.isPrivateChat) {
|
if(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) {
|
||||||
tdLibWrapper.getGroupsInCommon(chatInformationPage.chatPartnerGroupId, 200, 0); // we only use the first 200
|
tdLibWrapper.getGroupsInCommon(chatInformationPage.chatPartnerGroupId, 200, 0); // we only use the first 200
|
||||||
} else if(chatInformationPage.isSuperGroup) {
|
} else if(chatInformationPage.isSuperGroup) {
|
||||||
fetchMoreMembersTimer.start();
|
fetchMoreMembersTimer.start();
|
||||||
|
|
|
@ -124,14 +124,14 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if(!(isPrivateChat && chatPartnerGroupId === myUserId.toString())) {
|
if(!((isPrivateChat || isSecretChat) && chatPartnerGroupId === myUserId.toString())) {
|
||||||
tabModel.append({
|
tabModel.append({
|
||||||
tab:"ChatInformationTabItemMembersGroups",
|
tab:"ChatInformationTabItemMembersGroups",
|
||||||
title: chatInformationPage.isPrivateChat ? qsTr("Groups", "Button: groups in common (short)") : qsTr("Members", "Button: Group Members"),
|
title: ( chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat ) ? qsTr("Groups", "Button: groups in common (short)") : qsTr("Members", "Button: Group Members"),
|
||||||
image: "image://theme/icon-m-people"
|
image: "image://theme/icon-m-people"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if(!isPrivateChat && (groupInformation.status.can_restrict_members || groupInformation.status["@type"] === "chatMemberStatusCreator")) {
|
if(!(isPrivateChat || isSecretChat) && (groupInformation.status.can_restrict_members || groupInformation.status["@type"] === "chatMemberStatusCreator")) {
|
||||||
tabModel.append({
|
tabModel.append({
|
||||||
tab:"ChatInformationTabItemSettings",
|
tab:"ChatInformationTabItemSettings",
|
||||||
title: qsTr("Settings", "Button: Chat Settings"),
|
title: qsTr("Settings", "Button: Chat Settings"),
|
||||||
|
|
|
@ -34,13 +34,14 @@ Page {
|
||||||
property int myUserId: tdLibWrapper.getUserInformation().id;
|
property int myUserId: tdLibWrapper.getUserInformation().id;
|
||||||
|
|
||||||
property bool isPrivateChat: false
|
property bool isPrivateChat: false
|
||||||
|
property bool isSecretChat: false
|
||||||
property bool isBasicGroup: false
|
property bool isBasicGroup: false
|
||||||
property bool isSuperGroup: false
|
property bool isSuperGroup: false
|
||||||
property bool isChannel: false
|
property bool isChannel: false
|
||||||
|
|
||||||
property string chatPartnerGroupId
|
property string chatPartnerGroupId
|
||||||
|
|
||||||
property bool userIsMember: (isPrivateChat && chatInformation["@type"]) || // should be optimized
|
property bool userIsMember: ((isPrivateChat || isSecretChat ) && chatInformation["@type"]) || // should be optimized
|
||||||
(isBasicGroup || isSuperGroup) && (
|
(isBasicGroup || isSuperGroup) && (
|
||||||
(groupInformation.status["@type"] === "chatMemberStatusMember")
|
(groupInformation.status["@type"] === "chatMemberStatusMember")
|
||||||
|| (groupInformation.status["@type"] === "chatMemberStatusAdministrator")
|
|| (groupInformation.status["@type"] === "chatMemberStatusAdministrator")
|
||||||
|
|
|
@ -429,7 +429,7 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onSecretChatReceived: {
|
onSecretChatReceived: {
|
||||||
if (secretChatId.toString() === chatInformation.type.secret_chat_id.toString()) {
|
if (secretChatId === chatInformation.type.secret_chat_id) {
|
||||||
Debug.log("[ChatPage] Received detailed information about this secret chat");
|
Debug.log("[ChatPage] Received detailed information about this secret chat");
|
||||||
chatPage.secretChatDetails = secretChat;
|
chatPage.secretChatDetails = secretChat;
|
||||||
updateChatPartnerStatusText();
|
updateChatPartnerStatusText();
|
||||||
|
@ -706,7 +706,7 @@ Page {
|
||||||
id: chatNameText
|
id: chatNameText
|
||||||
width: Math.min(implicitWidth, parent.width)
|
width: Math.min(implicitWidth, parent.width)
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: chatInformation.title !== "" ? Emoji.emojify((chatPage.isSecretChat ? "🔒 " : "" ) + chatInformation.title, font.pixelSize) : qsTr("Unknown")
|
text: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, font.pixelSize) : qsTr("Unknown")
|
||||||
textFormat: Text.StyledText
|
textFormat: Text.StyledText
|
||||||
font.pixelSize: chatPage.isPortrait ? Theme.fontSizeLarge : Theme.fontSizeMedium
|
font.pixelSize: chatPage.isPortrait ? Theme.fontSizeLarge : Theme.fontSizeMedium
|
||||||
font.family: Theme.fontFamilyHeading
|
font.family: Theme.fontFamilyHeading
|
||||||
|
|
|
@ -35,7 +35,7 @@ Page {
|
||||||
|
|
||||||
function reloadContacts() {
|
function reloadContacts() {
|
||||||
contactsModel.hydrateContacts();
|
contactsModel.hydrateContacts();
|
||||||
contactsListView.model = contactsModel;
|
contactsListView.model = contactsProxyModel;
|
||||||
newChatPage.isLoading = false;
|
newChatPage.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,14 +46,6 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: contactsModel
|
|
||||||
onErrorSynchronizingContacts: {
|
|
||||||
reloadContacts();
|
|
||||||
appNotification.show(qsTr("Could not synchronize your contacts with Telegram."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: tdLibWrapper
|
target: tdLibWrapper
|
||||||
onContactsImported: {
|
onContactsImported: {
|
||||||
|
@ -72,7 +64,11 @@ Page {
|
||||||
MenuItem {
|
MenuItem {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
newChatPage.isLoading = true;
|
newChatPage.isLoading = true;
|
||||||
contactsModel.synchronizeContacts();
|
if (!contactsModel.synchronizeContacts()) {
|
||||||
|
reloadContacts();
|
||||||
|
appNotification.show(qsTr("Could not synchronize your contacts with Telegram."));
|
||||||
|
}
|
||||||
|
// Success message is not fired before TDLib returned "Contacts imported" (see above)
|
||||||
}
|
}
|
||||||
text: qsTr("Synchronize Contacts with Telegram")
|
text: qsTr("Synchronize Contacts with Telegram")
|
||||||
}
|
}
|
||||||
|
@ -103,7 +99,11 @@ Page {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
placeholderText: qsTr("Search a contact...")
|
placeholderText: qsTr("Search a contact...")
|
||||||
active: !newChatPage.isLoading
|
active: !newChatPage.isLoading
|
||||||
onTextChanged: contactsModel.applyFilter(text);
|
|
||||||
|
onTextChanged: {
|
||||||
|
contactsProxyModel.setFilterWildcard("*" + text + "*");
|
||||||
|
}
|
||||||
|
|
||||||
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
EnterKey.iconSource: "image://theme/icon-m-enter-close"
|
||||||
EnterKey.onClicked: {
|
EnterKey.onClicked: {
|
||||||
resetFocus();
|
resetFocus();
|
||||||
|
@ -140,15 +140,15 @@ Page {
|
||||||
Behavior on opacity { FadeAnimation {} }
|
Behavior on opacity { FadeAnimation {} }
|
||||||
|
|
||||||
pictureThumbnail {
|
pictureThumbnail {
|
||||||
photoData: (typeof display.profile_photo !== "undefined") ? display.profile_photo.small : {}
|
photoData: typeof photo_small !== "undefined" ? photo_small : {}
|
||||||
}
|
}
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
primaryText.text: Emoji.emojify(Functions.getUserName(display), primaryText.font.pixelSize, "../js/emoji/")
|
primaryText.text: Emoji.emojify(title, primaryText.font.pixelSize, "../js/emoji/")
|
||||||
prologSecondaryText.text: "@" + ( display.username !== "" ? display.username : display.id )
|
prologSecondaryText.text: "@" + ( username !== "" ? username : user_id )
|
||||||
tertiaryText {
|
tertiaryText {
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
text: Functions.getChatPartnerStatusText(display.status["@type"], display.status.was_online);
|
text: Functions.getChatPartnerStatusText(user_status, user_last_online);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -191,22 +191,20 @@ Page {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
opacity: 0.3
|
opacity: Theme.opacityLow
|
||||||
color: Theme.overlayBackgroundColor
|
color: Theme.overlayBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: privateChatItem
|
id: privateChatItem
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: parent.width / 2 // - ( Theme.horizontalPageMargin / 2 )
|
width: parent.width / 2
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: privateChatHighlightBackground
|
id: privateChatHighlightBackground
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Theme.highlightBackgroundColor
|
color: Theme.highlightBackgroundColor
|
||||||
opacity: 0.5
|
opacity: Theme.opacityHigh
|
||||||
visible: false
|
visible: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +271,7 @@ Page {
|
||||||
Item {
|
Item {
|
||||||
id: secretChatItem
|
id: secretChatItem
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: parent.width / 2 //+ ( Theme.horizontalPageMargin / 2 )
|
width: parent.width / 2
|
||||||
anchors.left: privateChatItem.right
|
anchors.left: privateChatItem.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
@ -281,7 +279,7 @@ Page {
|
||||||
id: secretChatHighlightBackground
|
id: secretChatHighlightBackground
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Theme.highlightBackgroundColor
|
color: Theme.highlightBackgroundColor
|
||||||
opacity: 0.5
|
opacity: Theme.opacityHigh
|
||||||
visible: false
|
visible: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +295,7 @@ Page {
|
||||||
icon.source: "image://theme/icon-m-device-lock"
|
icon.source: "image://theme/icon-m-device-lock"
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("SECRET CHAT!");
|
tdLibWrapper.createNewSecretChat(display.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,15 +51,39 @@ ContactsModel::ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> ContactsModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int,QByteArray> roles;
|
||||||
|
roles.insert(ContactRole::RoleDisplay, "display");
|
||||||
|
roles.insert(ContactRole::RoleTitle, "title");
|
||||||
|
roles.insert(ContactRole::RoleUserId, "user_id");
|
||||||
|
roles.insert(ContactRole::RoleUsername, "username");
|
||||||
|
roles.insert(ContactRole::RolePhotoSmall, "photo_small");
|
||||||
|
roles.insert(ContactRole::RoleUserStatus, "user_status");
|
||||||
|
roles.insert(ContactRole::RoleUserLastOnline, "user_last_online");
|
||||||
|
roles.insert(ContactRole::RoleFilter, "filter");
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
int ContactsModel::rowCount(const QModelIndex &) const
|
int ContactsModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return this->filter.isEmpty() ? this->contacts.size() : this->filteredContacts.size();
|
return this->contacts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ContactsModel::data(const QModelIndex &index, int role) const
|
QVariant ContactsModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (index.isValid() && role == Qt::DisplayRole) {
|
if (index.isValid()) {
|
||||||
return this->filter.isEmpty() ? QVariant(contacts.value(index.row())) : QVariant(filteredContacts.value(index.row())) ;
|
QVariantMap requestedContact = contacts.value(index.row()).toMap();
|
||||||
|
switch (static_cast<ContactRole>(role)) {
|
||||||
|
case ContactRole::RoleDisplay: return requestedContact;
|
||||||
|
case ContactRole::RoleTitle: return QString(requestedContact.value("first_name").toString() + " " + requestedContact.value("last_name").toString()).trimmed();
|
||||||
|
case ContactRole::RoleUserId: return requestedContact.value("id");
|
||||||
|
case ContactRole::RoleUsername: return requestedContact.value("username");
|
||||||
|
case ContactRole::RolePhotoSmall: return requestedContact.value("profile_photo").toMap().value("small");
|
||||||
|
case ContactRole::RoleUserStatus: return requestedContact.value("status").toMap().value("@type");
|
||||||
|
case ContactRole::RoleUserLastOnline: return requestedContact.value("status").toMap().value("was_online");
|
||||||
|
case ContactRole::RoleFilter: return QString(requestedContact.value("first_name").toString() + " " + requestedContact.value("last_name").toString() + " " + requestedContact.value("username").toString()).trimmed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -126,34 +150,7 @@ void ContactsModel::hydrateContacts()
|
||||||
std::sort(this->contacts.begin(), this->contacts.end(), compareUsers);
|
std::sort(this->contacts.begin(), this->contacts.end(), compareUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsModel::applyFilter(const QString &filter)
|
bool ContactsModel::synchronizeContacts()
|
||||||
{
|
|
||||||
LOG("Applying filter:" << filter);
|
|
||||||
beginResetModel();
|
|
||||||
this->filter = filter;
|
|
||||||
this->filteredContacts.clear();
|
|
||||||
if (!this->filter.isEmpty()) {
|
|
||||||
QListIterator<QVariant> contactIterator(this->contacts);
|
|
||||||
while (contactIterator.hasNext()) {
|
|
||||||
QVariantMap contact = contactIterator.next().toMap();
|
|
||||||
if (contact.value(LAST_NAME).toString().contains(this->filter, Qt::CaseInsensitive)) {
|
|
||||||
this->filteredContacts.append(contact);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (contact.value(FIRST_NAME).toString().contains(this->filter, Qt::CaseInsensitive)) {
|
|
||||||
this->filteredContacts.append(contact);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (contact.value(USERNAME).toString().contains(this->filter, Qt::CaseInsensitive)) {
|
|
||||||
this->filteredContacts.append(contact);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContactsModel::synchronizeContacts()
|
|
||||||
{
|
{
|
||||||
LOG("Synchronizing device contacts");
|
LOG("Synchronizing device contacts");
|
||||||
QVariantList deviceContacts;
|
QVariantList deviceContacts;
|
||||||
|
@ -173,10 +170,10 @@ void ContactsModel::synchronizeContacts()
|
||||||
LOG("Importing found contacts" << deviceContacts.size());
|
LOG("Importing found contacts" << deviceContacts.size());
|
||||||
this->tdLibWrapper->importContacts(deviceContacts);
|
this->tdLibWrapper->importContacts(deviceContacts);
|
||||||
}
|
}
|
||||||
emit contactsSynchronized();
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOG("Error selecting contacts from database!");
|
LOG("Error selecting contacts from database!");
|
||||||
emit errorSynchronizingContacts();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,27 +31,34 @@ class ContactsModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum ContactRole {
|
||||||
|
RoleDisplay = Qt::DisplayRole,
|
||||||
|
RolePhotoSmall,
|
||||||
|
RoleTitle,
|
||||||
|
RoleUserId,
|
||||||
|
RoleUsername,
|
||||||
|
RoleUserStatus,
|
||||||
|
RoleUserLastOnline,
|
||||||
|
RoleFilter
|
||||||
|
};
|
||||||
|
|
||||||
ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent = nullptr);
|
ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent = nullptr);
|
||||||
|
|
||||||
virtual int rowCount(const QModelIndex &) const;
|
virtual QHash<int,QByteArray> roleNames() const override;
|
||||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
virtual int rowCount(const QModelIndex &) const override;
|
||||||
|
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
Q_INVOKABLE void hydrateContacts();
|
Q_INVOKABLE void hydrateContacts();
|
||||||
Q_INVOKABLE void applyFilter(const QString &filter);
|
Q_INVOKABLE bool synchronizeContacts();
|
||||||
Q_INVOKABLE void synchronizeContacts();
|
|
||||||
Q_INVOKABLE bool canSynchronizeContacts();
|
Q_INVOKABLE bool canSynchronizeContacts();
|
||||||
|
|
||||||
signals:
|
|
||||||
void contactsSynchronized();
|
|
||||||
void errorSynchronizingContacts();
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers);
|
void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TDLibWrapper *tdLibWrapper;
|
TDLibWrapper *tdLibWrapper;
|
||||||
QVariantList contacts;
|
QVariantList contacts;
|
||||||
QVariantList filteredContacts;
|
|
||||||
QList<QString> contactIds;
|
QList<QString> contactIds;
|
||||||
QString filter;
|
QString filter;
|
||||||
QSqlDatabase deviceContactsDatabase;
|
QSqlDatabase deviceContactsDatabase;
|
||||||
|
|
|
@ -99,6 +99,11 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
ContactsModel contactsModel(tdLibWrapper, view.data());
|
ContactsModel contactsModel(tdLibWrapper, view.data());
|
||||||
context->setContextProperty("contactsModel", &contactsModel);
|
context->setContextProperty("contactsModel", &contactsModel);
|
||||||
|
QSortFilterProxyModel contactsProxyModel(view.data());
|
||||||
|
contactsProxyModel.setSourceModel(&contactsModel);
|
||||||
|
contactsProxyModel.setFilterRole(ContactsModel::RoleFilter);
|
||||||
|
contactsProxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
context->setContextProperty("contactsProxyModel", &contactsProxyModel);
|
||||||
|
|
||||||
view->setSource(SailfishApp::pathTo("qml/harbour-fernschreiber.qml"));
|
view->setSource(SailfishApp::pathTo("qml/harbour-fernschreiber.qml"));
|
||||||
view->show();
|
view->show();
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation>Neuer geheimer Chat</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation>New Secret Chat</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -176,6 +176,10 @@
|
||||||
<numerusform>%1 en línea</numerusform>
|
<numerusform>%1 en línea</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 paikalla</numerusform>
|
<numerusform>%1 paikalla</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -176,6 +176,10 @@
|
||||||
<numerusform></numerusform>
|
<numerusform></numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -182,6 +182,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -182,6 +182,10 @@
|
||||||
<numerusform></numerusform>
|
<numerusform></numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -176,6 +176,10 @@
|
||||||
<numerusform>%1 位在线</numerusform>
|
<numerusform>%1 位在线</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
|
@ -179,6 +179,10 @@
|
||||||
<numerusform>%1 online</numerusform>
|
<numerusform>%1 online</numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>New Secret Chat</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ChatInformationTabItemMembersGroups</name>
|
<name>ChatInformationTabItemMembersGroups</name>
|
||||||
|
|
Loading…
Reference in a new issue