From deacb7f0ea33b0a2e10aabaf780353e84f5934f9 Mon Sep 17 00:00:00 2001 From: Sebastian Wolf Date: Thu, 26 Nov 2020 22:18:51 +0100 Subject: [PATCH] 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