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;