From 3dbf38a1faec26e5eaddb43ee4d79392e6006e27 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Fri, 20 Nov 2020 18:30:33 +0100 Subject: [PATCH 01/17] Start implementing 'New Chat' functionality --- harbour-fernschreiber.pro | 1 + qml/pages/NewChatPage.qml | 92 +++++++++++++++++++++ qml/pages/OverviewPage.qml | 7 +- src/tdlibwrapper.cpp | 36 +++++++- src/tdlibwrapper.h | 4 + translations/harbour-fernschreiber-de.ts | 15 ++++ translations/harbour-fernschreiber-en.ts | 15 ++++ translations/harbour-fernschreiber-es.ts | 15 ++++ translations/harbour-fernschreiber-fi.ts | 15 ++++ translations/harbour-fernschreiber-hu.ts | 15 ++++ translations/harbour-fernschreiber-it.ts | 15 ++++ translations/harbour-fernschreiber-pl.ts | 15 ++++ translations/harbour-fernschreiber-ru.ts | 15 ++++ translations/harbour-fernschreiber-sv.ts | 15 ++++ translations/harbour-fernschreiber-zh_CN.ts | 15 ++++ translations/harbour-fernschreiber.ts | 19 ++++- 16 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 qml/pages/NewChatPage.qml diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 31887de..c1f6b12 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -70,6 +70,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/pages/ChatSelectionPage.qml \ qml/pages/CoverPage.qml \ qml/pages/InitializationPage.qml \ + qml/pages/NewChatPage.qml \ qml/pages/OverviewPage.qml \ qml/pages/AboutPage.qml \ qml/pages/PollCreationPage.qml \ diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml new file mode 100644 index 0000000..288d5b6 --- /dev/null +++ b/qml/pages/NewChatPage.qml @@ -0,0 +1,92 @@ +/* + 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 + +Page { + id: newChatPage + allowedOrientations: Orientation.All + + property var contacts; + property bool isLoading: true; + + SilicaFlickable { + id: newChatContainer + contentHeight: newChatPage.height + anchors.fill: parent + + Column { + id: newChatPageColumn + width: newChatPage.width + height: newChatPage.height + + PageHeader { + id: newChatPageHeader + title: qsTr("Your Contacts") + } + + SilicaListView { + id: contactsListView + model: newChatPage.contacts + clip: true + height: newChatPageColumn.height - newChatPageHeader.height + width: newChatPageColumn.width + opacity: newChatPage.isLoading ? 0 : 1 + Behavior on opacity { FadeAnimation {} } + + ViewPlaceholder { + y: Theme.paddingLarge + enabled: contactsListView.count === 0 + text: qsTr("You don't have any contacts.") + } + + delegate: PhotoTextsListItem { + pictureThumbnail { + photoData: (typeof modelData.profile_photo !== "undefined") ? modelData.profile_photo.small : "" + } + width: parent.width + + primaryText.text: Emoji.emojify(Functions.getUserName(modelData), primaryText.font.pixelSize, "../js/emoji/") + prologSecondaryText.text: "@" + ( modelData.username !== "" ? modelData.username : modelData.id ) +// secondaryText { +// horizontalAlignment: Text.AlignRight +// property string statusText: Functions.getChatMemberStatusText(model.status["@type"]) +// property string customText: model.status.custom_title ? Emoji.emojify(model.status.custom_title, secondaryText.font.pixelSize, "../js/emoji/") : "" +// text: (statusText !== "" && customText !== "") ? statusText + ", " + customText : statusText + customText +// } + tertiaryText { + maximumLineCount: 1 + text: Functions.getChatPartnerStatusText(modelData.status["@type"], modelData.status.was_online); + elide: Text.ElideRight + } + + onClicked: { + tdLibWrapper.createPrivateChat(user_id); + } + } + + VerticalScrollDecorator {} + } + } + + } +} diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index ee55c1f..8050f69 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -46,7 +46,7 @@ Page { onPleaseOpenMessage: { console.log("[OverviewPage] Opening chat from external call...") if (chatListCreated) { - pageStack.pop(overviewPage, PageStackAction.Immediate) + pageStack.pop(overviewPage, PageStackAction.Immediate); pageStack.push(Qt.resolvedUrl("../pages/ChatPage.qml"), { "chatInformation" : tdLibWrapper.getChat(chatId) }, PageStackAction.Immediate) } } @@ -96,6 +96,7 @@ Page { tdLibWrapper.getChats(); tdLibWrapper.getRecentStickers(); tdLibWrapper.getInstalledStickerSets(); + tdLibWrapper.getContacts(); } function initializePage() { @@ -184,6 +185,10 @@ Page { text: qsTr("Settings") onClicked: pageStack.push(Qt.resolvedUrl("../pages/SettingsPage.qml")) } + MenuItem { + text: qsTr("New Chat") + onClicked: pageStack.push(Qt.resolvedUrl("../pages/NewChatPage.qml")) + } } AppNotification { diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 293dbfa..69cb54c 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -47,7 +47,7 @@ namespace { const QString _EXTRA("@extra"); } -TDLibWrapper::TDLibWrapper(AppSettings *appSettings, QObject *parent) : QObject(parent), joinChatRequested(false) +TDLibWrapper::TDLibWrapper(AppSettings *appSettings, QObject *parent) : QObject(parent), joinChatRequested(false), contactsRequested(false) { LOG("Initializing TD Lib..."); this->appSettings = appSettings; @@ -113,7 +113,7 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, QObject *parent) : QObject( connect(this->tdLibReceiver, SIGNAL(chatPhotoUpdated(qlonglong, QVariantMap)), this, SIGNAL(chatPhotoUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatTitleUpdated(QString, QString)), this, SIGNAL(chatTitleUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong))); - connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SIGNAL(usersReceived(QString, QVariantList, int))); + connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SLOT(handleUsersReceived(QString, QVariantList, int))); connect(this->tdLibReceiver, SIGNAL(errorReceived(int, QString)), this, SIGNAL(errorReceived(int, QString))); connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList))); @@ -605,7 +605,7 @@ void TDLibWrapper::getGroupFullInfo(const QString &groupId, bool isSuperGroup) void TDLibWrapper::getUserFullInfo(const QString &userId) { - LOG("Retrieving UserFullInfo"); + LOG("Retrieving UserFullInfo" << userId); QVariantMap requestObject; requestObject.insert(_TYPE, "getUserFullInfo"); requestObject.insert(_EXTRA, userId); @@ -792,6 +792,15 @@ void TDLibWrapper::getDeepLinkInfo(const QString &link) this->sendRequest(requestObject); } +void TDLibWrapper::getContacts() +{ + LOG("Retrieving contacts"); + this->contactsRequested = true; + QVariantMap requestObject; + requestObject.insert(_TYPE, "getContacts"); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); @@ -813,6 +822,11 @@ QVariantMap TDLibWrapper::getUserInformation(const QString &userId) return this->allUsers.value(userId).toMap(); } +bool TDLibWrapper::hasUserInformation(const QString &userId) +{ + return this->allUsers.contains(userId); +} + QVariantMap TDLibWrapper::getUserInformationByName(const QString &userName) { return this->allUserNames.value(userName).toMap(); @@ -1133,6 +1147,22 @@ void TDLibWrapper::handleOpenWithChanged() } } +void TDLibWrapper::handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers) +{ + if (this->contactsRequested) { + LOG("Received contacts list..."); + this->contactsRequested = false; + QListIterator userIdIterator(userIds); + while (userIdIterator.hasNext()) { + QString nextUserId = userIdIterator.next().toString(); + if (!this->hasUserInformation(nextUserId)) { + this->getUserFullInfo(nextUserId); + } + } + } + emit usersReceived(extra, userIds, totalUsers); +} + void TDLibWrapper::setInitialParameters() { LOG("Sending initial parameters to TD Lib"); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 0f02595..897ea65 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -93,6 +93,7 @@ public: Q_INVOKABLE TDLibWrapper::ConnectionState getConnectionState(); Q_INVOKABLE QVariantMap getUserInformation(); Q_INVOKABLE QVariantMap getUserInformation(const QString &userId); + Q_INVOKABLE bool hasUserInformation(const QString &userId); Q_INVOKABLE QVariantMap getUserInformationByName(const QString &userName); Q_INVOKABLE QVariantMap getUnreadMessageInformation(); Q_INVOKABLE QVariantMap getUnreadChatInformation(); @@ -160,6 +161,7 @@ public: Q_INVOKABLE void searchPublicChat(const QString &userName); Q_INVOKABLE void joinChatByInviteLink(const QString &inviteLink); Q_INVOKABLE void getDeepLinkInfo(const QString &link); + Q_INVOKABLE void getContacts(); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); @@ -241,6 +243,7 @@ public slots: void handleStickerSets(const QVariantList &stickerSets); void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList); void handleOpenWithChanged(); + void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); private: void setInitialParameters(); @@ -270,6 +273,7 @@ private: QString activeChatSearchName; bool joinChatRequested; + bool contactsRequested; }; diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 6aae9f2..ccc7c22 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -890,6 +890,17 @@ Diese Nachricht wurde weitergeleitet. Ursprünglicher Autor: %1 + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -942,6 +953,10 @@ You don't have any chats yet. Sie haben noch keine Chats. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index c5d0035..345c7dc 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -890,6 +890,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -942,6 +953,10 @@ You don't have any chats yet. You don't have any chats yet. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 3ecd8ae..2d506d9 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -880,6 +880,17 @@ Este mensaje fue reenviado. Autor original: %1 + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -931,6 +942,10 @@ You don't have any chats yet. No hay todavía ninguna charla. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 7fb55f6..859707e 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -891,6 +891,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -943,6 +954,10 @@ You don't have any chats yet. Sinulla ei ole vielä keskusteluja. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index fce5b95..e2d74a5 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -880,6 +880,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -931,6 +942,10 @@ You don't have any chats yet. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index c04d265..6fa01c0 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -890,6 +890,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -942,6 +953,10 @@ Loading chat list... Carica lista chat... + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 0cf5934..b2a67fd 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -900,6 +900,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -953,6 +964,10 @@ You don't have any chats yet. Nie masz jeszcze żadnych czatów. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 289d794..8683689 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -900,6 +900,17 @@ + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -953,6 +964,10 @@ You don't have any chats yet. Тут пока ничего нет + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index e558854..b3f2436 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -890,6 +890,17 @@ Detta meddelande är vidarebefordrat. Ursprunglig avsändare: %1 + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -942,6 +953,10 @@ You don't have any chats yet. Du har inga chattar än. + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 5ffa019..2480d2f 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -880,6 +880,17 @@ 此消息为转发消息,原作者: %1 + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -931,6 +942,10 @@ You don't have any chats yet. 你还没有任何对话。 + + New Chat + + PinnedMessageItem diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 073eadb..345c7dc 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -883,13 +883,24 @@ MessageOverlayFlickable You - + You This message was forwarded. Original author: %1 + + NewChatPage + + Your Contacts + + + + You don't have any contacts. + + + NotificationManager @@ -942,12 +953,16 @@ You don't have any chats yet. You don't have any chats yet. + + New Chat + + PinnedMessageItem You - + You Pinned Message From 9d75cbbedfcbdc7bd7bac09374772c21d4cbe480 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Fri, 20 Nov 2020 23:00:50 +0100 Subject: [PATCH 02/17] Showing sorted contacts, wow! --- qml/pages/NewChatPage.qml | 10 ++++++-- src/tdlibwrapper.cpp | 48 +++++++++++++++++++++++++++++++++++++++ src/tdlibwrapper.h | 2 ++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 288d5b6..0ccb8ca 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -29,6 +29,12 @@ Page { property var contacts; property bool isLoading: true; + onStatusChanged: { + if (status === PageStatus.Active) { + newChatPage.contacts = tdLibWrapper.getContactsFullInfo(); + } + } + SilicaFlickable { id: newChatContainer contentHeight: newChatPage.height @@ -50,7 +56,7 @@ Page { clip: true height: newChatPageColumn.height - newChatPageHeader.height width: newChatPageColumn.width - opacity: newChatPage.isLoading ? 0 : 1 + //opacity: newChatPage.isLoading ? 0 : 1 Behavior on opacity { FadeAnimation {} } ViewPlaceholder { @@ -80,7 +86,7 @@ Page { } onClicked: { - tdLibWrapper.createPrivateChat(user_id); + tdLibWrapper.createPrivateChat(modelData.id); } } diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 69cb54c..1ee93e7 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -43,6 +43,9 @@ namespace { const QString STATUS("status"); const QString ID("id"); const QString TYPE("type"); + const QString LAST_NAME("last_name"); + const QString FIRST_NAME("first_name"); + const QString USERNAME("username"); const QString _TYPE("@type"); const QString _EXTRA("@extra"); } @@ -935,6 +938,49 @@ void TDLibWrapper::registerJoinChat() this->joinChatRequested = false; } +static bool compareUsers(const QVariant &user1, const QVariant &user2) +{ + const QVariantMap userMap1 = user1.toMap(); + const QVariantMap userMap2 = user2.toMap(); + + const QString lastName1 = userMap1.value(LAST_NAME).toString(); + const QString lastName2 = userMap2.value(LAST_NAME).toString(); + if (lastName1 < lastName2) { + return true; + } else if (lastName1 > lastName2) { + return false; + } + const QString firstName1 = userMap1.value(FIRST_NAME).toString(); + const QString firstName2 = userMap2.value(FIRST_NAME).toString(); + if (firstName1 < firstName2) { + return true; + } else if (firstName1 > firstName2) { + return false; + } + const QString userName1 = userMap1.value(USERNAME).toString(); + const QString userName2 = userMap2.value(USERNAME).toString(); + if (userName1 < userName2) { + return true; + } else if (userName1 > userName2) { + return false; + } + return userMap1.value(ID).toLongLong() < userMap2.value(ID).toLongLong(); +} + +QVariantList TDLibWrapper::getContactsFullInfo() +{ + QVariantList preparedContacts; + QListIterator userIdIterator(contacts); + while (userIdIterator.hasNext()) { + QString nextUserId = userIdIterator.next(); + if (allUsers.contains(nextUserId)) { + preparedContacts.append(allUsers.value(nextUserId)); + } + } + std::sort(preparedContacts.begin(), preparedContacts.end(), compareUsers); + return preparedContacts; +} + DBusAdaptor *TDLibWrapper::getDBusAdaptor() { return this->dbusInterface->getDBusAdaptor(); @@ -1152,12 +1198,14 @@ void TDLibWrapper::handleUsersReceived(const QString &extra, const QVariantList if (this->contactsRequested) { LOG("Received contacts list..."); this->contactsRequested = false; + contacts.clear(); QListIterator userIdIterator(userIds); while (userIdIterator.hasNext()) { QString nextUserId = userIdIterator.next().toString(); if (!this->hasUserInformation(nextUserId)) { this->getUserFullInfo(nextUserId); } + contacts.append(nextUserId); } } emit usersReceived(extra, userIds, totalUsers); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 897ea65..c716bc5 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -106,6 +106,7 @@ public: Q_INVOKABLE void controlScreenSaver(bool enabled); Q_INVOKABLE bool getJoinChatRequested(); Q_INVOKABLE void registerJoinChat(); + Q_INVOKABLE QVariantList getContactsFullInfo(); DBusAdaptor *getDBusAdaptor(); @@ -265,6 +266,7 @@ private: QVariantMap allUsers; QVariantMap allUserNames; QVariantMap chats; + QList contacts; QVariantMap unreadMessageInformation; QVariantMap unreadChatInformation; QHash basicGroups; From c6fa5cf97ff3a60345094864a98e67dfc80e66b6 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sat, 21 Nov 2020 22:13:37 +0100 Subject: [PATCH 03/17] Options for creating new chats... --- qml/pages/NewChatPage.qml | 298 +++++++++++++++++--- src/tdlibwrapper.cpp | 11 +- translations/harbour-fernschreiber-de.ts | 8 + translations/harbour-fernschreiber-en.ts | 8 + translations/harbour-fernschreiber-es.ts | 8 + translations/harbour-fernschreiber-fi.ts | 8 + translations/harbour-fernschreiber-hu.ts | 8 + translations/harbour-fernschreiber-it.ts | 8 + translations/harbour-fernschreiber-pl.ts | 8 + translations/harbour-fernschreiber-ru.ts | 8 + translations/harbour-fernschreiber-sv.ts | 8 + translations/harbour-fernschreiber-zh_CN.ts | 8 + translations/harbour-fernschreiber.ts | 8 + 13 files changed, 360 insertions(+), 37 deletions(-) diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 0ccb8ca..606710d 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -32,6 +32,7 @@ Page { onStatusChanged: { if (status === PageStatus.Active) { newChatPage.contacts = tdLibWrapper.getContactsFullInfo(); + newChatPage.isLoading = false; } } @@ -50,49 +51,280 @@ Page { title: qsTr("Your Contacts") } - SilicaListView { - id: contactsListView - model: newChatPage.contacts - clip: true - height: newChatPageColumn.height - newChatPageHeader.height + Item { + id: contactsItem + width: newChatPageColumn.width - //opacity: newChatPage.isLoading ? 0 : 1 - Behavior on opacity { FadeAnimation {} } + height: newChatPageColumn.height - newChatPageHeader.height - ViewPlaceholder { - y: Theme.paddingLarge - enabled: contactsListView.count === 0 - text: qsTr("You don't have any contacts.") - } - - delegate: PhotoTextsListItem { - pictureThumbnail { - photoData: (typeof modelData.profile_photo !== "undefined") ? modelData.profile_photo.small : "" - } + SilicaListView { + id: contactsListView + model: newChatPage.contacts + clip: true width: parent.width + height: parent.height + visible: !newChatPage.isLoading + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } - primaryText.text: Emoji.emojify(Functions.getUserName(modelData), primaryText.font.pixelSize, "../js/emoji/") - prologSecondaryText.text: "@" + ( modelData.username !== "" ? modelData.username : modelData.id ) -// secondaryText { -// horizontalAlignment: Text.AlignRight -// property string statusText: Functions.getChatMemberStatusText(model.status["@type"]) -// property string customText: model.status.custom_title ? Emoji.emojify(model.status.custom_title, secondaryText.font.pixelSize, "../js/emoji/") : "" -// text: (statusText !== "" && customText !== "") ? statusText + ", " + customText : statusText + customText -// } - tertiaryText { - maximumLineCount: 1 - text: Functions.getChatPartnerStatusText(modelData.status["@type"], modelData.status.was_online); - elide: Text.ElideRight + signal newChatInitiated ( int currentIndex ) + + ViewPlaceholder { + y: Theme.paddingLarge + enabled: contactsListView.count === 0 + text: qsTr("You don't have any contacts.") } - onClicked: { - tdLibWrapper.createPrivateChat(modelData.id); + delegate: Item { + id: newChatListItem + width: parent.width + height: contactListItem.height + + PhotoTextsListItem { + id: contactListItem + + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + + pictureThumbnail { + photoData: (typeof modelData.profile_photo !== "undefined") ? modelData.profile_photo.small : {} + } + width: parent.width + + primaryText.text: Emoji.emojify(Functions.getUserName(modelData), primaryText.font.pixelSize, "../js/emoji/") + prologSecondaryText.text: "@" + ( modelData.username !== "" ? modelData.username : modelData.id ) + tertiaryText { + maximumLineCount: 1 + text: Functions.getChatPartnerStatusText(modelData.status["@type"], modelData.status.was_online); + elide: Text.ElideRight + } + + onClicked: { + contactsListView.newChatInitiated(index); + } + + Connections { + target: contactsListView + onNewChatInitiated: { + if (index === currentIndex) { + contactListItem.visible = false; + } else { + contactListItem.visible = true; + } + } + } + } + + Column { + id: selectChatTypeColumn + visible: !contactListItem.visible + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + width: parent.width + height: contactListItem.height + + Item { + width: parent.width + height: parent.height - chatTypeSeparator.height + + Rectangle { + anchors.fill: parent + opacity: 0.3 + color: Theme.overlayBackgroundColor + } + + Item { + id: privateChatItem + height: parent.height + width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + anchors.left: parent.left + anchors.top: parent.top + + Rectangle { + id: privateChatHighlightBackground + anchors.fill: parent + color: Theme.highlightBackgroundColor + opacity: 0.5 + visible: false + } + + Row { + width: parent.width + height: parent.height - ( 2 * Theme.paddingSmall ) + anchors.verticalCenter: parent.verticalCenter + + IconButton { + id: privateChatButton + width: Theme.itemSizeLarge + height: Theme.itemSizeLarge + icon.source: "image://theme/icon-m-chat" + anchors.verticalCenter: parent.verticalCenter + onClicked: { + tdLibWrapper.createPrivateChat(modelData.id); + } + } + + Column { + height: parent.height + width: parent.width - privateChatButton.width - Theme.horizontalPageMargin + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.paddingSmall + Text { + id: privateChatHeader + width: parent.width + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.ExtraBold + color: Theme.primaryColor + maximumLineCount: 1 + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Private Chat") + } + Text { + width: parent.width + height: parent.height - privateChatHeader.height - Theme.paddingSmall + font.pixelSize: Theme.fontSizeTiny + color: Theme.secondaryColor + wrapMode: Text.Wrap + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Transport-encrypted, stored in Telegram Cloud, sharable across devices") + } + } + + } + + MouseArea { + anchors.fill: parent + onClicked: { + tdLibWrapper.createPrivateChat(modelData.id); + } + onPressed: { + privateChatHighlightBackground.visible = true; + } + onReleased: { + privateChatHighlightBackground.visible = false; + } + } + } + + Item { + id: secretChatItem + height: parent.height + width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + anchors.left: privateChatItem.right + anchors.top: parent.top + + Rectangle { + id: secretChatHighlightBackground + anchors.fill: parent + color: Theme.highlightBackgroundColor + opacity: 0.5 + visible: false + } + + Row { + width: parent.width + height: parent.height - ( 2 * Theme.paddingSmall ) + anchors.verticalCenter: parent.verticalCenter + + IconButton { + id: secretChatButton + width: Theme.itemSizeLarge + height: Theme.itemSizeLarge + icon.source: "image://theme/icon-m-device-lock" + anchors.verticalCenter: parent.verticalCenter + onClicked: { + console.log("SECRET CHAT!"); + } + } + + Column { + height: parent.height + width: parent.width - secretChatButton.width - Theme.horizontalPageMargin + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.paddingSmall + Text { + width: parent.width + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.ExtraBold + color: Theme.primaryColor + maximumLineCount: 1 + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Secret Chat") + } + Text { + width: parent.width + height: parent.height - privateChatHeader.height - Theme.paddingSmall + font.pixelSize: Theme.fontSizeTiny + color: Theme.secondaryColor + wrapMode: Text.Wrap + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("End-to-end-encrypted, accessible on this device only") + } + } + + } + + MouseArea { + anchors.fill: parent + onClicked: { + console.log("SECRET CHAT!"); + } + onPressed: { + secretChatHighlightBackground.visible = true; + } + onReleased: { + secretChatHighlightBackground.visible = false; + } + } + } + + } + + Separator { + id: chatTypeSeparator + width: parent.width + color: Theme.primaryColor + horizontalAlignment: Qt.AlignHCenter + } + + } + + } + + VerticalScrollDecorator {} + } + + Column { + + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + visible: newChatPage.isLoading + width: parent.width + height: loadingLabel.height + loadingBusyIndicator.height + Theme.paddingMedium + + spacing: Theme.paddingMedium + + anchors.verticalCenter: parent.verticalCenter + + InfoLabel { + id: loadingLabel + text: qsTr("Loading contacs...") + } + + BusyIndicator { + id: loadingBusyIndicator + anchors.horizontalCenter: parent.horizontalCenter + running: newChatPage.isLoading + size: BusyIndicatorSize.Large } } - VerticalScrollDecorator {} } - } + } } } diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 1ee93e7..35627f6 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -945,11 +945,14 @@ static bool compareUsers(const QVariant &user1, const QVariant &user2) const QString lastName1 = userMap1.value(LAST_NAME).toString(); const QString lastName2 = userMap2.value(LAST_NAME).toString(); - if (lastName1 < lastName2) { - return true; - } else if (lastName1 > lastName2) { - return false; + if (!lastName1.isEmpty()) { + if (lastName1 < lastName2) { + return true; + } else if (lastName1 > lastName2) { + return false; + } } + const QString firstName1 = userMap1.value(FIRST_NAME).toString(); const QString firstName2 = userMap2.value(FIRST_NAME).toString(); if (firstName1 < firstName2) { diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index ba7a6da..7275abf 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -900,6 +900,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 10b812e..cb366d0 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -900,6 +900,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 713df9e..c614667 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -890,6 +890,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 4ac28d9..9fe8954 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -901,6 +901,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index b4b5943..4285c5b 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -890,6 +890,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index e447337..891e2dd 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -900,6 +900,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 9c6ca06..5d1a105 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -910,6 +910,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index c77126f..20f6eef 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -910,6 +910,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index fb9b0d4..6722cc6 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -900,6 +900,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index a4c00ab..56403ac 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -890,6 +890,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 10b812e..cb366d0 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -900,6 +900,14 @@ You don't have any contacts. + + Loading contacs... + + + + Private Chat + + NotificationManager From cb764bae67f95afdef27a82f240cf13e86335950 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sun, 22 Nov 2020 19:15:14 +0100 Subject: [PATCH 04/17] Translation file updates --- translations/harbour-fernschreiber-de.ts | 12 ++++++++++++ translations/harbour-fernschreiber-en.ts | 12 ++++++++++++ translations/harbour-fernschreiber-es.ts | 12 ++++++++++++ translations/harbour-fernschreiber-fi.ts | 12 ++++++++++++ translations/harbour-fernschreiber-hu.ts | 12 ++++++++++++ translations/harbour-fernschreiber-it.ts | 12 ++++++++++++ translations/harbour-fernschreiber-pl.ts | 12 ++++++++++++ translations/harbour-fernschreiber-ru.ts | 12 ++++++++++++ translations/harbour-fernschreiber-sv.ts | 12 ++++++++++++ translations/harbour-fernschreiber-zh_CN.ts | 12 ++++++++++++ translations/harbour-fernschreiber.ts | 12 ++++++++++++ 11 files changed, 132 insertions(+) diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 7275abf..4149ee1 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -908,6 +908,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index cb366d0..efa5a1a 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -908,6 +908,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index c614667..f246dc2 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -898,6 +898,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 9fe8954..c85edfa 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -909,6 +909,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 4285c5b..6e3503d 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -898,6 +898,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 891e2dd..1d6a9bd 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -908,6 +908,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 5d1a105..5e3c3d1 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -918,6 +918,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 20f6eef..6376a20 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -918,6 +918,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 6722cc6..419b395 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -908,6 +908,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 56403ac..9334db7 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -898,6 +898,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index cb366d0..efa5a1a 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -908,6 +908,18 @@ Private Chat + + Transport-encrypted, stored in Telegram Cloud, sharable across devices + + + + Secret Chat + + + + End-to-end-encrypted, accessible on this device only + + NotificationManager From 20b773ac592ac60827b6a256beecb42babfdbfe8 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Mon, 23 Nov 2020 20:53:43 +0100 Subject: [PATCH 05/17] Check contacts requested via extra-attribute --- qml/pages/NewChatPage.qml | 1 - src/tdlibwrapper.cpp | 7 +++---- src/tdlibwrapper.h | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 606710d..42b3933 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -96,7 +96,6 @@ Page { tertiaryText { maximumLineCount: 1 text: Functions.getChatPartnerStatusText(modelData.status["@type"], modelData.status.was_online); - elide: Text.ElideRight } onClicked: { diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 91d5fa0..84634fe 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -44,7 +44,7 @@ namespace { const QString _EXTRA("@extra"); } -TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, QObject *parent) : QObject(parent), joinChatRequested(false), contactsRequested(false) +TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, QObject *parent) : QObject(parent), joinChatRequested(false) { LOG("Initializing TD Lib..."); this->appSettings = appSettings; @@ -793,9 +793,9 @@ void TDLibWrapper::getDeepLinkInfo(const QString &link) void TDLibWrapper::getContacts() { LOG("Retrieving contacts"); - this->contactsRequested = true; QVariantMap requestObject; requestObject.insert(_TYPE, "getContacts"); + requestObject.insert(_EXTRA, "contactsRequested"); this->sendRequest(requestObject); } @@ -1187,9 +1187,8 @@ void TDLibWrapper::handleOpenWithChanged() void TDLibWrapper::handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers) { - if (this->contactsRequested) { + if (extra == "contactsRequested") { LOG("Received contacts list..."); - this->contactsRequested = false; contacts.clear(); QListIterator userIdIterator(userIds); while (userIdIterator.hasNext()) { diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 9a0142a..d2d3268 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -277,7 +277,6 @@ private: QString activeChatSearchName; bool joinChatRequested; - bool contactsRequested; }; From 86599b2859a01694f0ba37511ec5656fdad0ff35 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Tue, 24 Nov 2020 16:13:16 +0100 Subject: [PATCH 06/17] Move contacts to an own model --- harbour-fernschreiber.pro | 2 + qml/pages/NewChatPage.qml | 17 +++-- src/contactsmodel.cpp | 118 ++++++++++++++++++++++++++++++++++ src/contactsmodel.h | 48 ++++++++++++++ src/harbour-fernschreiber.cpp | 4 ++ src/tdlibwrapper.cpp | 75 ++++----------------- src/tdlibwrapper.h | 4 +- 7 files changed, 192 insertions(+), 76 deletions(-) create mode 100644 src/contactsmodel.cpp create mode 100644 src/contactsmodel.h diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 67d6326..3731efa 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -24,6 +24,7 @@ SOURCES += src/harbour-fernschreiber.cpp \ src/appsettings.cpp \ src/chatlistmodel.cpp \ src/chatmodel.cpp \ + src/contactsmodel.cpp \ src/dbusadaptor.cpp \ src/dbusinterface.cpp \ src/emojisearchworker.cpp \ @@ -146,6 +147,7 @@ HEADERS += \ src/appsettings.h \ src/chatlistmodel.h \ src/chatmodel.h \ + src/contactsmodel.h \ src/dbusadaptor.h \ src/dbusinterface.h \ src/debuglog.h \ diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 42b3933..0579f11 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -26,12 +26,12 @@ Page { id: newChatPage allowedOrientations: Orientation.All - property var contacts; property bool isLoading: true; onStatusChanged: { if (status === PageStatus.Active) { - newChatPage.contacts = tdLibWrapper.getContactsFullInfo(); + contactsModel.hydrateContacts(); + contactsListView.model = contactsModel; newChatPage.isLoading = false; } } @@ -59,7 +59,6 @@ Page { SilicaListView { id: contactsListView - model: newChatPage.contacts clip: true width: parent.width height: parent.height @@ -87,15 +86,15 @@ Page { Behavior on opacity { FadeAnimation {} } pictureThumbnail { - photoData: (typeof modelData.profile_photo !== "undefined") ? modelData.profile_photo.small : {} + photoData: (typeof display.profile_photo !== "undefined") ? display.profile_photo.small : {} } width: parent.width - primaryText.text: Emoji.emojify(Functions.getUserName(modelData), primaryText.font.pixelSize, "../js/emoji/") - prologSecondaryText.text: "@" + ( modelData.username !== "" ? modelData.username : modelData.id ) + primaryText.text: Emoji.emojify(Functions.getUserName(display), primaryText.font.pixelSize, "../js/emoji/") + prologSecondaryText.text: "@" + ( display.username !== "" ? display.username : display.id ) tertiaryText { maximumLineCount: 1 - text: Functions.getChatPartnerStatusText(modelData.status["@type"], modelData.status.was_online); + text: Functions.getChatPartnerStatusText(display.status["@type"], display.status.was_online); } onClicked: { @@ -159,7 +158,7 @@ Page { icon.source: "image://theme/icon-m-chat" anchors.verticalCenter: parent.verticalCenter onClicked: { - tdLibWrapper.createPrivateChat(modelData.id); + tdLibWrapper.createPrivateChat(display.id); } } @@ -196,7 +195,7 @@ Page { MouseArea { anchors.fill: parent onClicked: { - tdLibWrapper.createPrivateChat(modelData.id); + tdLibWrapper.createPrivateChat(display.id); } onPressed: { privateChatHighlightBackground.visible = true; diff --git a/src/contactsmodel.cpp b/src/contactsmodel.cpp new file mode 100644 index 0000000..ebb0984 --- /dev/null +++ b/src/contactsmodel.cpp @@ -0,0 +1,118 @@ +/* + 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 . +*/ + +#include "contactsmodel.h" +#include + +#define DEBUG_MODULE ContactsModel +#include "debuglog.h" + +namespace { + const QString STATUS("status"); + const QString ID("id"); + const QString TYPE("type"); + const QString LAST_NAME("last_name"); + const QString FIRST_NAME("first_name"); + const QString USERNAME("username"); + const QString _TYPE("@type"); + const QString _EXTRA("@extra"); +} + +ContactsModel::ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent) + : QAbstractListModel(parent) +{ + this->tdLibWrapper = tdLibWrapper; + + connect(this->tdLibWrapper, SIGNAL(usersReceived(QString, QVariantList, int)), this, SLOT(handleUsersReceived(QString, QVariantList, int))); +} + +int ContactsModel::rowCount(const QModelIndex &) const +{ + return this->contacts.size(); +} + +QVariant ContactsModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid() && role == Qt::DisplayRole) { + return QVariant(contacts.value(index.row())); + } + return QVariant(); +} + +void ContactsModel::handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers) +{ + if (extra == "contactsRequested") { + LOG("Received contacts list..." << totalUsers); + this->contactIds.clear(); + QListIterator userIdIterator(userIds); + while (userIdIterator.hasNext()) { + QString nextUserId = userIdIterator.next().toString(); + if (!this->tdLibWrapper->hasUserInformation(nextUserId)) { + this->tdLibWrapper->getUserFullInfo(nextUserId); + } + this->contactIds.append(nextUserId); + } + } +} + +static bool compareUsers(const QVariant &user1, const QVariant &user2) +{ + const QVariantMap userMap1 = user1.toMap(); + const QVariantMap userMap2 = user2.toMap(); + + const QString lastName1 = userMap1.value(LAST_NAME).toString(); + const QString lastName2 = userMap2.value(LAST_NAME).toString(); + if (!lastName1.isEmpty()) { + if (lastName1 < lastName2) { + return true; + } else if (lastName1 > lastName2) { + return false; + } + } + + const QString firstName1 = userMap1.value(FIRST_NAME).toString(); + const QString firstName2 = userMap2.value(FIRST_NAME).toString(); + if (firstName1 < firstName2) { + return true; + } else if (firstName1 > firstName2) { + return false; + } + const QString userName1 = userMap1.value(USERNAME).toString(); + const QString userName2 = userMap2.value(USERNAME).toString(); + if (userName1 < userName2) { + return true; + } else if (userName1 > userName2) { + return false; + } + return userMap1.value(ID).toLongLong() < userMap2.value(ID).toLongLong(); +} + +void ContactsModel::hydrateContacts() +{ + LOG("Hydrating contacts..."); + this->contacts.clear(); + QListIterator userIdIterator(contactIds); + while (userIdIterator.hasNext()) { + QString nextUserId = userIdIterator.next(); + LOG("Hydrating contact:" << nextUserId); + this->contacts.append(this->tdLibWrapper->getUserInformation(nextUserId)); + } + LOG("Hydrated contacts:" << this->contacts.size()); + std::sort(this->contacts.begin(), this->contacts.end(), compareUsers); +} diff --git a/src/contactsmodel.h b/src/contactsmodel.h new file mode 100644 index 0000000..e9c38b4 --- /dev/null +++ b/src/contactsmodel.h @@ -0,0 +1,48 @@ +/* + 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 . +*/ + +#ifndef CONTACTSMODEL_H +#define CONTACTSMODEL_H + +#include +#include + +#include "tdlibwrapper.h" + +class ContactsModel : public QAbstractListModel +{ + Q_OBJECT +public: + ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent = nullptr); + + virtual int rowCount(const QModelIndex &) const; + virtual QVariant data(const QModelIndex &index, int role) const; + + Q_INVOKABLE void hydrateContacts(); + +public slots: + void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); + +private: + TDLibWrapper *tdLibWrapper; + QVariantList contacts; + QList contactIds; +}; + +#endif // CONTACTSMODEL_H diff --git a/src/harbour-fernschreiber.cpp b/src/harbour-fernschreiber.cpp index 1c54a3e..a75f8de 100644 --- a/src/harbour-fernschreiber.cpp +++ b/src/harbour-fernschreiber.cpp @@ -42,6 +42,7 @@ #include "stickermanager.h" #include "tgsplugin.h" #include "fernschreiberutils.h" +#include "contactsmodel.h" // The default filter can be overridden by QT_LOGGING_RULES envinronment variable, e.g. // QT_LOGGING_RULES="fernschreiber.*=true" harbour-fernschreiber @@ -96,6 +97,9 @@ int main(int argc, char *argv[]) StickerManager stickerManager(tdLibWrapper); context->setContextProperty("stickerManager", &stickerManager); + ContactsModel contactsModel(tdLibWrapper, view.data()); + context->setContextProperty("contactsModel", &contactsModel); + view->setSource(SailfishApp::pathTo("qml/harbour-fernschreiber.qml")); view->show(); return app->exec(); diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 84634fe..bf94d2b 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -111,7 +111,7 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(chatPhotoUpdated(qlonglong, QVariantMap)), this, SIGNAL(chatPhotoUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chatTitleUpdated(QString, QString)), this, SIGNAL(chatTitleUpdated(QString, QString))); connect(this->tdLibReceiver, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong))); - connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SLOT(handleUsersReceived(QString, QVariantList, int))); + connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SIGNAL(usersReceived(QString, QVariantList, int))); connect(this->tdLibReceiver, SIGNAL(errorReceived(int, QString)), this, SIGNAL(errorReceived(int, QString))); connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList))); @@ -621,6 +621,16 @@ void TDLibWrapper::createPrivateChat(const QString &userId) this->sendRequest(requestObject); } +void TDLibWrapper::createNewSecretChat(const QString &userId) +{ + LOG("Creating new secret chat"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "createNewSecretChat"); + requestObject.insert("user_id", userId); + requestObject.insert(_EXTRA, "openDirectly"); //gets matched in qml + this->sendRequest(requestObject); +} + void TDLibWrapper::createSupergroupChat(const QString &supergroupId) { LOG("Creating Supergroup Chat"); @@ -927,52 +937,6 @@ void TDLibWrapper::registerJoinChat() this->joinChatRequested = false; } -static bool compareUsers(const QVariant &user1, const QVariant &user2) -{ - const QVariantMap userMap1 = user1.toMap(); - const QVariantMap userMap2 = user2.toMap(); - - const QString lastName1 = userMap1.value(LAST_NAME).toString(); - const QString lastName2 = userMap2.value(LAST_NAME).toString(); - if (!lastName1.isEmpty()) { - if (lastName1 < lastName2) { - return true; - } else if (lastName1 > lastName2) { - return false; - } - } - - const QString firstName1 = userMap1.value(FIRST_NAME).toString(); - const QString firstName2 = userMap2.value(FIRST_NAME).toString(); - if (firstName1 < firstName2) { - return true; - } else if (firstName1 > firstName2) { - return false; - } - const QString userName1 = userMap1.value(USERNAME).toString(); - const QString userName2 = userMap2.value(USERNAME).toString(); - if (userName1 < userName2) { - return true; - } else if (userName1 > userName2) { - return false; - } - return userMap1.value(ID).toLongLong() < userMap2.value(ID).toLongLong(); -} - -QVariantList TDLibWrapper::getContactsFullInfo() -{ - QVariantList preparedContacts; - QListIterator userIdIterator(contacts); - while (userIdIterator.hasNext()) { - QString nextUserId = userIdIterator.next(); - if (allUsers.contains(nextUserId)) { - preparedContacts.append(allUsers.value(nextUserId)); - } - } - std::sort(preparedContacts.begin(), preparedContacts.end(), compareUsers); - return preparedContacts; -} - DBusAdaptor *TDLibWrapper::getDBusAdaptor() { return this->dbusInterface->getDBusAdaptor(); @@ -1185,23 +1149,6 @@ void TDLibWrapper::handleOpenWithChanged() } } -void TDLibWrapper::handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers) -{ - if (extra == "contactsRequested") { - LOG("Received contacts list..."); - contacts.clear(); - QListIterator userIdIterator(userIds); - while (userIdIterator.hasNext()) { - QString nextUserId = userIdIterator.next().toString(); - if (!this->hasUserInformation(nextUserId)) { - this->getUserFullInfo(nextUserId); - } - contacts.append(nextUserId); - } - } - emit usersReceived(extra, userIds, totalUsers); -} - void TDLibWrapper::setInitialParameters() { LOG("Sending initial parameters to TD Lib"); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index d2d3268..8bc0f9b 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -107,7 +107,6 @@ public: Q_INVOKABLE void controlScreenSaver(bool enabled); Q_INVOKABLE bool getJoinChatRequested(); Q_INVOKABLE void registerJoinChat(); - Q_INVOKABLE QVariantList getContactsFullInfo(); DBusAdaptor *getDBusAdaptor(); @@ -147,6 +146,7 @@ public: Q_INVOKABLE void getGroupFullInfo(const QString &groupId, bool isSuperGroup); Q_INVOKABLE void getUserFullInfo(const QString &userId); Q_INVOKABLE void createPrivateChat(const QString &userId); + Q_INVOKABLE void createNewSecretChat(const QString &userId); Q_INVOKABLE void createSupergroupChat(const QString &supergroupId); Q_INVOKABLE void createBasicGroupChat(const QString &basicGroupId); Q_INVOKABLE void getGroupsInCommon(const QString &userId, int limit, int offset); @@ -245,7 +245,6 @@ public slots: void handleStickerSets(const QVariantList &stickerSets); void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList); void handleOpenWithChanged(); - void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); private: void setInitialParameters(); @@ -268,7 +267,6 @@ private: QVariantMap allUsers; QVariantMap allUserNames; QVariantMap chats; - QList contacts; QVariantMap unreadMessageInformation; QVariantMap unreadChatInformation; QHash basicGroups; From 4713fbfba6ce79504a99f52400589430f266c15d Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Tue, 24 Nov 2020 17:28:41 +0100 Subject: [PATCH 07/17] Apply a dumb filter on contacts --- qml/pages/NewChatPage.qml | 414 +++++++++++--------- src/contactsmodel.cpp | 31 +- src/contactsmodel.h | 3 + translations/harbour-fernschreiber-de.ts | 4 + translations/harbour-fernschreiber-en.ts | 4 + translations/harbour-fernschreiber-es.ts | 4 + translations/harbour-fernschreiber-fi.ts | 4 + translations/harbour-fernschreiber-hu.ts | 4 + translations/harbour-fernschreiber-it.ts | 4 + translations/harbour-fernschreiber-pl.ts | 4 + translations/harbour-fernschreiber-ru.ts | 4 + translations/harbour-fernschreiber-sv.ts | 4 + translations/harbour-fernschreiber-zh_CN.ts | 4 + translations/harbour-fernschreiber.ts | 4 + 14 files changed, 300 insertions(+), 192 deletions(-) diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 0579f11..44f6912 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -36,6 +36,11 @@ Page { } } + function resetFocus() { + contactsSearchField.focus = false; + newChatPage.focus = true; + } + SilicaFlickable { id: newChatContainer contentHeight: newChatPage.height @@ -57,243 +62,272 @@ Page { width: newChatPageColumn.width height: newChatPageColumn.height - newChatPageHeader.height - SilicaListView { - id: contactsListView - clip: true + Column { + visible: !newChatPage.isLoading width: parent.width height: parent.height - visible: !newChatPage.isLoading - opacity: visible ? 1 : 0 - Behavior on opacity { FadeAnimation {} } - - signal newChatInitiated ( int currentIndex ) - - ViewPlaceholder { - y: Theme.paddingLarge - enabled: contactsListView.count === 0 - text: qsTr("You don't have any contacts.") - } - - delegate: Item { - id: newChatListItem + SearchField { + id: contactsSearchField width: parent.width - height: contactListItem.height - - PhotoTextsListItem { - id: contactListItem - - opacity: visible ? 1 : 0 - Behavior on opacity { FadeAnimation {} } - - pictureThumbnail { - photoData: (typeof display.profile_photo !== "undefined") ? display.profile_photo.small : {} - } - width: parent.width - - primaryText.text: Emoji.emojify(Functions.getUserName(display), primaryText.font.pixelSize, "../js/emoji/") - prologSecondaryText.text: "@" + ( display.username !== "" ? display.username : display.id ) - tertiaryText { - maximumLineCount: 1 - text: Functions.getChatPartnerStatusText(display.status["@type"], display.status.was_online); - } - - onClicked: { - contactsListView.newChatInitiated(index); - } - - Connections { - target: contactsListView - onNewChatInitiated: { - if (index === currentIndex) { - contactListItem.visible = false; - } else { - contactListItem.visible = true; - } - } - } + placeholderText: qsTr("Search a contact") + active: !newChatPage.isLoading + onTextChanged: contactsModel.applyFilter(text); + EnterKey.iconSource: "image://theme/icon-m-enter-close" + EnterKey.onClicked: { + resetFocus(); } - Column { - id: selectChatTypeColumn - visible: !contactListItem.visible - opacity: visible ? 1 : 0 - Behavior on opacity { FadeAnimation {} } + } + + SilicaListView { + id: contactsListView + clip: true + width: parent.width + height: parent.height - contactsSearchField.height + visible: !newChatPage.isLoading + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + + signal newChatInitiated ( int currentIndex ) + + ViewPlaceholder { + y: Theme.paddingLarge + enabled: contactsListView.count === 0 + text: qsTr("You don't have any contacts.") + } + + delegate: Item { + id: newChatListItem width: parent.width height: contactListItem.height - Item { - width: parent.width - height: parent.height - chatTypeSeparator.height + PhotoTextsListItem { + id: contactListItem - Rectangle { - anchors.fill: parent - opacity: 0.3 - color: Theme.overlayBackgroundColor + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + + pictureThumbnail { + photoData: (typeof display.profile_photo !== "undefined") ? display.profile_photo.small : {} + } + width: parent.width + + primaryText.text: Emoji.emojify(Functions.getUserName(display), primaryText.font.pixelSize, "../js/emoji/") + prologSecondaryText.text: "@" + ( display.username !== "" ? display.username : display.id ) + tertiaryText { + maximumLineCount: 1 + text: Functions.getChatPartnerStatusText(display.status["@type"], display.status.was_online); } + onClicked: { + contactsListView.newChatInitiated(index); + } + + Connections { + target: contactsListView + + onNewChatInitiated: { + if (index === currentIndex) { + contactListItem.visible = false; + } else { + contactListItem.visible = true; + } + } + } + + Connections { + target: contactsSearchField + onFocusChanged: { + if (contactsSearchField.focus) { + contactListItem.visible = true; + } + } + } + } + + Column { + id: selectChatTypeColumn + visible: !contactListItem.visible + opacity: visible ? 1 : 0 + Behavior on opacity { FadeAnimation {} } + width: parent.width + height: contactListItem.height + Item { - id: privateChatItem - height: parent.height - width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) - anchors.left: parent.left - anchors.top: parent.top + width: parent.width + height: parent.height - chatTypeSeparator.height Rectangle { - id: privateChatHighlightBackground anchors.fill: parent - color: Theme.highlightBackgroundColor - opacity: 0.5 - visible: false + opacity: 0.3 + color: Theme.overlayBackgroundColor } - Row { - width: parent.width - height: parent.height - ( 2 * Theme.paddingSmall ) - anchors.verticalCenter: parent.verticalCenter + Item { + id: privateChatItem + height: parent.height + width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + anchors.left: parent.left + anchors.top: parent.top - IconButton { - id: privateChatButton - width: Theme.itemSizeLarge - height: Theme.itemSizeLarge - icon.source: "image://theme/icon-m-chat" + Rectangle { + id: privateChatHighlightBackground + anchors.fill: parent + color: Theme.highlightBackgroundColor + opacity: 0.5 + visible: false + } + + Row { + width: parent.width + height: parent.height - ( 2 * Theme.paddingSmall ) anchors.verticalCenter: parent.verticalCenter + + IconButton { + id: privateChatButton + width: Theme.itemSizeLarge + height: Theme.itemSizeLarge + icon.source: "image://theme/icon-m-chat" + anchors.verticalCenter: parent.verticalCenter + onClicked: { + tdLibWrapper.createPrivateChat(display.id); + } + } + + Column { + height: parent.height + width: parent.width - privateChatButton.width - Theme.horizontalPageMargin + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.paddingSmall + Text { + id: privateChatHeader + width: parent.width + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.ExtraBold + color: Theme.primaryColor + maximumLineCount: 1 + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Private Chat") + } + Text { + width: parent.width + height: parent.height - privateChatHeader.height - Theme.paddingSmall + font.pixelSize: Theme.fontSizeTiny + color: Theme.secondaryColor + wrapMode: Text.Wrap + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Transport-encrypted, stored in Telegram Cloud, sharable across devices") + } + } + + } + + MouseArea { + anchors.fill: parent onClicked: { tdLibWrapper.createPrivateChat(display.id); } - } - - Column { - height: parent.height - width: parent.width - privateChatButton.width - Theme.horizontalPageMargin - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.paddingSmall - Text { - id: privateChatHeader - width: parent.width - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.ExtraBold - color: Theme.primaryColor - maximumLineCount: 1 - elide: Text.ElideRight - textFormat: Text.StyledText - text: qsTr("Private Chat") + onPressed: { + privateChatHighlightBackground.visible = true; } - Text { - width: parent.width - height: parent.height - privateChatHeader.height - Theme.paddingSmall - font.pixelSize: Theme.fontSizeTiny - color: Theme.secondaryColor - wrapMode: Text.Wrap - elide: Text.ElideRight - textFormat: Text.StyledText - text: qsTr("Transport-encrypted, stored in Telegram Cloud, sharable across devices") + onReleased: { + privateChatHighlightBackground.visible = false; } } - } - MouseArea { - anchors.fill: parent - onClicked: { - tdLibWrapper.createPrivateChat(display.id); + Item { + id: secretChatItem + height: parent.height + width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + anchors.left: privateChatItem.right + anchors.top: parent.top + + Rectangle { + id: secretChatHighlightBackground + anchors.fill: parent + color: Theme.highlightBackgroundColor + opacity: 0.5 + visible: false } - onPressed: { - privateChatHighlightBackground.visible = true; - } - onReleased: { - privateChatHighlightBackground.visible = false; - } - } - } - Item { - id: secretChatItem - height: parent.height - width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) - anchors.left: privateChatItem.right - anchors.top: parent.top - - Rectangle { - id: secretChatHighlightBackground - anchors.fill: parent - color: Theme.highlightBackgroundColor - opacity: 0.5 - visible: false - } - - Row { - width: parent.width - height: parent.height - ( 2 * Theme.paddingSmall ) - anchors.verticalCenter: parent.verticalCenter - - IconButton { - id: secretChatButton - width: Theme.itemSizeLarge - height: Theme.itemSizeLarge - icon.source: "image://theme/icon-m-device-lock" + Row { + width: parent.width + height: parent.height - ( 2 * Theme.paddingSmall ) anchors.verticalCenter: parent.verticalCenter + + IconButton { + id: secretChatButton + width: Theme.itemSizeLarge + height: Theme.itemSizeLarge + icon.source: "image://theme/icon-m-device-lock" + anchors.verticalCenter: parent.verticalCenter + onClicked: { + console.log("SECRET CHAT!"); + } + } + + Column { + height: parent.height + width: parent.width - secretChatButton.width - Theme.horizontalPageMargin + anchors.verticalCenter: parent.verticalCenter + spacing: Theme.paddingSmall + Text { + width: parent.width + font.pixelSize: Theme.fontSizeMedium + font.weight: Font.ExtraBold + color: Theme.primaryColor + maximumLineCount: 1 + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("Secret Chat") + } + Text { + width: parent.width + height: parent.height - privateChatHeader.height - Theme.paddingSmall + font.pixelSize: Theme.fontSizeTiny + color: Theme.secondaryColor + wrapMode: Text.Wrap + elide: Text.ElideRight + textFormat: Text.StyledText + text: qsTr("End-to-end-encrypted, accessible on this device only") + } + } + + } + + MouseArea { + anchors.fill: parent onClicked: { console.log("SECRET CHAT!"); } - } - - Column { - height: parent.height - width: parent.width - secretChatButton.width - Theme.horizontalPageMargin - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.paddingSmall - Text { - width: parent.width - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.ExtraBold - color: Theme.primaryColor - maximumLineCount: 1 - elide: Text.ElideRight - textFormat: Text.StyledText - text: qsTr("Secret Chat") + onPressed: { + secretChatHighlightBackground.visible = true; } - Text { - width: parent.width - height: parent.height - privateChatHeader.height - Theme.paddingSmall - font.pixelSize: Theme.fontSizeTiny - color: Theme.secondaryColor - wrapMode: Text.Wrap - elide: Text.ElideRight - textFormat: Text.StyledText - text: qsTr("End-to-end-encrypted, accessible on this device only") + onReleased: { + secretChatHighlightBackground.visible = false; } } - } - MouseArea { - anchors.fill: parent - onClicked: { - console.log("SECRET CHAT!"); - } - onPressed: { - secretChatHighlightBackground.visible = true; - } - onReleased: { - secretChatHighlightBackground.visible = false; - } - } } - } + Separator { + id: chatTypeSeparator + width: parent.width + color: Theme.primaryColor + horizontalAlignment: Qt.AlignHCenter + } - Separator { - id: chatTypeSeparator - width: parent.width - color: Theme.primaryColor - horizontalAlignment: Qt.AlignHCenter } } + VerticalScrollDecorator {} } - VerticalScrollDecorator {} } Column { diff --git a/src/contactsmodel.cpp b/src/contactsmodel.cpp index ebb0984..2f0f08e 100644 --- a/src/contactsmodel.cpp +++ b/src/contactsmodel.cpp @@ -44,13 +44,13 @@ ContactsModel::ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent) int ContactsModel::rowCount(const QModelIndex &) const { - return this->contacts.size(); + return this->filter.isEmpty() ? this->contacts.size() : this->filteredContacts.size(); } QVariant ContactsModel::data(const QModelIndex &index, int role) const { if (index.isValid() && role == Qt::DisplayRole) { - return QVariant(contacts.value(index.row())); + return this->filter.isEmpty() ? QVariant(contacts.value(index.row())) : QVariant(filteredContacts.value(index.row())) ; } return QVariant(); } @@ -116,3 +116,30 @@ void ContactsModel::hydrateContacts() LOG("Hydrated contacts:" << this->contacts.size()); std::sort(this->contacts.begin(), this->contacts.end(), compareUsers); } + +void ContactsModel::applyFilter(const QString &filter) +{ + LOG("Applying filter:" << filter); + beginResetModel(); + this->filter = filter; + this->filteredContacts.clear(); + if (!this->filter.isEmpty()) { + QListIterator 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(); +} diff --git a/src/contactsmodel.h b/src/contactsmodel.h index e9c38b4..0500358 100644 --- a/src/contactsmodel.h +++ b/src/contactsmodel.h @@ -35,6 +35,7 @@ public: virtual QVariant data(const QModelIndex &index, int role) const; Q_INVOKABLE void hydrateContacts(); + Q_INVOKABLE void applyFilter(const QString &filter); public slots: void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); @@ -42,7 +43,9 @@ public slots: private: TDLibWrapper *tdLibWrapper; QVariantList contacts; + QVariantList filteredContacts; QList contactIds; + QString filter; }; #endif // CONTACTSMODEL_H diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 4149ee1..c67fcf4 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -920,6 +920,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index efa5a1a..5b7749b 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -920,6 +920,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index f246dc2..b23e74d 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -910,6 +910,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index e294f4b..73f0a08 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -921,6 +921,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 6e3503d..a1641b9 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -910,6 +910,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 3cb5d6e..e48ce94 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -920,6 +920,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 5e3c3d1..14d2e88 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -930,6 +930,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 6376a20..80bbaaf 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -930,6 +930,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 6d177c4..430859d 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -920,6 +920,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index a1d1f1e..c14d458 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -910,6 +910,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index efa5a1a..5b7749b 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -920,6 +920,10 @@ End-to-end-encrypted, accessible on this device only + + Search a contact + + NotificationManager From a6d8328b1031d8d60831e9436e597889313a0fb3 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Wed, 25 Nov 2020 00:23:38 +0100 Subject: [PATCH 08/17] I can see secret chats... ;) --- qml/components/ChatListViewItem.qml | 8 ++- qml/components/PhotoTextsListItem.qml | 25 +++++++ qml/js/functions.js | 13 ++++ qml/pages/ChatPage.qml | 79 +++++++++++++++++---- qml/pages/NewChatPage.qml | 10 +-- src/fernschreiberutils.cpp | 4 ++ src/tdlibreceiver.cpp | 14 ++++ src/tdlibreceiver.h | 5 +- src/tdlibwrapper.cpp | 11 +++ src/tdlibwrapper.h | 3 + translations/harbour-fernschreiber-de.ts | 42 +++++++---- translations/harbour-fernschreiber-en.ts | 32 ++++++--- translations/harbour-fernschreiber-es.ts | 32 ++++++--- translations/harbour-fernschreiber-fi.ts | 32 ++++++--- translations/harbour-fernschreiber-hu.ts | 32 ++++++--- translations/harbour-fernschreiber-it.ts | 32 ++++++--- translations/harbour-fernschreiber-pl.ts | 32 ++++++--- translations/harbour-fernschreiber-ru.ts | 32 ++++++--- translations/harbour-fernschreiber-sv.ts | 32 ++++++--- translations/harbour-fernschreiber-zh_CN.ts | 32 ++++++--- translations/harbour-fernschreiber.ts | 32 ++++++--- 21 files changed, 419 insertions(+), 115 deletions(-) diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml index 47bf5fc..4644efc 100644 --- a/qml/components/ChatListViewItem.qml +++ b/qml/components/ChatListViewItem.qml @@ -1,5 +1,6 @@ import QtQuick 2.6 import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 import "../js/twemoji.js" as Emoji import "../js/functions.js" as Functions @@ -14,12 +15,13 @@ PhotoTextsListItem { // chat title primaryText.text: title ? Emoji.emojify(title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown") // 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") ) : qsTr("Unknown") ) + 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 - secondaryText.text: last_message_text ? Emoji.emojify(Functions.enhanceHtmlEntities(last_message_text), Theme.fontSizeExtraSmall) : qsTr("Unknown") + secondaryText.text: last_message_text ? Emoji.emojify(Functions.enhanceHtmlEntities(last_message_text), Theme.fontSizeExtraSmall) : "" + qsTr("No message in this chat.") + "" // message date - tertiaryText.text: ( last_message_date ? Functions.getDateTimeElapsed(last_message_date) : qsTr("Unknown") ) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) + tertiaryText.text: ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" ) unreadCount: unread_count + isSecret: ( chat_type === TelegramAPI.ChatTypeSecret ) openMenuOnPressAndHold: true//chat_id != overviewPage.ownUserId menu: ContextMenu { diff --git a/qml/components/PhotoTextsListItem.qml b/qml/components/PhotoTextsListItem.qml index 0a40a37..ceb8c39 100644 --- a/qml/components/PhotoTextsListItem.qml +++ b/qml/components/PhotoTextsListItem.qml @@ -1,5 +1,7 @@ import QtQuick 2.6 import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 + ListItem { id: chatListViewItem @@ -10,6 +12,7 @@ ListItem { property alias tertiaryText: tertiaryText //usually last message date property int unreadCount + property bool isSecret: false property alias pictureThumbnail: pictureThumbnail contentHeight: mainRow.height + separator.height + 2 * Theme.paddingMedium @@ -50,6 +53,27 @@ ListItem { height: parent.width } + Rectangle { + id: chatSecretBackground + color: Theme.overlayBackgroundColor + width: Theme.fontSizeExtraLarge + height: Theme.fontSizeExtraLarge + anchors.left: parent.left + anchors.bottom: parent.bottom + radius: parent.width / 2 + visible: chatListViewItem.isSecret + } + + Image { + id: chatSecretImage + source: "image://theme/icon-s-secure" + height: Theme.fontSizeMedium + width: Theme.fontSizeMedium + anchors.centerIn: chatSecretBackground + visible: chatListViewItem.isSecret + } + + Rectangle { id: chatUnreadMessagesCountBackground color: Theme.highlightBackgroundColor @@ -104,6 +128,7 @@ ListItem { width: parent.width - Theme.paddingMedium - prologSecondaryText.width truncationMode: TruncationMode.Fade textFormat: Text.StyledText + visible: prologSecondaryText.width < ( parent.width - Theme.paddingLarge ) } } diff --git a/qml/js/functions.js b/qml/js/functions.js index b1b9735..64feea0 100644 --- a/qml/js/functions.js +++ b/qml/js/functions.js @@ -160,6 +160,7 @@ function getMessageText(message, simple, myself) { return myself ? qsTr("sent an unsupported message: %1", "myself; %1 is message type").arg(message.content['@type'].substring(7)) : qsTr("sent an unsupported message: %1", "%1 is message type").arg(message.content['@type'].substring(7)); } + function getChatPartnerStatusText(statusType, was_online) { switch(statusType) { case "userStatusEmpty": @@ -176,6 +177,18 @@ function getChatPartnerStatusText(statusType, was_online) { return qsTr("offline, was recently online"); } } + +function getSecretChatStatus(secretChatDetails) { + switch (secretChatDetails.state["@type"]) { + case "secretChatStateClosed": + return "" + qsTr("Closed!") + ""; + case "secretChatStatePending": + return qsTr("Pending acknowledgement"); + case "secretChatStateReady": + return qsTr("Ready to use"); + } +} + function getChatMemberStatusText(statusType) { // chatMemberStatusAdministrator, chatMemberStatusBanned, chatMemberStatusCreator, chatMemberStatusLeft, chatMemberStatusMember, and chatMemberStatusRestricted. switch(statusType) { diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 0c77e58..ae98723 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -36,8 +36,10 @@ Page { property bool isInitialized: false; readonly property int myUserId: tdLibWrapper.getUserInformation().id; property var chatInformation; + property var secretChatDetails; property alias chatPicture: chatPictureThumbnail.photoData property bool isPrivateChat: false; + property bool isSecretChat: false; property bool isBasicGroup: false; property bool isSuperGroup: false; property bool isChannel: false; @@ -104,11 +106,18 @@ Page { } function updateChatPartnerStatusText() { - if(chatPage.state === "selectMessages") { + if (chatPage.state === "selectMessages") { return } var statusText = Functions.getChatPartnerStatusText(chatPartnerInformation.status['@type'], chatPartnerInformation.status.was_online); - if(statusText) { + if (chatPage.secretChatDetails) { + if (statusText) { + statusText += " - "; + } + statusText += Functions.getSecretChatStatus(chatPage.secretChatDetails); + } + + if (statusText) { chatStatusText.text = statusText; } } @@ -138,12 +147,16 @@ Page { chatView.currentIndex = -1; chatView.lastReadSentIndex = 0; var chatType = chatInformation.type['@type']; - isPrivateChat = ( chatType === "chatTypePrivate" ); + isPrivateChat = ( chatType === "chatTypePrivate"|| chatType === "chatTypeSecret" ); + isSecretChat = chatType === "chatTypeSecret"; isBasicGroup = ( chatType === "chatTypeBasicGroup" ); isSuperGroup = ( chatType === "chatTypeSupergroup" ); if (isPrivateChat) { chatPartnerInformation = tdLibWrapper.getUserInformation(chatInformation.type.user_id); updateChatPartnerStatusText(); + if (isSecretChat) { + tdLibWrapper.getSecretChat(chatInformation.type.secret_chat_id); + } } else if (isBasicGroup) { chatGroupInformation = tdLibWrapper.getBasicGroup(chatInformation.type.basic_group_id); @@ -410,6 +423,20 @@ Page { pinnedMessageItem.pinnedMessage = message; } } + onSecretChatReceived: { + if (secretChatId === chatInformation.type.secret_chat_id.toString()) { + Debug.log("[ChatPage] Received detailed information about this secret chat"); + chatPage.secretChatDetails = secretChat; + updateChatPartnerStatusText(); + } + } + onSecretChatUpdated: { + if (secretChatId === chatInformation.type.secret_chat_id.toString()) { + Debug.log("[ChatPage] Detailed information about this secret chat was updated"); + chatPage.secretChatDetails = secretChat; + updateChatPartnerStatusText(); + } + } } Connections { @@ -604,23 +631,49 @@ Page { anchors.horizontalCenter: parent.horizontalCenter spacing: Theme.paddingMedium - ProfileThumbnail { - id: chatPictureThumbnail - replacementStringHint: chatNameText.text + Item { width: chatOverviewItem.height height: chatOverviewItem.height anchors.bottom: parent.bottom anchors.bottomMargin: chatPage.isPortrait ? Theme.paddingMedium : Theme.paddingSmall - // Setting it directly may cause an stale state for the thumbnail in case the chat page - // was previously loaded with a picture and now it doesn't have one. Instead setting it - // when the ChatModel indicates a change. This also avoids flickering when the page is loaded... - Connections { - target: chatModel - onSmallPhotoChanged: { - chatPictureThumbnail.photoData = chatModel.smallPhoto; + ProfileThumbnail { + id: chatPictureThumbnail + replacementStringHint: chatNameText.text + width: parent.height + height: parent.height + + // Setting it directly may cause an stale state for the thumbnail in case the chat page + // was previously loaded with a picture and now it doesn't have one. Instead setting it + // when the ChatModel indicates a change. This also avoids flickering when the page is loaded... + Connections { + target: chatModel + onSmallPhotoChanged: { + chatPictureThumbnail.photoData = chatModel.smallPhoto; + } } } + + Rectangle { + id: chatSecretBackground + color: Theme.overlayBackgroundColor + width: chatPage.isPortrait ? Theme.fontSizeLarge : Theme.fontSizeMedium + height: width + anchors.left: parent.left + anchors.bottom: parent.bottom + radius: parent.width / 2 + visible: chatPage.isSecretChat + } + + Image { + id: chatSecretImage + source: "image://theme/icon-s-secure" + width: chatPage.isPortrait ? Theme.fontSizeSmall : Theme.fontSizeExtraSmall + height: width + anchors.centerIn: chatSecretBackground + visible: chatPage.isSecretChat + } + } Item { diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 44f6912..b0e45f6 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -166,7 +166,7 @@ Page { Item { id: privateChatItem height: parent.height - width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + width: parent.width / 2 // - ( Theme.horizontalPageMargin / 2 ) anchors.left: parent.left anchors.top: parent.top @@ -218,7 +218,7 @@ Page { wrapMode: Text.Wrap elide: Text.ElideRight textFormat: Text.StyledText - text: qsTr("Transport-encrypted, stored in Telegram Cloud, sharable across devices") + text: qsTr("Transport-encrypted, uses Telegram Cloud, sharable across devices") } } @@ -241,7 +241,7 @@ Page { Item { id: secretChatItem height: parent.height - width: parent.width / 2 + ( Theme.horizontalPageMargin / 2 ) + width: parent.width / 2 //+ ( Theme.horizontalPageMargin / 2 ) anchors.left: privateChatItem.right anchors.top: parent.top @@ -301,7 +301,7 @@ Page { MouseArea { anchors.fill: parent onClicked: { - console.log("SECRET CHAT!"); + tdLibWrapper.createNewSecretChat(display.id); } onPressed: { secretChatHighlightBackground.visible = true; @@ -344,7 +344,7 @@ Page { InfoLabel { id: loadingLabel - text: qsTr("Loading contacs...") + text: qsTr("Loading contacts...") } BusyIndicator { diff --git a/src/fernschreiberutils.cpp b/src/fernschreiberutils.cpp index 26a7e93..2bb8ec7 100644 --- a/src/fernschreiberutils.cpp +++ b/src/fernschreiberutils.cpp @@ -10,6 +10,10 @@ FernschreiberUtils::FernschreiberUtils(QObject *parent) : QObject(parent) QString FernschreiberUtils::getMessageShortText(const QVariantMap &messageContent, const bool &myself) { + if (messageContent.isEmpty()) { + return QString(); + } + QString contentType = messageContent.value("@type").toString(); if (contentType == "messageText") { diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index b15230c..a4ce0f9 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -126,6 +126,8 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren handlers.insert("users", &TDLibReceiver::processUsers); handlers.insert("error", &TDLibReceiver::processError); handlers.insert("ok", &TDLibReceiver::nop); + handlers.insert("secretChat", &TDLibReceiver::processSecretChat); + handlers.insert("updateSecretChat", &TDLibReceiver::processUpdateSecretChat); } void TDLibReceiver::setActive(bool active) @@ -523,3 +525,15 @@ void TDLibReceiver::processError(const QVariantMap &receivedInformation) void TDLibReceiver::nop(const QVariantMap &) { } + +void TDLibReceiver::processSecretChat(const QVariantMap &receivedInformation) +{ + LOG("Received a secret chat"); + emit secretChat(receivedInformation.value(ID).toString(), receivedInformation); +} + +void TDLibReceiver::processUpdateSecretChat(const QVariantMap &receivedInformation) +{ + LOG("A secret chat was updated"); + emit secretChatUpdated(receivedInformation.value(ID).toString(), receivedInformation); +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index 48b04af..25ec0ed 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -85,7 +85,8 @@ signals: void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId); void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); void errorReceived(const int code, const QString &message); - + void secretChat(const QString &secretChatId, const QVariantMap &secretChat); + void secretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); private: typedef void (TDLibReceiver::*Handler)(const QVariantMap &); @@ -145,6 +146,8 @@ private: void processUsers(const QVariantMap &receivedInformation); void processError(const QVariantMap &receivedInformation); void nop(const QVariantMap &receivedInformation); + void processSecretChat(const QVariantMap &receivedInformation); + void processUpdateSecretChat(const QVariantMap &receivedInformation); }; #endif // TDLIBRECEIVER_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index bf94d2b..380d3dc 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -94,6 +94,8 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(messagesDeleted(QString, QVariantList)), this, SIGNAL(messagesDeleted(QString, QVariantList))); connect(this->tdLibReceiver, SIGNAL(chats(QVariantMap)), this, SIGNAL(chatsReceived(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chat(QVariantMap)), this, SLOT(handleChatReceived(QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChat(QString, QVariantMap)), this, SIGNAL(secretChatReceived(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SIGNAL(secretChatUpdated(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(recentStickersUpdated(QVariantList)), this, SIGNAL(recentStickersUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickers(QVariantList)), this, SIGNAL(stickersReceived(QVariantList))); connect(this->tdLibReceiver, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SIGNAL(installedStickerSetsUpdated(QVariantList))); @@ -809,6 +811,15 @@ void TDLibWrapper::getContacts() this->sendRequest(requestObject); } +void TDLibWrapper::getSecretChat(const QString &secretChatId) +{ + LOG("Getting detailed information about secret chat" << secretChatId); + QVariantMap requestObject; + requestObject.insert(_TYPE, "getSecretChat"); + requestObject.insert("secret_chat_id", secretChatId); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 8bc0f9b..c081771 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -164,6 +164,7 @@ public: Q_INVOKABLE void joinChatByInviteLink(const QString &inviteLink); Q_INVOKABLE void getDeepLinkInfo(const QString &link); Q_INVOKABLE void getContacts(); + Q_INVOKABLE void getSecretChat(const QString &secretChatId); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); @@ -207,6 +208,8 @@ signals: void messagesDeleted(const QString &chatId, const QVariantList &messageIds); void chatsReceived(const QVariantMap &chats); void chatReceived(const QVariantMap &chat); + void secretChatReceived(const QString &secretChatId, const QVariantMap &secretChat); + void secretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); void recentStickersUpdated(const QVariantList &stickerIds); void stickersReceived(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index c67fcf4..9710208 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -260,6 +260,10 @@ Mark all messages as read Nachrichten als gelesen markieren + + No message in this chat. + Keine Nachricht in diesem Chat + ChatPage @@ -894,35 +898,35 @@ NewChatPage Your Contacts - + Ihre Kontakte You don't have any contacts. - - - - Loading contacs... - + Sie haben keine Kontakte Private Chat - + Privater Chat - Transport-encrypted, stored in Telegram Cloud, sharable across devices - + Transport-encrypted, uses Telegram Cloud, sharable across devices + Transportverschlüsselt, nutzt Telegram-Cloud, teilbar zwischen Geräten Secret Chat - + Geheimer Chat End-to-end-encrypted, accessible on this device only - + Ende-zu-Ende-verschlüsselt, nur auf diesem Gerät zugreifbar Search a contact - + Suchen Sie einen Kontakt + + + Loading contacts... + Lade Kontakte... @@ -979,7 +983,7 @@ New Chat - + Neuer Chat @@ -1643,5 +1647,17 @@ You are already a member of this chat. Sie sind bereits Mitglied dieses Chats. + + Closed! + Geschlossen! + + + Pending acknowledgement + Ausstehende Bestätigung + + + Ready to use + Einsatzbereit + diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 5b7749b..29bbd41 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -260,6 +260,10 @@ Mark all messages as read Mark all messages as read + + No message in this chat. + + ChatPage @@ -900,18 +904,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -924,6 +920,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1643,5 +1647,17 @@ You are already a member of this chat. You are already a member of this chat. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index b23e74d..f6fd6cf 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -257,6 +257,10 @@ Mark all messages as read Marcar todos como leídos + + No message in this chat. + + ChatPage @@ -890,18 +894,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -914,6 +910,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1624,5 +1628,17 @@ You are already a member of this chat. Ya eres miembro de este grupo. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 73f0a08..f06607a 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -260,6 +260,10 @@ Mark all messages as read Merkitse kaikki viestit luetuiksi + + No message in this chat. + + ChatPage @@ -901,18 +905,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -925,6 +921,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1644,5 +1648,17 @@ You are already a member of this chat. Olet jo tämän ryhmän jäsen. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index a1641b9..422a567 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -257,6 +257,10 @@ Mark all messages as read + + No message in this chat. + + ChatPage @@ -890,18 +894,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -914,6 +910,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1624,5 +1628,17 @@ You are already a member of this chat. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index e48ce94..d1a1de1 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -260,6 +260,10 @@ Mark all messages as read Segna tutti i messaggi come già letti + + No message in this chat. + + ChatPage @@ -900,18 +904,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -924,6 +920,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1643,5 +1647,17 @@ You are already a member of this chat. Sei già membro di questa chat. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 14d2e88..04c15c9 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -263,6 +263,10 @@ Mark all messages as read Zaznacz wszystkie wiadomości jako przeczytane + + No message in this chat. + + ChatPage @@ -910,18 +914,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -934,6 +930,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1662,5 +1666,17 @@ You are already a member of this chat. Jesteś już członkiem tego czatu. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 80bbaaf..381659b 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -263,6 +263,10 @@ Mark all messages as read Отметить все сообщения как прочитанные + + No message in this chat. + + ChatPage @@ -910,18 +914,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -934,6 +930,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1662,5 +1666,17 @@ You are already a member of this chat. Вы уже в этом чате. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 430859d..010b92a 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -260,6 +260,10 @@ Mark all messages as read Markera alla meddelanden som lästa + + No message in this chat. + + ChatPage @@ -900,18 +904,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -924,6 +920,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1643,5 +1647,17 @@ You are already a member of this chat. Du är redan medlem i den här chatten. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index c14d458..37cf62c 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -257,6 +257,10 @@ Mark all messages as read 标记全部消息为已读 + + No message in this chat. + + ChatPage @@ -890,18 +894,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -914,6 +910,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1624,5 +1628,17 @@ You are already a member of this chat. 你已是此对话成员。 + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 5b7749b..29bbd41 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -260,6 +260,10 @@ Mark all messages as read Mark all messages as read + + No message in this chat. + + ChatPage @@ -900,18 +904,10 @@ You don't have any contacts. - - Loading contacs... - - Private Chat - - Transport-encrypted, stored in Telegram Cloud, sharable across devices - - Secret Chat @@ -924,6 +920,14 @@ Search a contact + + Loading contacts... + + + + Transport-encrypted, uses Telegram Cloud, sharable across devices + + NotificationManager @@ -1643,5 +1647,17 @@ You are already a member of this chat. You are already a member of this chat. + + Closed! + + + + Pending acknowledgement + + + + Ready to use + + From 3b8d284b2ba495ecd55cbc07ed1ae7ead19282c4 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Wed, 25 Nov 2020 22:09:47 +0100 Subject: [PATCH 09/17] Handle secret chat state for chat list --- src/chatlistmodel.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++ src/chatlistmodel.h | 2 ++ src/tdlibreceiver.cpp | 7 ++-- src/tdlibwrapper.cpp | 33 ++++++++++++++--- src/tdlibwrapper.h | 13 +++++++ 5 files changed, 132 insertions(+), 6 deletions(-) diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 4a48045..72f3f70 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -64,6 +64,7 @@ public: RoleLastMessageText, RoleLastMessageStatus, RoleChatMemberStatus, + RoleSecretChatState, RoleIsChannel }; @@ -86,6 +87,7 @@ public: bool updateLastReadInboxMessageId(qlonglong messageId); QVector updateLastMessage(const QVariantMap &message); QVector updateGroup(const TDLibWrapper::Group *group); + QVector updateSecretChat(const QVariantMap &secretChatDetails); public: QVariantMap chatData; @@ -94,6 +96,7 @@ public: qlonglong groupId; TDLibWrapper::ChatType chatType; TDLibWrapper::ChatMemberStatus memberStatus; + TDLibWrapper::SecretChatState secretChatState; QVariantMap userInformation; }; @@ -103,6 +106,7 @@ ChatListModel::ChatData::ChatData(const QVariantMap &data, const QVariantMap &us order(data.value(ORDER).toLongLong()), groupId(0), memberStatus(TDLibWrapper::ChatMemberStatusUnknown), + secretChatState(TDLibWrapper::SecretChatStateUnknown), userInformation(userInfo) { const QVariantMap type(data.value(TYPE).toMap()); @@ -227,7 +231,11 @@ bool ChatListModel::ChatData::isHidden() const break; case TDLibWrapper::ChatTypeUnknown: case TDLibWrapper::ChatTypePrivate: + break; case TDLibWrapper::ChatTypeSecret: + if (secretChatState == TDLibWrapper::SecretChatStateClosed) { + return true; + } break; } return false; @@ -288,6 +296,18 @@ QVector ChatListModel::ChatData::updateGroup(const TDLibWrapper::Group *gro return changedRoles; } +QVector ChatListModel::ChatData::updateSecretChat(const QVariantMap &secretChatDetails) +{ + QVector changedRoles; + + TDLibWrapper::SecretChatState newSecretChatState = TDLibWrapper::secretChatStateFromString(secretChatDetails.value("state").toMap().value(_TYPE).toString()); + if (newSecretChatState != secretChatState) { + secretChatState = newSecretChatState; + changedRoles.append(RoleSecretChatState); + } + return changedRoles; +} + ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false) { this->tdLibWrapper = tdLibWrapper; @@ -302,6 +322,8 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false connect(tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString, QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString, QVariantMap))); connect(tdLibWrapper, SIGNAL(superGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); connect(tdLibWrapper, SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); + connect(tdLibWrapper, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); + connect(tdLibWrapper, SIGNAL(secretChatReceived(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); // Don't start the timer until we have at least one chat relativeTimeRefreshTimer = new QTimer(this); @@ -332,6 +354,7 @@ QHash ChatListModel::roleNames() const roles.insert(ChatData::RoleLastMessageText, "last_message_text"); roles.insert(ChatData::RoleLastMessageStatus, "last_message_status"); roles.insert(ChatData::RoleChatMemberStatus, "chat_member_status"); + roles.insert(ChatData::RoleSecretChatState, "secret_chat_state"); roles.insert(ChatData::RoleIsChannel, "is_channel"); return roles; } @@ -359,6 +382,7 @@ QVariant ChatListModel::data(const QModelIndex &index, int role) const case ChatData::RoleLastMessageDate: return data->senderMessageDate(); case ChatData::RoleLastMessageStatus: return data->senderMessageStatus(); case ChatData::RoleChatMemberStatus: return data->memberStatus; + case ChatData::RoleSecretChatState: return data->secretChatState; case ChatData::RoleIsChannel: return data->isChannel(); } } @@ -492,6 +516,50 @@ void ChatListModel::updateChatVisibility(const TDLibWrapper::Group *group) } } +void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetails) +{ + LOG("Updating secret chat visibility" << secretChatDetails.value(ID)); + // See if any group has been removed from from view + for (int i = 0; i < chatList.size(); i++) { + ChatData *chat = chatList.at(i); + if (chat->chatType != TDLibWrapper::ChatTypeSecret) { + continue; + } + const QVector changedRoles(chat->updateSecretChat(secretChatDetails)); + if (chat->isHidden() && !showHiddenChats) { + LOG("Hiding chat" << chat->chatId << "at" << i); + beginRemoveRows(QModelIndex(), i, i); + chatList.removeAt(i); + // Update damaged part of the map + const int n = chatList.size(); + for (int pos = i; pos < n; pos++) { + chatIndexMap.insert(chatList.at(pos)->chatId, pos); + } + i--; + hiddenChats.insert(chat->chatId, chat); + endRemoveRows(); + } else if (!changedRoles.isEmpty()) { + const QModelIndex modelIndex(index(i)); + emit dataChanged(modelIndex, modelIndex, changedRoles); + } + } + + // And see if any group been added to the view + const QList hiddenChatList = hiddenChats.values(); + const int n = hiddenChatList.size(); + for (int j = 0; j < n; j++) { + ChatData *chat = hiddenChatList.at(j); + if (chat->chatType != TDLibWrapper::ChatTypeSecret) { + continue; + } + chat->updateSecretChat(secretChatDetails); + if (!chat->isHidden() || showHiddenChats) { + hiddenChats.remove(chat->chatId); + addVisibleChat(chat); + } + } +} + bool ChatListModel::showAllChats() const { return showHiddenChats; @@ -509,10 +577,19 @@ void ChatListModel::setShowAllChats(bool showAll) void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &chatToBeAdded) { ChatData *chat = new ChatData(chatToBeAdded, tdLibWrapper->getUserInformation()); + const TDLibWrapper::Group *group = tdLibWrapper->getGroup(chat->groupId); if (group) { chat->updateGroup(group); } + + if (chat->chatType == TDLibWrapper::ChatTypeSecret) { + QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value("secret_chat_id").toString()); + if (!secretChatDetails.isEmpty()) { + chat->updateSecretChat(secretChatDetails); + } + } + if (chat->isHidden()) { LOG("Hidden chat" << chat->chatId); hiddenChats.insert(chat->chatId, chat); @@ -707,6 +784,12 @@ void ChatListModel::handleGroupUpdated(qlonglong groupId) updateChatVisibility(tdLibWrapper->getGroup(groupId)); } +void ChatListModel::handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat) +{ + LOG("Updating visibility of secret chat " << secretChatId); + updateSecretChatVisibility(secretChat); +} + void ChatListModel::handleRelativeTimeRefreshTimer() { LOG("Refreshing timestamps"); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index e802fb1..470ea99 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -54,6 +54,7 @@ private slots: void handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message); void handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings); void handleGroupUpdated(qlonglong groupId); + void handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); void handleRelativeTimeRefreshTimer(); signals: @@ -65,6 +66,7 @@ private: class ChatData; void addVisibleChat(ChatData *chat); void updateChatVisibility(const TDLibWrapper::Group *group); + void updateSecretChatVisibility(const QVariantMap secretChatDetails); int updateChatOrder(int chatIndex); private: diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index a4ce0f9..6e17b36 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -44,6 +44,7 @@ namespace { const QString UNREAD_COUNT("unread_count"); const QString LAST_READ_INBOX_MESSAGE_ID("last_read_inbox_message_id"); const QString LAST_READ_OUTBOX_MESSAGE_ID("last_read_outbox_message_id"); + const QString SECRET_CHAT("secret_chat"); const QString TYPE("@type"); const QString EXTRA("@extra"); @@ -529,11 +530,13 @@ void TDLibReceiver::nop(const QVariantMap &) void TDLibReceiver::processSecretChat(const QVariantMap &receivedInformation) { LOG("Received a secret chat"); - emit secretChat(receivedInformation.value(ID).toString(), receivedInformation); + QVariantMap discoveredSecretChat = receivedInformation.value(SECRET_CHAT).toMap(); + emit secretChat(discoveredSecretChat.value(ID).toString(), discoveredSecretChat); } void TDLibReceiver::processUpdateSecretChat(const QVariantMap &receivedInformation) { LOG("A secret chat was updated"); - emit secretChatUpdated(receivedInformation.value(ID).toString(), receivedInformation); + QVariantMap updatedSecretChat = receivedInformation.value(SECRET_CHAT).toMap(); + emit secretChatUpdated(updatedSecretChat.value(ID).toString(), updatedSecretChat); } diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 380d3dc..d9dd99c 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -94,8 +94,8 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(messagesDeleted(QString, QVariantList)), this, SIGNAL(messagesDeleted(QString, QVariantList))); connect(this->tdLibReceiver, SIGNAL(chats(QVariantMap)), this, SIGNAL(chatsReceived(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chat(QVariantMap)), this, SLOT(handleChatReceived(QVariantMap))); - connect(this->tdLibReceiver, SIGNAL(secretChat(QString, QVariantMap)), this, SIGNAL(secretChatReceived(QString, QVariantMap))); - connect(this->tdLibReceiver, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SIGNAL(secretChatUpdated(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChat(QString, QVariantMap)), this, SLOT(handleSecretChatReceived(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(recentStickersUpdated(QVariantList)), this, SIGNAL(recentStickersUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickers(QVariantList)), this, SIGNAL(stickersReceived(QVariantList))); connect(this->tdLibReceiver, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SIGNAL(installedStickerSetsUpdated(QVariantList))); @@ -891,6 +891,11 @@ QVariantMap TDLibWrapper::getChat(const QString &chatId) return this->chats.value(chatId).toMap(); } +QVariantMap TDLibWrapper::getSecretChatFromCache(const QString &secretChatId) +{ + return this->secretChats.value(secretChatId).toMap(); +} + QString TDLibWrapper::getOptionString(const QString &optionName) { return this->options.value(optionName).toString(); @@ -1160,6 +1165,18 @@ void TDLibWrapper::handleOpenWithChanged() } } +void TDLibWrapper::handleSecretChatReceived(const QString &secretChatId, const QVariantMap &secretChat) +{ + this->secretChats.insert(secretChatId, secretChat); + emit secretChatReceived(secretChatId, secretChat); +} + +void TDLibWrapper::handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat) +{ + this->secretChats.insert(secretChatId, secretChat); + emit secretChatUpdated(secretChatId, secretChat); +} + void TDLibWrapper::setInitialParameters() { LOG("Sending initial parameters to TD Lib"); @@ -1172,7 +1189,7 @@ void TDLibWrapper::setInitialParameters() initialParameters.insert("use_file_database", true); initialParameters.insert("use_chat_info_database", true); initialParameters.insert("use_message_database", true); - initialParameters.insert("use_secret_chats", false); + initialParameters.insert("use_secret_chats", true); initialParameters.insert("system_language_code", QLocale::system().name()); QSettings hardwareSettings("/etc/hw-release", QSettings::NativeFormat); initialParameters.insert("device_model", hardwareSettings.value("NAME", "Unknown Mobile Device").toString()); @@ -1306,7 +1323,15 @@ TDLibWrapper::ChatMemberStatus TDLibWrapper::chatMemberStatusFromString(const QS (status == QStringLiteral("chatMemberStatusAdministrator")) ? ChatMemberStatusAdministrator : (status == QStringLiteral("chatMemberStatusRestricted")) ? ChatMemberStatusRestricted : (status == QStringLiteral("chatMemberStatusBanned")) ? ChatMemberStatusBanned : - ChatMemberStatusUnknown; + ChatMemberStatusUnknown; +} + +TDLibWrapper::SecretChatState TDLibWrapper::secretChatStateFromString(const QString &state) +{ + return (state == QStringLiteral("secretChatStateClosed")) ? SecretChatStateClosed : + (state == QStringLiteral("secretChatStatePending")) ? SecretChatStatePending : + (state == QStringLiteral("secretChatStateReady")) ? SecretChatStateReady : + SecretChatStateUnknown; } TDLibWrapper::ChatMemberStatus TDLibWrapper::Group::chatMemberStatus() const diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index c081771..23ff18f 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -79,6 +79,14 @@ public: }; Q_ENUM(ChatMemberStatus) + enum SecretChatState { + SecretChatStateUnknown, + SecretChatStateClosed, + SecretChatStatePending, + SecretChatStateReady, + }; + Q_ENUM(SecretChatState) + class Group { public: Group(qlonglong id) : groupId(id) { } @@ -101,6 +109,7 @@ public: Q_INVOKABLE QVariantMap getBasicGroup(qlonglong groupId) const; Q_INVOKABLE QVariantMap getSuperGroup(qlonglong groupId) const; Q_INVOKABLE QVariantMap getChat(const QString &chatId); + Q_INVOKABLE QVariantMap getSecretChatFromCache(const QString &secretChatId); Q_INVOKABLE QString getOptionString(const QString &optionName); Q_INVOKABLE void copyFileToDownloads(const QString &filePath); Q_INVOKABLE void openFileOnDevice(const QString &filePath); @@ -175,6 +184,7 @@ public: const Group* getGroup(qlonglong groupId) const; static ChatType chatTypeFromString(const QString &type); static ChatMemberStatus chatMemberStatusFromString(const QString &status); + static SecretChatState secretChatStateFromString(const QString &state); signals: void versionDetected(const QString &version); @@ -248,6 +258,8 @@ public slots: void handleStickerSets(const QVariantList &stickerSets); void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList); void handleOpenWithChanged(); + void handleSecretChatReceived(const QString &secretChatId, const QVariantMap &secretChat); + void handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); private: void setInitialParameters(); @@ -270,6 +282,7 @@ private: QVariantMap allUsers; QVariantMap allUserNames; QVariantMap chats; + QVariantMap secretChats; QVariantMap unreadMessageInformation; QVariantMap unreadChatInformation; QHash basicGroups; From 90f7535fdace98295c4abc6c34c69a81422e5fc8 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 26 Nov 2020 00:25:15 +0100 Subject: [PATCH 10/17] Secret chats begin to work properly... --- qml/components/ChatListViewItem.qml | 2 +- qml/js/functions.js | 2 +- qml/pages/ChatPage.qml | 34 +++++++++------ qml/pages/NewChatPage.qml | 2 +- src/chatlistmodel.cpp | 25 +++-------- src/tdlibreceiver.cpp | 3 +- translations/harbour-fernschreiber-de.ts | 12 +++--- translations/harbour-fernschreiber-en.ts | 48 ++++++++++----------- translations/harbour-fernschreiber-es.ts | 16 +++---- translations/harbour-fernschreiber-fi.ts | 16 +++---- translations/harbour-fernschreiber-hu.ts | 16 +++---- translations/harbour-fernschreiber-it.ts | 16 +++---- translations/harbour-fernschreiber-pl.ts | 16 +++---- translations/harbour-fernschreiber-ru.ts | 16 +++---- translations/harbour-fernschreiber-sv.ts | 16 +++---- translations/harbour-fernschreiber-zh_CN.ts | 16 +++---- translations/harbour-fernschreiber.ts | 16 +++---- 17 files changed, 134 insertions(+), 138 deletions(-) diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml index 4644efc..67ec0c4 100644 --- a/qml/components/ChatListViewItem.qml +++ b/qml/components/ChatListViewItem.qml @@ -13,7 +13,7 @@ PhotoTextsListItem { property int ownUserId // chat title - primaryText.text: title ? Emoji.emojify(title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown") + primaryText.text: title ? Emoji.emojify((listItem.isSecret ? "🔒 " : "" ) + title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown") // 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") ) : "" ) // last message diff --git a/qml/js/functions.js b/qml/js/functions.js index 64feea0..13e8a04 100644 --- a/qml/js/functions.js +++ b/qml/js/functions.js @@ -185,7 +185,7 @@ function getSecretChatStatus(secretChatDetails) { case "secretChatStatePending": return qsTr("Pending acknowledgement"); case "secretChatStateReady": - return qsTr("Ready to use"); + return ""; } } diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index ae98723..d7e885c 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -40,6 +40,7 @@ Page { property alias chatPicture: chatPictureThumbnail.photoData property bool isPrivateChat: false; property bool isSecretChat: false; + property bool isSecretChatReady: false; property bool isBasicGroup: false; property bool isSuperGroup: false; property bool isChannel: false; @@ -48,7 +49,7 @@ Page { property int chatOnlineMemberCount: 0; property var emojiProposals; property bool iterativeInitialization: false; - readonly property bool userIsMember: (isPrivateChat && chatInformation["@type"]) || // should be optimized + readonly property bool userIsMember: ((isPrivateChat || isSecretChat) && chatInformation["@type"]) || // should be optimized (isBasicGroup || isSuperGroup) && ( (chatGroupInformation.status["@type"] === "chatMemberStatusMember") || (chatGroupInformation.status["@type"] === "chatMemberStatusAdministrator") @@ -111,10 +112,13 @@ Page { } var statusText = Functions.getChatPartnerStatusText(chatPartnerInformation.status['@type'], chatPartnerInformation.status.was_online); if (chatPage.secretChatDetails) { - if (statusText) { + var secretChatStatus = Functions.getSecretChatStatus(chatPage.secretChatDetails); + if (statusText && secretChatStatus) { statusText += " - "; } - statusText += Functions.getSecretChatStatus(chatPage.secretChatDetails); + if (secretChatStatus) { + statusText += secretChatStatus; + } } if (statusText) { @@ -147,11 +151,11 @@ Page { chatView.currentIndex = -1; chatView.lastReadSentIndex = 0; var chatType = chatInformation.type['@type']; - isPrivateChat = ( chatType === "chatTypePrivate"|| chatType === "chatTypeSecret" ); + isPrivateChat = chatType === "chatTypePrivate"; isSecretChat = chatType === "chatTypeSecret"; isBasicGroup = ( chatType === "chatTypeBasicGroup" ); isSuperGroup = ( chatType === "chatTypeSupergroup" ); - if (isPrivateChat) { + if (isPrivateChat || isSecretChat) { chatPartnerInformation = tdLibWrapper.getUserInformation(chatInformation.type.user_id); updateChatPartnerStatusText(); if (isSecretChat) { @@ -304,11 +308,12 @@ Page { || groupStatusType === "chatMemberStatusAdministrator" || groupStatusType === "chatMemberStatusCreator" || (groupStatusType === "chatMemberStatusRestricted" && groupStatus.permissions[privilege]) + || (chatPage.isSecretChat && chatPage.isSecretChatReady) } function canPinMessages() { Debug.log("Can we pin messages?"); - if (chatPage.isPrivateChat) { - Debug.log("Private Chat: No!"); + if (chatPage.isPrivateChat || chatPage.isSecretChat) { + Debug.log("Private/Secret Chat: No!"); return false; } if (chatPage.chatGroupInformation.status["@type"] === "chatMemberStatusCreator") { @@ -380,7 +385,7 @@ Page { Connections { target: tdLibWrapper onUserUpdated: { - if (isPrivateChat && chatPartnerInformation.id.toString() === userId ) { + if ((isPrivateChat || isSecretChat) && chatPartnerInformation.id.toString() === userId ) { chatPartnerInformation = userInformation; updateChatPartnerStatusText(); } @@ -428,6 +433,7 @@ Page { Debug.log("[ChatPage] Received detailed information about this secret chat"); chatPage.secretChatDetails = secretChat; updateChatPartnerStatusText(); + chatPage.isSecretChatReady = chatPage.secretChatDetails.state["@type"] === "secretChatStateReady"; } } onSecretChatUpdated: { @@ -435,6 +441,7 @@ Page { Debug.log("[ChatPage] Detailed information about this secret chat was updated"); chatPage.secretChatDetails = secretChat; updateChatPartnerStatusText(); + chatPage.isSecretChatReady = chatPage.secretChatDetails.state["@type"] === "secretChatStateReady"; } } } @@ -534,7 +541,7 @@ Page { Timer { id: chatContactTimeUpdater interval: 60000 - running: isPrivateChat + running: isPrivateChat || isSecretChat repeat: true onTriggered: { updateChatPartnerStatusText(); @@ -686,7 +693,7 @@ Page { id: chatNameText width: Math.min(implicitWidth, parent.width) anchors.right: parent.right - text: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, font.pixelSize) : qsTr("Unknown") + text: chatInformation.title !== "" ? Emoji.emojify((chatPage.isSecretChat ? "🔒 " : "" ) + chatInformation.title, font.pixelSize) : qsTr("Unknown") textFormat: Text.StyledText font.pixelSize: chatPage.isPortrait ? Theme.fontSizeLarge : Theme.fontSizeMedium font.family: Theme.fontFamilyHeading @@ -908,8 +915,9 @@ Page { VerticalScrollDecorator {} ViewPlaceholder { + id: chatViewPlaceholder enabled: chatView.count === 0 - text: qsTr("This chat is empty.") + text: (chatPage.isSecretChat && !chatPage.isSecretChatReady) ? qsTr("This secret chat is not yet ready. Your chat partner needs to go online first.") : qsTr("This chat is empty.") } } @@ -1103,7 +1111,7 @@ Page { } } IconButton { - visible: !chatPage.isPrivateChat && chatPage.hasSendPrivilege("can_send_polls") + visible: !(chatPage.isPrivateChat || chatPage.isSecretChat) && chatPage.hasSendPrivilege("can_send_polls") icon.source: "image://theme/icon-m-question" onClicked: { pageStack.push(Qt.resolvedUrl("../pages/PollCreationPage.qml"), { "chatId" : chatInformation.id, groupName: chatInformation.title}); @@ -1383,7 +1391,7 @@ Page { verticalCenter: parent.verticalCenter } visible: selectedMessages.every(function(message){ - return message.can_be_forwarded + return message.can_be_forwarded && !chatPage.isSecretChat }) width: visible ? Theme.itemSizeMedium : 0 icon.source: "image://theme/icon-m-forward" diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index b0e45f6..3f7380a 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -69,7 +69,7 @@ Page { SearchField { id: contactsSearchField width: parent.width - placeholderText: qsTr("Search a contact") + placeholderText: qsTr("Search a contact...") active: !newChatPage.isLoading onTextChanged: contactsModel.applyFilter(text); EnterKey.iconSource: "image://theme/icon-m-enter-close" diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 72f3f70..9141ae9 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -46,6 +46,7 @@ namespace { const QString IS_CHANNEL("is_channel"); const QString PINNED_MESSAGE_ID("pinned_message_id"); const QString _TYPE("@type"); + const QString SECRET_CHAT_ID("secret_chat_id"); } class ChatListModel::ChatData @@ -518,13 +519,16 @@ void ChatListModel::updateChatVisibility(const TDLibWrapper::Group *group) void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetails) { - LOG("Updating secret chat visibility" << secretChatDetails.value(ID)); - // See if any group has been removed from from view + LOG("Updating secret chat visibility" << secretChatDetails.value(ID).toString()); + // See if any secret chat has been closed for (int i = 0; i < chatList.size(); i++) { ChatData *chat = chatList.at(i); if (chat->chatType != TDLibWrapper::ChatTypeSecret) { continue; } + if (chat->chatData.value(TYPE).toMap().value(SECRET_CHAT_ID).toString() != secretChatDetails.value(ID).toString()) { + continue; + } const QVector changedRoles(chat->updateSecretChat(secretChatDetails)); if (chat->isHidden() && !showHiddenChats) { LOG("Hiding chat" << chat->chatId << "at" << i); @@ -543,21 +547,6 @@ void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetai emit dataChanged(modelIndex, modelIndex, changedRoles); } } - - // And see if any group been added to the view - const QList hiddenChatList = hiddenChats.values(); - const int n = hiddenChatList.size(); - for (int j = 0; j < n; j++) { - ChatData *chat = hiddenChatList.at(j); - if (chat->chatType != TDLibWrapper::ChatTypeSecret) { - continue; - } - chat->updateSecretChat(secretChatDetails); - if (!chat->isHidden() || showHiddenChats) { - hiddenChats.remove(chat->chatId); - addVisibleChat(chat); - } - } } bool ChatListModel::showAllChats() const @@ -584,7 +573,7 @@ void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &cha } if (chat->chatType == TDLibWrapper::ChatTypeSecret) { - QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value("secret_chat_id").toString()); + QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value(SECRET_CHAT_ID).toString()); if (!secretChatDetails.isEmpty()) { chat->updateSecretChat(secretChatDetails); } diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 6e17b36..41c4b51 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -530,8 +530,7 @@ void TDLibReceiver::nop(const QVariantMap &) void TDLibReceiver::processSecretChat(const QVariantMap &receivedInformation) { LOG("Received a secret chat"); - QVariantMap discoveredSecretChat = receivedInformation.value(SECRET_CHAT).toMap(); - emit secretChat(discoveredSecretChat.value(ID).toString(), discoveredSecretChat); + emit secretChat(receivedInformation.value(ID).toString(), receivedInformation); } void TDLibReceiver::processUpdateSecretChat(const QVariantMap &receivedInformation) diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index 9710208..a944b45 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -379,6 +379,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + Dieser geheime Chat ist noch nicht bereit. Ihr Chatpartner muss erst noch online gehen. + ChatSelectionPage @@ -921,8 +925,8 @@ Ende-zu-Ende-verschlüsselt, nur auf diesem Gerät zugreifbar - Search a contact - Suchen Sie einen Kontakt + Search a contact... + Einen Kontakt suchen... Loading contacts... @@ -1655,9 +1659,5 @@ Pending acknowledgement Ausstehende Bestätigung - - Ready to use - Einsatzbereit - diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 29bbd41..e1ba79b 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -262,7 +262,7 @@ No message in this chat. - + No message in this chat. @@ -379,6 +379,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + This secret chat is not yet ready. Your chat partner needs to go online first. + ChatSelectionPage @@ -873,7 +877,7 @@ Pin Message - + Pin Message @@ -887,46 +891,46 @@ MessageOverlayFlickable You - You + You This message was forwarded. Original author: %1 - + This message was forwarded. Original author: %1 NewChatPage Your Contacts - + Your Contacts You don't have any contacts. - + You don't have any contacts. Private Chat - + Private Chat Secret Chat - + Secret Chat End-to-end-encrypted, accessible on this device only - + End-to-end-encrypted, accessible on this device only - Search a contact - + Search a contact... + Search a contact... Loading contacts... - + Loading contacts... Transport-encrypted, uses Telegram Cloud, sharable across devices - + Transport-encrypted, uses Telegram Cloud, sharable across devices @@ -983,22 +987,22 @@ New Chat - + New Chat PinnedMessageItem You - You + You Pinned Message - + Pinned Message Message unpinned - + Message unpinned @@ -1243,7 +1247,7 @@ Notification turns on the display - + Notification turns on the display @@ -1649,15 +1653,11 @@ Closed! - + Closed! Pending acknowledgement - - - - Ready to use - + Pending acknowledgement diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index f6fd6cf..770a726 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -369,6 +369,10 @@ %1 en línea + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -906,10 +910,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -918,6 +918,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1636,9 +1640,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index f06607a..9d03ed7 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -379,6 +379,10 @@ %1 paikalla + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -917,10 +921,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -929,6 +929,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1656,9 +1660,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 422a567..b34e31d 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -369,6 +369,10 @@ + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -906,10 +910,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -918,6 +918,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1636,9 +1640,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index d1a1de1..af11ec6 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -379,6 +379,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -916,10 +920,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -928,6 +928,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1655,9 +1659,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 04c15c9..8de180d 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -389,6 +389,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -926,10 +930,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -938,6 +938,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1674,9 +1678,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 381659b..19e46da 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -389,6 +389,10 @@ + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -926,10 +930,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -938,6 +938,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1674,9 +1678,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 010b92a..b262811 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -379,6 +379,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -916,10 +920,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -928,6 +928,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1655,9 +1659,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 37cf62c..13c7f0e 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -369,6 +369,10 @@ %1 位在线 + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -906,10 +910,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -918,6 +918,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1636,9 +1640,5 @@ Pending acknowledgement - - Ready to use - - diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 29bbd41..5be7bdd 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -379,6 +379,10 @@ %1 online + + This secret chat is not yet ready. Your chat partner needs to go online first. + + ChatSelectionPage @@ -916,10 +920,6 @@ End-to-end-encrypted, accessible on this device only - - Search a contact - - Loading contacts... @@ -928,6 +928,10 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices + + Search a contact... + + NotificationManager @@ -1655,9 +1659,5 @@ Pending acknowledgement - - Ready to use - - From b31072ff82af7e9b28209a265e95ec33c405fed6 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 26 Nov 2020 14:44:02 +0100 Subject: [PATCH 11/17] Realign emojis to avoid strange text alignment --- qml/js/twemoji.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qml/js/twemoji.js b/qml/js/twemoji.js index 67f677c..054bb37 100644 --- a/qml/js/twemoji.js +++ b/qml/js/twemoji.js @@ -54,13 +54,13 @@ function emojify(str, emojiSize) { basePath, iconId, '.svg', - '" align="middle" width="', - emojiSize, + '" align="bottom" width="', + Math.round(emojiSize * 6 / 5 ), '" height="', - emojiSize, + Math.round(emojiSize * 6 / 5 ), '"/>' ); } return ret.replace(ampersandRe, "&"); }); -} \ No newline at end of file +} From 7ab58d3730569c4ba36ff9ac2d1ad95b31f8f1e8 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 26 Nov 2020 16:11:12 +0100 Subject: [PATCH 12/17] Add option to close a secret chat --- qml/pages/ChatPage.qml | 13 +++++++++++++ src/tdlibwrapper.cpp | 9 +++++++++ src/tdlibwrapper.h | 1 + translations/harbour-fernschreiber-de.ts | 8 ++++++++ translations/harbour-fernschreiber-en.ts | 8 ++++++++ translations/harbour-fernschreiber-es.ts | 8 ++++++++ translations/harbour-fernschreiber-fi.ts | 8 ++++++++ translations/harbour-fernschreiber-hu.ts | 8 ++++++++ translations/harbour-fernschreiber-it.ts | 8 ++++++++ translations/harbour-fernschreiber-pl.ts | 8 ++++++++ translations/harbour-fernschreiber-ru.ts | 8 ++++++++ translations/harbour-fernschreiber-sv.ts | 8 ++++++++ translations/harbour-fernschreiber-zh_CN.ts | 8 ++++++++ translations/harbour-fernschreiber.ts | 8 ++++++++ 14 files changed, 111 insertions(+) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index d7e885c..244baa8 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -577,6 +577,19 @@ Page { PullDownMenu { visible: chatInformation.id !== chatPage.myUserId && !stickerPickerLoader.active && !messageOverlayLoader.active + MenuItem { + id: closeSecretChatMenuItem + visible: chatPage.isSecretChat && chatPage.secretChatDetails.state["@type"] !== "secretChatStateClosed" + onClicked: { + var remorse = Remorse.popupAction(appWindow, qsTr("Closing chat"), (function(secretChatId) { + return function() { + tdLibWrapper.closeSecretChat(secretChatId); + }; + }(chatPage.secretChatDetails.id))) + } + text: qsTr("Close Chat") + } + MenuItem { id: joinLeaveChatMenuItem visible: (chatPage.isSuperGroup || chatPage.isBasicGroup) && chatGroupInformation && chatGroupInformation.status["@type"] !== "chatMemberStatusBanned" diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index dfc1dde..b774f1c 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -833,6 +833,15 @@ void TDLibWrapper::getSecretChat(const QString &secretChatId) this->sendRequest(requestObject); } +void TDLibWrapper::closeSecretChat(const QString &secretChatId) +{ + LOG("Closing secret chat" << secretChatId); + QVariantMap requestObject; + requestObject.insert(_TYPE, "closeSecretChat"); + requestObject.insert("secret_chat_id", secretChatId); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 426d5c6..734a186 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -175,6 +175,7 @@ public: Q_INVOKABLE void getDeepLinkInfo(const QString &link); Q_INVOKABLE void getContacts(); Q_INVOKABLE void getSecretChat(const QString &secretChatId); + Q_INVOKABLE void closeSecretChat(const QString &secretChatId); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index f567081..efdc353 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. Dieser geheime Chat ist noch nicht bereit. Ihr Chatpartner muss erst noch online gehen. + + Closing chat + Schließe Chat + + + Close Chat + Chat schließen + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index d9aad5d..a94105c 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + Closing chat + + + Close Chat + Close Chat + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 8949356..2e23061 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -373,6 +373,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index 22ace3a..cd35d38 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index 0fbcec8..c9e57e5 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -373,6 +373,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index 3cabd13..e05cadc 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index ff4c3c6..0a52400 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -393,6 +393,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 74c69a9..a169b83 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -393,6 +393,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 2724b54..e69719b 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 0bf69e7..6b95c79 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -373,6 +373,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 5d67afc..4437afa 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -383,6 +383,14 @@ This secret chat is not yet ready. Your chat partner needs to go online first. + + Closing chat + + + + Close Chat + + ChatSelectionPage From deacb7f0ea33b0a2e10aabaf780353e84f5934f9 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 26 Nov 2020 22:18:51 +0100 Subject: [PATCH 13/17] Synchronize contacts with Telegram --- qml/pages/NewChatPage.qml | 48 +++++++++++++++++---- src/chatlistmodel.cpp | 22 ++++++++++ src/chatlistmodel.h | 1 + src/contactsmodel.cpp | 44 ++++++++++++++++++- src/contactsmodel.h | 10 +++++ src/tdlibreceiver.cpp | 7 +++ src/tdlibreceiver.h | 3 ++ src/tdlibwrapper.cpp | 10 +++++ src/tdlibwrapper.h | 2 + translations/harbour-fernschreiber-de.ts | 12 ++++++ translations/harbour-fernschreiber-en.ts | 12 ++++++ translations/harbour-fernschreiber-es.ts | 12 ++++++ translations/harbour-fernschreiber-fi.ts | 12 ++++++ translations/harbour-fernschreiber-hu.ts | 12 ++++++ translations/harbour-fernschreiber-it.ts | 12 ++++++ translations/harbour-fernschreiber-pl.ts | 12 ++++++ translations/harbour-fernschreiber-ru.ts | 12 ++++++ translations/harbour-fernschreiber-sv.ts | 12 ++++++ translations/harbour-fernschreiber-zh_CN.ts | 12 ++++++ translations/harbour-fernschreiber.ts | 12 ++++++ 20 files changed, 270 insertions(+), 9 deletions(-) diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 3f7380a..8586a5b 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -28,24 +28,56 @@ Page { property bool isLoading: true; - onStatusChanged: { - if (status === PageStatus.Active) { - contactsModel.hydrateContacts(); - contactsListView.model = contactsModel; - newChatPage.isLoading = false; - } - } - function resetFocus() { contactsSearchField.focus = false; newChatPage.focus = true; } + function reloadContacts() { + contactsModel.hydrateContacts(); + contactsListView.model = contactsModel; + newChatPage.isLoading = false; + } + + + onStatusChanged: { + if (status === PageStatus.Active) { + reloadContacts(); + } + } + + Connections { + target: contactsModel + onErrorSynchronizingContacts: { + reloadContacts(); + appNotification.show(qsTr("Could not synchronize your contacts with Telegram.")); + } + } + + Connections { + target: tdLibWrapper + onContactsImported: { + reloadContacts(); + appNotification.show(qsTr("Contacts successfully synchronized with Telegram.")); + } + } + SilicaFlickable { id: newChatContainer contentHeight: newChatPage.height anchors.fill: parent + PullDownMenu { + visible: contactsModel.canSynchronizeContacts() + MenuItem { + onClicked: { + newChatPage.isLoading = true; + contactsModel.synchronizeContacts(); + } + text: qsTr("Synchronize Contacts with Telegram") + } + } + Column { id: newChatPageColumn width: newChatPage.width diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index 9141ae9..fda507f 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -325,6 +325,7 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false connect(tdLibWrapper, SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); connect(tdLibWrapper, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); connect(tdLibWrapper, SIGNAL(secretChatReceived(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); + connect(tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString))); // Don't start the timer until we have at least one chat relativeTimeRefreshTimer = new QTimer(this); @@ -779,6 +780,27 @@ void ChatListModel::handleSecretChatUpdated(const QString &secretChatId, const Q updateSecretChatVisibility(secretChat); } +void ChatListModel::handleChatTitleUpdated(const QString &chatId, const QString &title) +{ + qlonglong chatIdLongLong = chatId.toLongLong(); + if (chatIndexMap.contains(chatIdLongLong)) { + LOG("Updating title for" << chatId); + const int chatIndex = chatIndexMap.value(chatIdLongLong); + ChatData *chat = chatList.at(chatIndex); + chat->chatData.insert(TITLE, title); + QVector changedRoles; + changedRoles.append(ChatData::RoleTitle); + const QModelIndex modelIndex(index(chatIndex)); + emit dataChanged(modelIndex, modelIndex, changedRoles); + } else { + ChatData *chat = hiddenChats.value(chatId.toLongLong()); + if (chat) { + LOG("Updating title for hidden chat" << chatId); + chat->chatData.insert(TITLE, title); + } + } +} + void ChatListModel::handleRelativeTimeRefreshTimer() { LOG("Refreshing timestamps"); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index 470ea99..8624e8d 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -55,6 +55,7 @@ private slots: void handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings); void handleGroupUpdated(qlonglong groupId); void handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void handleChatTitleUpdated(const QString &chatId, const QString &title); void handleRelativeTimeRefreshTimer(); signals: diff --git a/src/contactsmodel.cpp b/src/contactsmodel.cpp index 2f0f08e..6901c1b 100644 --- a/src/contactsmodel.cpp +++ b/src/contactsmodel.cpp @@ -38,8 +38,17 @@ ContactsModel::ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent) : QAbstractListModel(parent) { this->tdLibWrapper = tdLibWrapper; - connect(this->tdLibWrapper, SIGNAL(usersReceived(QString, QVariantList, int)), this, SLOT(handleUsersReceived(QString, QVariantList, int))); + + this->deviceContactsDatabase = QSqlDatabase::addDatabase("QSQLITE", "contacts"); + this->deviceContactsDatabase.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.local/share/system/Contacts/qtcontacts-sqlite/contacts.db"); + if (this->deviceContactsDatabase.open()) { + LOG("Device's contacts database successfully opened :)"); + this->canUseDeviceContacts = true; + } else { + LOG("Error opening device's contacts database :("); + this->canUseDeviceContacts = false; + } } int ContactsModel::rowCount(const QModelIndex &) const @@ -143,3 +152,36 @@ void ContactsModel::applyFilter(const QString &filter) } endResetModel(); } + +void ContactsModel::synchronizeContacts() +{ + LOG("Synchronizing device contacts"); + QVariantList deviceContacts; + QSqlQuery databaseQuery(this->deviceContactsDatabase); + databaseQuery.prepare("select distinct c.contactId, c.firstName, c.lastName, n.phoneNumber from Contacts as c inner join PhoneNumbers as n on c.contactId = n.contactId where n.phoneNumber is not null and ( c.firstName is not null or c.lastName is not null );"); + if (databaseQuery.exec()) { + LOG("Device contacts successfully selected from database!"); + while (databaseQuery.next()) { + QVariantMap singleContact; + singleContact.insert("first_name", databaseQuery.value(1).toString()); + singleContact.insert("last_name", databaseQuery.value(2).toString()); + singleContact.insert("phone_number", databaseQuery.value(3).toString()); + deviceContacts.append(singleContact); + LOG("Found contact" << singleContact.value("first_name").toString() << singleContact.value("last_name").toString() << singleContact.value("phone_number").toString()); + } + if (!deviceContacts.isEmpty()) { + LOG("Importing found contacts" << deviceContacts.size()); + this->tdLibWrapper->importContacts(deviceContacts); + } + emit contactsSynchronized(); + } else { + LOG("Error selecting contacts from database!"); + emit errorSynchronizingContacts(); + } + +} + +bool ContactsModel::canSynchronizeContacts() +{ + return this->canUseDeviceContacts; +} diff --git a/src/contactsmodel.h b/src/contactsmodel.h index 0500358..e517ac3 100644 --- a/src/contactsmodel.h +++ b/src/contactsmodel.h @@ -22,6 +22,8 @@ #include #include +#include +#include #include "tdlibwrapper.h" @@ -36,6 +38,12 @@ public: Q_INVOKABLE void hydrateContacts(); Q_INVOKABLE void applyFilter(const QString &filter); + Q_INVOKABLE void synchronizeContacts(); + Q_INVOKABLE bool canSynchronizeContacts(); + +signals: + void contactsSynchronized(); + void errorSynchronizingContacts(); public slots: void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); @@ -46,6 +54,8 @@ private: QVariantList filteredContacts; QList contactIds; QString filter; + QSqlDatabase deviceContactsDatabase; + bool canUseDeviceContacts; }; #endif // CONTACTSMODEL_H diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index 41c4b51..f3d272d 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -129,6 +129,7 @@ TDLibReceiver::TDLibReceiver(void *tdLibClient, QObject *parent) : QThread(paren handlers.insert("ok", &TDLibReceiver::nop); handlers.insert("secretChat", &TDLibReceiver::processSecretChat); handlers.insert("updateSecretChat", &TDLibReceiver::processUpdateSecretChat); + handlers.insert("importedContacts", &TDLibReceiver::processImportedContacts); } void TDLibReceiver::setActive(bool active) @@ -539,3 +540,9 @@ void TDLibReceiver::processUpdateSecretChat(const QVariantMap &receivedInformati QVariantMap updatedSecretChat = receivedInformation.value(SECRET_CHAT).toMap(); emit secretChatUpdated(updatedSecretChat.value(ID).toString(), updatedSecretChat); } + +void TDLibReceiver::processImportedContacts(const QVariantMap &receivedInformation) +{ + LOG("Contacts were imported"); + emit contactsImported(receivedInformation.value("importer_count").toList(), receivedInformation.value("user_ids").toList()); +} diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index 25ec0ed..b56bc0c 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -87,6 +87,8 @@ signals: void errorReceived(const int code, const QString &message); void secretChat(const QString &secretChatId, const QVariantMap &secretChat); void secretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); + private: typedef void (TDLibReceiver::*Handler)(const QVariantMap &); @@ -148,6 +150,7 @@ private: void nop(const QVariantMap &receivedInformation); void processSecretChat(const QVariantMap &receivedInformation); void processUpdateSecretChat(const QVariantMap &receivedInformation); + void processImportedContacts(const QVariantMap &receivedInformation); }; #endif // TDLIBRECEIVER_H diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index b774f1c..d9becc3 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -116,6 +116,7 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong)), this, SIGNAL(chatPinnedMessageUpdated(qlonglong, qlonglong))); connect(this->tdLibReceiver, SIGNAL(usersReceived(QString, QVariantList, int)), this, SIGNAL(usersReceived(QString, QVariantList, int))); connect(this->tdLibReceiver, SIGNAL(errorReceived(int, QString)), this, SIGNAL(errorReceived(int, QString))); + connect(this->tdLibReceiver, SIGNAL(contactsImported(QVariantList, QVariantList)), this, SIGNAL(contactsImported(QVariantList, QVariantList))); connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList))); @@ -842,6 +843,15 @@ void TDLibWrapper::closeSecretChat(const QString &secretChatId) this->sendRequest(requestObject); } +void TDLibWrapper::importContacts(const QVariantList &contacts) +{ + LOG("Importing contacts"); + QVariantMap requestObject; + requestObject.insert(_TYPE, "importContacts"); + requestObject.insert("contacts", contacts); + this->sendRequest(requestObject); +} + void TDLibWrapper::searchEmoji(const QString &queryString) { LOG("Searching emoji" << queryString); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 734a186..3857880 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -176,6 +176,7 @@ public: Q_INVOKABLE void getContacts(); Q_INVOKABLE void getSecretChat(const QString &secretChatId); Q_INVOKABLE void closeSecretChat(const QString &secretChatId); + Q_INVOKABLE void importContacts(const QVariantList &contacts); // Others (candidates for extraction ;)) Q_INVOKABLE void searchEmoji(const QString &queryString); @@ -242,6 +243,7 @@ signals: void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId); void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); void errorReceived(const int code, const QString &message); + void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); public slots: void handleVersionDetected(const QString &version); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index efdc353..dfbf44f 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -944,6 +944,18 @@ Loading contacts... Lade Kontakte... + + Synchronize Contacts with Telegram + Kontakte mit Telegram synchronisieren + + + Could not synchronize your contacts with Telegram. + Konnte Ihre Kontakte nicht mit Telegram synchronisieren. + + + Contacts successfully synchronized with Telegram. + Die Kontakte wurden erfolgreich mit Telegram synchronisiert. + NotificationManager diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index a94105c..1171c25 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -944,6 +944,18 @@ Transport-encrypted, uses Telegram Cloud, sharable across devices Transport-encrypted, uses Telegram Cloud, sharable across devices + + Synchronize Contacts with Telegram + Synchronize Contacts with Telegram + + + Could not synchronize your contacts with Telegram. + Could not synchronize your contacts with Telegram. + + + Contacts successfully synchronized with Telegram. + Contacts successfully synchronized with Telegram. + NotificationManager diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index 2e23061..b54f71f 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -934,6 +934,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index cd35d38..a17f1df 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -945,6 +945,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index c9e57e5..6e56e19 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -934,6 +934,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index e05cadc..391f78b 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -944,6 +944,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 0a52400..2abc25f 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -954,6 +954,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index a169b83..2dbb3ae 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -954,6 +954,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index e69719b..317b980 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -944,6 +944,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 6b95c79..e1d9b75 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -934,6 +934,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index 4437afa..db98832 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -944,6 +944,18 @@ Search a contact... + + Synchronize Contacts with Telegram + + + + Could not synchronize your contacts with Telegram. + + + + Contacts successfully synchronized with Telegram. + + NotificationManager From 4cf35641c50bb0810dd7bf615cff69073a69d7c2 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Fri, 27 Nov 2020 19:42:39 +0100 Subject: [PATCH 14/17] Secret chat identifer switches to qlonglong --- qml/pages/ChatPage.qml | 4 ++-- src/chatlistmodel.cpp | 10 +++++----- src/chatlistmodel.h | 2 +- src/tdlibreceiver.cpp | 4 ++-- src/tdlibreceiver.h | 4 ++-- src/tdlibwrapper.cpp | 16 ++++++++-------- src/tdlibwrapper.h | 16 ++++++++-------- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 244baa8..25ece74 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -429,7 +429,7 @@ Page { } } onSecretChatReceived: { - if (secretChatId === chatInformation.type.secret_chat_id.toString()) { + if (secretChatId.toString() === chatInformation.type.secret_chat_id.toString()) { Debug.log("[ChatPage] Received detailed information about this secret chat"); chatPage.secretChatDetails = secretChat; updateChatPartnerStatusText(); @@ -437,7 +437,7 @@ Page { } } onSecretChatUpdated: { - if (secretChatId === chatInformation.type.secret_chat_id.toString()) { + if (secretChatId.toString() === chatInformation.type.secret_chat_id.toString()) { Debug.log("[ChatPage] Detailed information about this secret chat was updated"); chatPage.secretChatDetails = secretChat; updateChatPartnerStatusText(); diff --git a/src/chatlistmodel.cpp b/src/chatlistmodel.cpp index fda507f..6c2044f 100644 --- a/src/chatlistmodel.cpp +++ b/src/chatlistmodel.cpp @@ -323,8 +323,8 @@ ChatListModel::ChatListModel(TDLibWrapper *tdLibWrapper) : showHiddenChats(false connect(tdLibWrapper, SIGNAL(chatNotificationSettingsUpdated(QString, QVariantMap)), this, SLOT(handleChatNotificationSettingsUpdated(QString, QVariantMap))); connect(tdLibWrapper, SIGNAL(superGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); connect(tdLibWrapper, SIGNAL(basicGroupUpdated(qlonglong)), this, SLOT(handleGroupUpdated(qlonglong))); - connect(tdLibWrapper, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); - connect(tdLibWrapper, SIGNAL(secretChatReceived(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); + connect(tdLibWrapper, SIGNAL(secretChatUpdated(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap))); + connect(tdLibWrapper, SIGNAL(secretChatReceived(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap))); connect(tdLibWrapper, SIGNAL(chatTitleUpdated(QString, QString)), this, SLOT(handleChatTitleUpdated(QString, QString))); // Don't start the timer until we have at least one chat @@ -527,7 +527,7 @@ void ChatListModel::updateSecretChatVisibility(const QVariantMap secretChatDetai if (chat->chatType != TDLibWrapper::ChatTypeSecret) { continue; } - if (chat->chatData.value(TYPE).toMap().value(SECRET_CHAT_ID).toString() != secretChatDetails.value(ID).toString()) { + if (chat->chatData.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong() != secretChatDetails.value(ID).toLongLong()) { continue; } const QVector changedRoles(chat->updateSecretChat(secretChatDetails)); @@ -574,7 +574,7 @@ void ChatListModel::handleChatDiscovered(const QString &, const QVariantMap &cha } if (chat->chatType == TDLibWrapper::ChatTypeSecret) { - QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value(SECRET_CHAT_ID).toString()); + QVariantMap secretChatDetails = tdLibWrapper->getSecretChatFromCache(chatToBeAdded.value(TYPE).toMap().value(SECRET_CHAT_ID).toLongLong()); if (!secretChatDetails.isEmpty()) { chat->updateSecretChat(secretChatDetails); } @@ -774,7 +774,7 @@ void ChatListModel::handleGroupUpdated(qlonglong groupId) updateChatVisibility(tdLibWrapper->getGroup(groupId)); } -void ChatListModel::handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat) +void ChatListModel::handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat) { LOG("Updating visibility of secret chat " << secretChatId); updateSecretChatVisibility(secretChat); diff --git a/src/chatlistmodel.h b/src/chatlistmodel.h index 8624e8d..44e93d3 100644 --- a/src/chatlistmodel.h +++ b/src/chatlistmodel.h @@ -54,7 +54,7 @@ private slots: void handleMessageSendSucceeded(const QString &messageId, const QString &oldMessageId, const QVariantMap &message); void handleChatNotificationSettingsUpdated(const QString &chatId, const QVariantMap &chatNotificationSettings); void handleGroupUpdated(qlonglong groupId); - void handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void handleChatTitleUpdated(const QString &chatId, const QString &title); void handleRelativeTimeRefreshTimer(); diff --git a/src/tdlibreceiver.cpp b/src/tdlibreceiver.cpp index f3d272d..f06a664 100644 --- a/src/tdlibreceiver.cpp +++ b/src/tdlibreceiver.cpp @@ -531,14 +531,14 @@ void TDLibReceiver::nop(const QVariantMap &) void TDLibReceiver::processSecretChat(const QVariantMap &receivedInformation) { LOG("Received a secret chat"); - emit secretChat(receivedInformation.value(ID).toString(), receivedInformation); + emit secretChat(receivedInformation.value(ID).toLongLong(), receivedInformation); } void TDLibReceiver::processUpdateSecretChat(const QVariantMap &receivedInformation) { LOG("A secret chat was updated"); QVariantMap updatedSecretChat = receivedInformation.value(SECRET_CHAT).toMap(); - emit secretChatUpdated(updatedSecretChat.value(ID).toString(), updatedSecretChat); + emit secretChatUpdated(updatedSecretChat.value(ID).toLongLong(), updatedSecretChat); } void TDLibReceiver::processImportedContacts(const QVariantMap &receivedInformation) diff --git a/src/tdlibreceiver.h b/src/tdlibreceiver.h index b56bc0c..8fd7ca8 100644 --- a/src/tdlibreceiver.h +++ b/src/tdlibreceiver.h @@ -85,8 +85,8 @@ signals: void chatPinnedMessageUpdated(qlonglong chatId, qlonglong pinnedMessageId); void usersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); void errorReceived(const int code, const QString &message); - void secretChat(const QString &secretChatId, const QVariantMap &secretChat); - void secretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void secretChat(qlonglong secretChatId, const QVariantMap &secretChat); + void secretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void contactsImported(const QVariantList &importerCount, const QVariantList &userIds); private: diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index d9becc3..5e96d91 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -95,8 +95,8 @@ TDLibWrapper::TDLibWrapper(AppSettings *appSettings, MceInterface *mceInterface, connect(this->tdLibReceiver, SIGNAL(messagesDeleted(QString, QVariantList)), this, SIGNAL(messagesDeleted(QString, QVariantList))); connect(this->tdLibReceiver, SIGNAL(chats(QVariantMap)), this, SIGNAL(chatsReceived(QVariantMap))); connect(this->tdLibReceiver, SIGNAL(chat(QVariantMap)), this, SLOT(handleChatReceived(QVariantMap))); - connect(this->tdLibReceiver, SIGNAL(secretChat(QString, QVariantMap)), this, SLOT(handleSecretChatReceived(QString, QVariantMap))); - connect(this->tdLibReceiver, SIGNAL(secretChatUpdated(QString, QVariantMap)), this, SLOT(handleSecretChatUpdated(QString, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChat(qlonglong, QVariantMap)), this, SLOT(handleSecretChatReceived(qlonglong, QVariantMap))); + connect(this->tdLibReceiver, SIGNAL(secretChatUpdated(qlonglong, QVariantMap)), this, SLOT(handleSecretChatUpdated(qlonglong, QVariantMap))); connect(this->tdLibReceiver, SIGNAL(recentStickersUpdated(QVariantList)), this, SIGNAL(recentStickersUpdated(QVariantList))); connect(this->tdLibReceiver, SIGNAL(stickers(QVariantList)), this, SIGNAL(stickersReceived(QVariantList))); connect(this->tdLibReceiver, SIGNAL(installedStickerSetsUpdated(QVariantList)), this, SIGNAL(installedStickerSetsUpdated(QVariantList))); @@ -825,7 +825,7 @@ void TDLibWrapper::getContacts() this->sendRequest(requestObject); } -void TDLibWrapper::getSecretChat(const QString &secretChatId) +void TDLibWrapper::getSecretChat(qlonglong secretChatId) { LOG("Getting detailed information about secret chat" << secretChatId); QVariantMap requestObject; @@ -834,7 +834,7 @@ void TDLibWrapper::getSecretChat(const QString &secretChatId) this->sendRequest(requestObject); } -void TDLibWrapper::closeSecretChat(const QString &secretChatId) +void TDLibWrapper::closeSecretChat(qlonglong secretChatId) { LOG("Closing secret chat" << secretChatId); QVariantMap requestObject; @@ -923,9 +923,9 @@ QVariantMap TDLibWrapper::getChat(const QString &chatId) return this->chats.value(chatId).toMap(); } -QVariantMap TDLibWrapper::getSecretChatFromCache(const QString &secretChatId) +QVariantMap TDLibWrapper::getSecretChatFromCache(qlonglong secretChatId) { - return this->secretChats.value(secretChatId).toMap(); + return this->secretChats.value(secretChatId); } QString TDLibWrapper::getOptionString(const QString &optionName) @@ -1197,13 +1197,13 @@ void TDLibWrapper::handleOpenWithChanged() } } -void TDLibWrapper::handleSecretChatReceived(const QString &secretChatId, const QVariantMap &secretChat) +void TDLibWrapper::handleSecretChatReceived(qlonglong secretChatId, const QVariantMap &secretChat) { this->secretChats.insert(secretChatId, secretChat); emit secretChatReceived(secretChatId, secretChat); } -void TDLibWrapper::handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat) +void TDLibWrapper::handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat) { this->secretChats.insert(secretChatId, secretChat); emit secretChatUpdated(secretChatId, secretChat); diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 3857880..ca7858c 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -109,7 +109,7 @@ public: Q_INVOKABLE QVariantMap getBasicGroup(qlonglong groupId) const; Q_INVOKABLE QVariantMap getSuperGroup(qlonglong groupId) const; Q_INVOKABLE QVariantMap getChat(const QString &chatId); - Q_INVOKABLE QVariantMap getSecretChatFromCache(const QString &secretChatId); + Q_INVOKABLE QVariantMap getSecretChatFromCache(qlonglong secretChatId); Q_INVOKABLE QString getOptionString(const QString &optionName); Q_INVOKABLE void copyFileToDownloads(const QString &filePath); Q_INVOKABLE void openFileOnDevice(const QString &filePath); @@ -174,8 +174,8 @@ public: Q_INVOKABLE void joinChatByInviteLink(const QString &inviteLink); Q_INVOKABLE void getDeepLinkInfo(const QString &link); Q_INVOKABLE void getContacts(); - Q_INVOKABLE void getSecretChat(const QString &secretChatId); - Q_INVOKABLE void closeSecretChat(const QString &secretChatId); + Q_INVOKABLE void getSecretChat(qlonglong secretChatId); + Q_INVOKABLE void closeSecretChat(qlonglong secretChatId); Q_INVOKABLE void importContacts(const QVariantList &contacts); // Others (candidates for extraction ;)) @@ -221,8 +221,8 @@ signals: void messagesDeleted(const QString &chatId, const QVariantList &messageIds); void chatsReceived(const QVariantMap &chats); void chatReceived(const QVariantMap &chat); - void secretChatReceived(const QString &secretChatId, const QVariantMap &secretChat); - void secretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void secretChatReceived(qlonglong secretChatId, const QVariantMap &secretChat); + void secretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void recentStickersUpdated(const QVariantList &stickerIds); void stickersReceived(const QVariantList &stickers); void installedStickerSetsUpdated(const QVariantList &stickerSetIds); @@ -262,8 +262,8 @@ public slots: void handleStickerSets(const QVariantList &stickerSets); void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList); void handleOpenWithChanged(); - void handleSecretChatReceived(const QString &secretChatId, const QVariantMap &secretChat); - void handleSecretChatUpdated(const QString &secretChatId, const QVariantMap &secretChat); + void handleSecretChatReceived(qlonglong secretChatId, const QVariantMap &secretChat); + void handleSecretChatUpdated(qlonglong secretChatId, const QVariantMap &secretChat); void handleStorageOptimizerChanged(); private: @@ -288,7 +288,7 @@ private: QVariantMap allUsers; QVariantMap allUserNames; QVariantMap chats; - QVariantMap secretChats; + QMap secretChats; QVariantMap unreadMessageInformation; QVariantMap unreadChatInformation; QHash basicGroups; From 48b5e14335942b96198e22f637548cc43005cc5c Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sat, 28 Nov 2020 19:11:51 +0100 Subject: [PATCH 15/17] Improvements after feedback round --- qml/components/ChatListViewItem.qml | 2 +- qml/components/PhotoTextsListItem.qml | 5 +- .../ChatInformationPageContent.qml | 55 ++++++++-------- .../ChatInformationTabItemMembersGroups.qml | 12 ++-- .../ChatInformationTabView.qml | 6 +- qml/pages/ChatInformationPage.qml | 3 +- qml/pages/ChatPage.qml | 4 +- qml/pages/NewChatPage.qml | 44 +++++++------ src/contactsmodel.cpp | 63 +++++++++---------- src/contactsmodel.h | 25 +++++--- src/harbour-fernschreiber.cpp | 5 ++ translations/harbour-fernschreiber-de.ts | 4 ++ translations/harbour-fernschreiber-en.ts | 4 ++ translations/harbour-fernschreiber-es.ts | 4 ++ translations/harbour-fernschreiber-fi.ts | 4 ++ translations/harbour-fernschreiber-hu.ts | 4 ++ translations/harbour-fernschreiber-it.ts | 4 ++ translations/harbour-fernschreiber-pl.ts | 4 ++ translations/harbour-fernschreiber-ru.ts | 4 ++ translations/harbour-fernschreiber-sv.ts | 4 ++ translations/harbour-fernschreiber-zh_CN.ts | 4 ++ translations/harbour-fernschreiber.ts | 4 ++ 22 files changed, 161 insertions(+), 107 deletions(-) diff --git a/qml/components/ChatListViewItem.qml b/qml/components/ChatListViewItem.qml index 67ec0c4..4644efc 100644 --- a/qml/components/ChatListViewItem.qml +++ b/qml/components/ChatListViewItem.qml @@ -13,7 +13,7 @@ PhotoTextsListItem { property int ownUserId // 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 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 diff --git a/qml/components/PhotoTextsListItem.qml b/qml/components/PhotoTextsListItem.qml index ceb8c39..c91fd1e 100644 --- a/qml/components/PhotoTextsListItem.qml +++ b/qml/components/PhotoTextsListItem.qml @@ -11,7 +11,7 @@ ListItem { property alias secondaryText: secondaryText //usually last message property alias tertiaryText: tertiaryText //usually last message date - property int unreadCount + property int unreadCount: 0 property bool isSecret: false property alias pictureThumbnail: pictureThumbnail @@ -58,14 +58,12 @@ ListItem { color: Theme.overlayBackgroundColor width: Theme.fontSizeExtraLarge height: Theme.fontSizeExtraLarge - anchors.left: parent.left anchors.bottom: parent.bottom radius: parent.width / 2 visible: chatListViewItem.isSecret } Image { - id: chatSecretImage source: "image://theme/icon-s-secure" height: Theme.fontSizeMedium width: Theme.fontSizeMedium @@ -73,7 +71,6 @@ ListItem { visible: chatListViewItem.isSecret } - Rectangle { id: chatUnreadMessagesCountBackground color: Theme.highlightBackgroundColor diff --git a/qml/components/chatInformationPage/ChatInformationPageContent.qml b/qml/components/chatInformationPage/ChatInformationPageContent.qml index f8470fb..9fbf08e 100644 --- a/qml/components/chatInformationPage/ChatInformationPageContent.qml +++ b/qml/components/chatInformationPage/ChatInformationPageContent.qml @@ -41,6 +41,15 @@ SilicaFlickable { tdLibWrapper.getUserFullInfo(chatInformationPage.chatPartnerGroupId); tdLibWrapper.getUserProfilePhotos(chatInformationPage.chatPartnerGroupId, 100, 0); 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": chatInformationPage.isBasicGroup = true; chatInformationPage.chatPartnerGroupId = chatInformation.type.basic_group_id.toString(); @@ -60,8 +69,8 @@ SilicaFlickable { chatInformationPage.isChannel = chatInformationPage.groupInformation.is_channel; break; } - Debug.log("is set up", chatInformationPage.isPrivateChat, chatInformationPage.isBasicGroup, chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId) - if(!chatInformationPage.isPrivateChat) { + Debug.log("is set up", chatInformationPage.isPrivateChat, chatInformationPage.isSecretChat, chatInformationPage.isBasicGroup, chatInformationPage.isSuperGroup, chatInformationPage.chatPartnerGroupId) + if(!(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)) { updateGroupStatusText(); } @@ -147,18 +156,18 @@ SilicaFlickable { } } onUserFullInfoReceived: { - if(chatInformationPage.isPrivateChat && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) { + if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && userFullInfo["@extra"] === chatInformationPage.chatPartnerGroupId) { chatInformationPage.chatPartnerFullInformation = userFullInfo; } } onUserFullInfoUpdated: { - if(chatInformationPage.isPrivateChat && userId === chatInformationPage.chatPartnerGroupId) { + if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && userId === chatInformationPage.chatPartnerGroupId) { chatInformationPage.chatPartnerFullInformation = userFullInfo; } } onUserProfilePhotosReceived: { - if(chatInformationPage.isPrivateChat && extra === chatInformationPage.chatPartnerGroupId) { + if((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && extra === chatInformationPage.chatPartnerGroupId) { chatInformationPage.chatPartnerProfilePhotos = photos; } } @@ -180,14 +189,10 @@ SilicaFlickable { } } - - - Component.onCompleted: {7 + Component.onCompleted: { initializePage(); } - - ListModel { id: membersList } @@ -227,13 +232,13 @@ SilicaFlickable { } text: chatInformation.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat") } - // MenuItem { //TODO Implement - // visible: !userIsMember - // onClicked: { - // tdLibWrapper.joinChat(chatInformationPage.chatInformation.id); - // } - // text: qsTr("Join Chat") - // } + MenuItem { + visible: chatInformationPage.isPrivateChat + onClicked: { + tdLibWrapper.createNewSecretChat(chatInformationPage.chatPartnerGroupId); + } + text: qsTr("New Secret Chat") + } } // header PageHeader { @@ -278,14 +283,14 @@ SilicaFlickable { active: imageContainer.hasImage asynchronous: true anchors.fill: chatPictureThumbnail - source: chatInformationPage.isPrivateChat + source: ( chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? "ChatInformationProfilePictureList.qml" : "ChatInformationProfilePicture.qml" } } 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") - description: chatInformationPage.isPrivateChat ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : "" + description: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : "" } SilicaFlickable { @@ -350,7 +355,7 @@ SilicaFlickable { ChatInformationEditArea { 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") text: chatInformationPage.chatInformation.title @@ -375,13 +380,13 @@ SilicaFlickable { } } 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.") headerText: qsTr("Info", "group or user infotext header") multiLine: true - text: (chatInformationPage.isPrivateChat ? chatInformationPage.chatPartnerFullInformation.bio : chatInformationPage.groupFullInformation.description) || "" + text: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? chatInformationPage.chatPartnerFullInformation.bio : chatInformationPage.groupFullInformation.description) || "" onSaveButtonClicked: { - if(chatInformationPage.isPrivateChat) { // own bio + if ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)) { // own bio tdLibWrapper.setBio(textValue); } else { // group info tdLibWrapper.setChatDescription(chatInformationPage.chatInformation.id, textValue); @@ -391,7 +396,7 @@ SilicaFlickable { ChatInformationTextItem { 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 } @@ -408,7 +413,7 @@ SilicaFlickable { visible: !!inviteLinkItem.text ChatInformationTextItem { id: inviteLinkItem - text: !isPrivateChat ? chatInformationPage.groupFullInformation.invite_link : "" + text: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? chatInformationPage.groupFullInformation.invite_link : "" width: parent.width - inviteLinkButton.width } IconButton { diff --git a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml index 9d9243f..9c898bb 100644 --- a/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml +++ b/qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml @@ -27,15 +27,15 @@ import "../../js/functions.js" as Functions ChatInformationTabItemBase { id: tabBase - loadingText: isPrivateChat ? qsTr("Loading common chats…", "chats you have in common with a user") : qsTr("Loading group members…") - loading: ( chatInformationPage.isSuperGroup || chatInformationPage.isPrivateChat) && !chatInformationPage.isChannel + 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.isSecretChat) && !chatInformationPage.isChannel loadingVisible: loading && membersView.count === 0 property var chatPartnerCommonGroupsIds: ([]); SilicaListView { 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 height: tabBase.height width: tabBase.width @@ -68,7 +68,7 @@ ChatInformationTabItemBase { ViewPlaceholder { y: Theme.paddingLarge 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 { pictureThumbnail { @@ -204,7 +204,7 @@ ChatInformationTabItemBase { } } onChatsReceived: {// common chats with user - if(isPrivateChat && chats["@extra"] === chatInformationPage.chatPartnerGroupId) { + if((isPrivateChat || isSecretChat) && chats["@extra"] === chatInformationPage.chatPartnerGroupId) { tabBase.chatPartnerCommonGroupsIds = chats.chat_ids; delegateModel.applyFilter(); // if we set it directly, the views start scrolling @@ -221,7 +221,7 @@ ChatInformationTabItemBase { } Component.onCompleted: { - if(chatInformationPage.isPrivateChat) { + if(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) { tdLibWrapper.getGroupsInCommon(chatInformationPage.chatPartnerGroupId, 200, 0); // we only use the first 200 } else if(chatInformationPage.isSuperGroup) { fetchMoreMembersTimer.start(); diff --git a/qml/components/chatInformationPage/ChatInformationTabView.qml b/qml/components/chatInformationPage/ChatInformationTabView.qml index 4e09e69..0c556dd 100644 --- a/qml/components/chatInformationPage/ChatInformationTabView.qml +++ b/qml/components/chatInformationPage/ChatInformationTabView.qml @@ -124,14 +124,14 @@ Item { } } Component.onCompleted: { - if(!(isPrivateChat && chatPartnerGroupId === myUserId.toString())) { + if(!((isPrivateChat || isSecretChat) && chatPartnerGroupId === myUserId.toString())) { tabModel.append({ 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" }); } - 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({ tab:"ChatInformationTabItemSettings", title: qsTr("Settings", "Button: Chat Settings"), diff --git a/qml/pages/ChatInformationPage.qml b/qml/pages/ChatInformationPage.qml index d143bd6..18f6a2a 100644 --- a/qml/pages/ChatInformationPage.qml +++ b/qml/pages/ChatInformationPage.qml @@ -34,13 +34,14 @@ Page { property int myUserId: tdLibWrapper.getUserInformation().id; property bool isPrivateChat: false + property bool isSecretChat: false property bool isBasicGroup: false property bool isSuperGroup: false property bool isChannel: false property string chatPartnerGroupId - property bool userIsMember: (isPrivateChat && chatInformation["@type"]) || // should be optimized + property bool userIsMember: ((isPrivateChat || isSecretChat ) && chatInformation["@type"]) || // should be optimized (isBasicGroup || isSuperGroup) && ( (groupInformation.status["@type"] === "chatMemberStatusMember") || (groupInformation.status["@type"] === "chatMemberStatusAdministrator") diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 9568def..4a93c02 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -429,7 +429,7 @@ Page { } } 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"); chatPage.secretChatDetails = secretChat; updateChatPartnerStatusText(); @@ -706,7 +706,7 @@ Page { id: chatNameText width: Math.min(implicitWidth, parent.width) 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 font.pixelSize: chatPage.isPortrait ? Theme.fontSizeLarge : Theme.fontSizeMedium font.family: Theme.fontFamilyHeading diff --git a/qml/pages/NewChatPage.qml b/qml/pages/NewChatPage.qml index 8586a5b..b98f5fd 100644 --- a/qml/pages/NewChatPage.qml +++ b/qml/pages/NewChatPage.qml @@ -35,7 +35,7 @@ Page { function reloadContacts() { contactsModel.hydrateContacts(); - contactsListView.model = contactsModel; + contactsListView.model = contactsProxyModel; newChatPage.isLoading = false; } @@ -46,14 +46,6 @@ Page { } } - Connections { - target: contactsModel - onErrorSynchronizingContacts: { - reloadContacts(); - appNotification.show(qsTr("Could not synchronize your contacts with Telegram.")); - } - } - Connections { target: tdLibWrapper onContactsImported: { @@ -72,7 +64,11 @@ Page { MenuItem { onClicked: { 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") } @@ -103,7 +99,11 @@ Page { width: parent.width placeholderText: qsTr("Search a contact...") active: !newChatPage.isLoading - onTextChanged: contactsModel.applyFilter(text); + + onTextChanged: { + contactsProxyModel.setFilterWildcard("*" + text + "*"); + } + EnterKey.iconSource: "image://theme/icon-m-enter-close" EnterKey.onClicked: { resetFocus(); @@ -140,15 +140,15 @@ Page { Behavior on opacity { FadeAnimation {} } pictureThumbnail { - photoData: (typeof display.profile_photo !== "undefined") ? display.profile_photo.small : {} + photoData: typeof photo_small !== "undefined" ? photo_small : {} } width: parent.width - primaryText.text: Emoji.emojify(Functions.getUserName(display), primaryText.font.pixelSize, "../js/emoji/") - prologSecondaryText.text: "@" + ( display.username !== "" ? display.username : display.id ) + primaryText.text: Emoji.emojify(title, primaryText.font.pixelSize, "../js/emoji/") + prologSecondaryText.text: "@" + ( username !== "" ? username : user_id ) tertiaryText { maximumLineCount: 1 - text: Functions.getChatPartnerStatusText(display.status["@type"], display.status.was_online); + text: Functions.getChatPartnerStatusText(user_status, user_last_online); } onClicked: { @@ -191,22 +191,20 @@ Page { Rectangle { anchors.fill: parent - opacity: 0.3 + opacity: Theme.opacityLow color: Theme.overlayBackgroundColor } Item { id: privateChatItem height: parent.height - width: parent.width / 2 // - ( Theme.horizontalPageMargin / 2 ) - anchors.left: parent.left - anchors.top: parent.top + width: parent.width / 2 Rectangle { id: privateChatHighlightBackground anchors.fill: parent color: Theme.highlightBackgroundColor - opacity: 0.5 + opacity: Theme.opacityHigh visible: false } @@ -273,7 +271,7 @@ Page { Item { id: secretChatItem height: parent.height - width: parent.width / 2 //+ ( Theme.horizontalPageMargin / 2 ) + width: parent.width / 2 anchors.left: privateChatItem.right anchors.top: parent.top @@ -281,7 +279,7 @@ Page { id: secretChatHighlightBackground anchors.fill: parent color: Theme.highlightBackgroundColor - opacity: 0.5 + opacity: Theme.opacityHigh visible: false } @@ -297,7 +295,7 @@ Page { icon.source: "image://theme/icon-m-device-lock" anchors.verticalCenter: parent.verticalCenter onClicked: { - console.log("SECRET CHAT!"); + tdLibWrapper.createNewSecretChat(display.id); } } diff --git a/src/contactsmodel.cpp b/src/contactsmodel.cpp index 6901c1b..59184f5 100644 --- a/src/contactsmodel.cpp +++ b/src/contactsmodel.cpp @@ -51,15 +51,39 @@ ContactsModel::ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent) } } +QHash ContactsModel::roleNames() const +{ + QHash 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 { - return this->filter.isEmpty() ? this->contacts.size() : this->filteredContacts.size(); + return this->contacts.size(); } QVariant ContactsModel::data(const QModelIndex &index, int role) const { - if (index.isValid() && role == Qt::DisplayRole) { - return this->filter.isEmpty() ? QVariant(contacts.value(index.row())) : QVariant(filteredContacts.value(index.row())) ; + if (index.isValid()) { + QVariantMap requestedContact = contacts.value(index.row()).toMap(); + switch (static_cast(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(); } @@ -126,34 +150,7 @@ void ContactsModel::hydrateContacts() std::sort(this->contacts.begin(), this->contacts.end(), compareUsers); } -void ContactsModel::applyFilter(const QString &filter) -{ - LOG("Applying filter:" << filter); - beginResetModel(); - this->filter = filter; - this->filteredContacts.clear(); - if (!this->filter.isEmpty()) { - QListIterator 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() +bool ContactsModel::synchronizeContacts() { LOG("Synchronizing device contacts"); QVariantList deviceContacts; @@ -173,10 +170,10 @@ void ContactsModel::synchronizeContacts() LOG("Importing found contacts" << deviceContacts.size()); this->tdLibWrapper->importContacts(deviceContacts); } - emit contactsSynchronized(); + return true; } else { LOG("Error selecting contacts from database!"); - emit errorSynchronizingContacts(); + return false; } } diff --git a/src/contactsmodel.h b/src/contactsmodel.h index e517ac3..d4af011 100644 --- a/src/contactsmodel.h +++ b/src/contactsmodel.h @@ -31,27 +31,34 @@ class ContactsModel : public QAbstractListModel { Q_OBJECT public: + + enum ContactRole { + RoleDisplay = Qt::DisplayRole, + RolePhotoSmall, + RoleTitle, + RoleUserId, + RoleUsername, + RoleUserStatus, + RoleUserLastOnline, + RoleFilter + }; + ContactsModel(TDLibWrapper *tdLibWrapper, QObject *parent = nullptr); - virtual int rowCount(const QModelIndex &) const; - virtual QVariant data(const QModelIndex &index, int role) const; + virtual QHash roleNames() const override; + virtual int rowCount(const QModelIndex &) const override; + virtual QVariant data(const QModelIndex &index, int role) const override; Q_INVOKABLE void hydrateContacts(); - Q_INVOKABLE void applyFilter(const QString &filter); - Q_INVOKABLE void synchronizeContacts(); + Q_INVOKABLE bool synchronizeContacts(); Q_INVOKABLE bool canSynchronizeContacts(); -signals: - void contactsSynchronized(); - void errorSynchronizingContacts(); - public slots: void handleUsersReceived(const QString &extra, const QVariantList &userIds, int totalUsers); private: TDLibWrapper *tdLibWrapper; QVariantList contacts; - QVariantList filteredContacts; QList contactIds; QString filter; QSqlDatabase deviceContactsDatabase; diff --git a/src/harbour-fernschreiber.cpp b/src/harbour-fernschreiber.cpp index a75f8de..e35b8fd 100644 --- a/src/harbour-fernschreiber.cpp +++ b/src/harbour-fernschreiber.cpp @@ -99,6 +99,11 @@ int main(int argc, char *argv[]) ContactsModel contactsModel(tdLibWrapper, view.data()); 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->show(); diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index ea147ad..0f97618 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -179,6 +179,10 @@ %1 online + + New Secret Chat + Neuer geheimer Chat + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-en.ts b/translations/harbour-fernschreiber-en.ts index 740b696..869df56 100644 --- a/translations/harbour-fernschreiber-en.ts +++ b/translations/harbour-fernschreiber-en.ts @@ -179,6 +179,10 @@ %1 online + + New Secret Chat + New Secret Chat + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-es.ts b/translations/harbour-fernschreiber-es.ts index cf994ed..e49dcdd 100644 --- a/translations/harbour-fernschreiber-es.ts +++ b/translations/harbour-fernschreiber-es.ts @@ -176,6 +176,10 @@ %1 en línea + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-fi.ts b/translations/harbour-fernschreiber-fi.ts index e146725..33220d9 100644 --- a/translations/harbour-fernschreiber-fi.ts +++ b/translations/harbour-fernschreiber-fi.ts @@ -179,6 +179,10 @@ %1 paikalla + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-hu.ts b/translations/harbour-fernschreiber-hu.ts index abba1af..7eccdcf 100644 --- a/translations/harbour-fernschreiber-hu.ts +++ b/translations/harbour-fernschreiber-hu.ts @@ -176,6 +176,10 @@ + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-it.ts b/translations/harbour-fernschreiber-it.ts index a407584..36fcf40 100644 --- a/translations/harbour-fernschreiber-it.ts +++ b/translations/harbour-fernschreiber-it.ts @@ -179,6 +179,10 @@ %1 online + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-pl.ts b/translations/harbour-fernschreiber-pl.ts index 56cd633..d8856f2 100644 --- a/translations/harbour-fernschreiber-pl.ts +++ b/translations/harbour-fernschreiber-pl.ts @@ -182,6 +182,10 @@ %1 online + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-ru.ts b/translations/harbour-fernschreiber-ru.ts index 5216fa3..337c6e9 100644 --- a/translations/harbour-fernschreiber-ru.ts +++ b/translations/harbour-fernschreiber-ru.ts @@ -182,6 +182,10 @@ + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-sv.ts b/translations/harbour-fernschreiber-sv.ts index 1a0be63..47665d4 100644 --- a/translations/harbour-fernschreiber-sv.ts +++ b/translations/harbour-fernschreiber-sv.ts @@ -179,6 +179,10 @@ %1 online + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber-zh_CN.ts b/translations/harbour-fernschreiber-zh_CN.ts index 3e96853..0238ad7 100644 --- a/translations/harbour-fernschreiber-zh_CN.ts +++ b/translations/harbour-fernschreiber-zh_CN.ts @@ -176,6 +176,10 @@ %1 位在线 + + New Secret Chat + + ChatInformationTabItemMembersGroups diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index fcd90b7..5436d90 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -179,6 +179,10 @@ %1 online + + New Secret Chat + + ChatInformationTabItemMembersGroups From dff9b1668e86cbf39d6297c77db8b9f530bb92cd Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Sun, 29 Nov 2020 06:28:31 +0200 Subject: [PATCH 16/17] Animate opening and closing of attachment picker row And slightly tweaked the process of closing the sticker picker. --- qml/components/StickerPicker.qml | 16 ++++---------- qml/pages/ChatPage.qml | 36 ++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/qml/components/StickerPicker.qml b/qml/components/StickerPicker.qml index bc4eb93..8d89ce1 100644 --- a/qml/components/StickerPicker.qml +++ b/qml/components/StickerPicker.qml @@ -29,6 +29,8 @@ Item { property var installedStickerSets: stickerManager.getInstalledStickerSets() property bool pickerLoaded: false + signal stickerPicked(var stickerId) + Timer { id: stickerPickerLoadedTimer interval: 100 @@ -101,12 +103,7 @@ Item { MouseArea { anchors.fill: parent - onClicked: { - tdLibWrapper.sendStickerMessage(chatInformation.id, modelData.sticker.remote.id); - stickerPickerOverlayItem.visible = false; - attachmentOptionsRow.visible = false; - stickerPickerLoader.active = false; - } + onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id) } } @@ -168,12 +165,7 @@ Item { MouseArea { anchors.fill: parent - onClicked: { - tdLibWrapper.sendStickerMessage(chatInformation.id, modelData.sticker.remote.id); - stickerPickerOverlayItem.visible = false; - attachmentOptionsRow.visible = false; - stickerPickerLoader.active = false; - } + onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id) } } diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 15258eb..9ec3e06 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -925,6 +925,16 @@ Page { source: "../components/StickerPicker.qml" } + Connections { + target: stickerPickerLoader.item + onStickerPicked: { + console.log(stickerId) + tdLibWrapper.sendStickerMessage(chatInformation.id, stickerId) + stickerPickerLoader.active = false + attachmentOptionsRow.isNeeded = false + } + } + Loader { id: messageOverlayLoader @@ -984,18 +994,22 @@ Page { Row { id: attachmentOptionsRow - visible: false + property bool isNeeded: false + visible: height > 0 + height: isNeeded ? implicitHeight : 0 anchors.right: parent.right width: parent.width layoutDirection: Qt.RightToLeft spacing: Theme.paddingMedium + clip: true + Behavior on height { SmoothedAnimation { duration: 200 } } IconButton { visible: chatPage.hasSendPrivilege("can_send_media_messages") icon.source: "image://theme/icon-m-image" onClicked: { var picker = pageStack.push("Sailfish.Pickers.ImagePickerPage"); picker.selectedContentPropertiesChanged.connect(function(){ - attachmentOptionsRow.visible = false; + attachmentOptionsRow.isNeeded = false; Debug.log("Selected document: ", picker.selectedContentProperties.filePath ); attachmentPreviewRow.fileProperties = picker.selectedContentProperties; attachmentPreviewRow.isPicture = true; @@ -1010,7 +1024,7 @@ Page { onClicked: { var picker = pageStack.push("Sailfish.Pickers.VideoPickerPage"); picker.selectedContentPropertiesChanged.connect(function(){ - attachmentOptionsRow.visible = false; + attachmentOptionsRow.isNeeded = false; Debug.log("Selected video: ", picker.selectedContentProperties.filePath ); attachmentPreviewRow.fileProperties = picker.selectedContentProperties; attachmentPreviewRow.isVideo = true; @@ -1025,7 +1039,7 @@ Page { onClicked: { var picker = pageStack.push("Sailfish.Pickers.FilePickerPage"); picker.selectedContentPropertiesChanged.connect(function(){ - attachmentOptionsRow.visible = false; + attachmentOptionsRow.isNeeded = false; Debug.log("Selected document: ", picker.selectedContentProperties.filePath ); attachmentPreviewRow.fileProperties = picker.selectedContentProperties; attachmentPreviewRow.isDocument = true; @@ -1034,16 +1048,13 @@ Page { }) } } - IconButton { - visible: chatPage.hasSendPrivilege("can_send_other_messages") icon.source: "../../images/icon-m-sticker.svg" icon.sourceSize { width: Theme.iconSizeMedium height: Theme.iconSizeMedium } - highlighted: down || stickerPickerLoader.active onClicked: { stickerPickerLoader.active = !stickerPickerLoader.active; @@ -1054,7 +1065,7 @@ Page { icon.source: "image://theme/icon-m-question" onClicked: { pageStack.push(Qt.resolvedUrl("../pages/PollCreationPage.qml"), { "chatId" : chatInformation.id, groupName: chatInformation.title}); - attachmentOptionsRow.visible = false; + attachmentOptionsRow.isNeeded = false; } } } @@ -1247,17 +1258,16 @@ Page { IconButton { id: attachmentIconButton - icon.source: attachmentOptionsRow.visible ? "image://theme/icon-m-attach?" + Theme.highlightColor : "image://theme/icon-m-attach?" + Theme.primaryColor - + icon.source: "image://theme/icon-m-attach?" + (attachmentOptionsRow.isNeeded ? Theme.highlightColor : Theme.primaryColor) anchors.bottom: parent.bottom anchors.bottomMargin: Theme.paddingSmall enabled: !attachmentPreviewRow.visible onClicked: { - if (attachmentOptionsRow.visible) { - attachmentOptionsRow.visible = false; + if (attachmentOptionsRow.isNeeded) { + attachmentOptionsRow.isNeeded = false; stickerPickerLoader.active = false; } else { - attachmentOptionsRow.visible = true; + attachmentOptionsRow.isNeeded = true; } } } From f446e350512542b40491a20d195f108f4625ccb5 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Sun, 29 Nov 2020 12:34:42 +0100 Subject: [PATCH 17/17] console.log -> Debug.log --- qml/pages/ChatPage.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 9ec3e06..9c5b177 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -928,10 +928,10 @@ Page { Connections { target: stickerPickerLoader.item onStickerPicked: { - console.log(stickerId) - tdLibWrapper.sendStickerMessage(chatInformation.id, stickerId) - stickerPickerLoader.active = false - attachmentOptionsRow.isNeeded = false + Debug.log("Sticker picked: " + stickerId); + tdLibWrapper.sendStickerMessage(chatInformation.id, stickerId); + stickerPickerLoader.active = false; + attachmentOptionsRow.isNeeded = false; } }