diff --git a/cli/kdeconnect-cli.cpp b/cli/kdeconnect-cli.cpp --- a/cli/kdeconnect-cli.cpp +++ b/cli/kdeconnect-cli.cpp @@ -41,7 +41,7 @@ QStringLiteral("kdeconnect-cli"), QStringLiteral(KDECONNECT_VERSION_STRING), i18n("KDE Connect CLI tool"), - KAboutLicense::GPL, + KAboutLicense::GPL, i18n("(C) 2015 Aleix Pol Gonzalez")); KAboutData::setApplicationData(about); @@ -214,7 +214,7 @@ blockOnReply(QDBusConnection::sessionBus().asyncCall(msg)); } else if(parser.isSet(QStringLiteral("send-sms"))) { if (parser.isSet(QStringLiteral("destination"))) { - QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/telephony", QStringLiteral("org.kde.kdeconnect.device.telephony"), QStringLiteral("sendSms")); + QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"), "/modules/kdeconnect/devices/"+device+"/sms", QStringLiteral("org.kde.kdeconnect.device.sms"), QStringLiteral("sendSms")); msg.setArguments({ parser.value("destination"), parser.value("send-sms") }); blockOnReply(QDBusConnection::sessionBus().asyncCall(msg)); } else { diff --git a/interfaces/CMakeLists.txt b/interfaces/CMakeLists.txt --- a/interfaces/CMakeLists.txt +++ b/interfaces/CMakeLists.txt @@ -48,8 +48,8 @@ geninterface(${CMAKE_SOURCE_DIR}/plugins/lockdevice/lockdeviceplugin.h lockdeviceinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/remotecommands/remotecommandsplugin.h remotecommandsinterface) geninterface(${CMAKE_SOURCE_DIR}/plugins/remotekeyboard/remotekeyboardplugin.h remotekeyboardinterface) -geninterface(${CMAKE_SOURCE_DIR}/plugins/telephony/telephonyplugin.h telephonyinterface) -geninterface(${CMAKE_SOURCE_DIR}/plugins/telephony/conversationsdbusinterface.h conversationsinterface) +geninterface(${CMAKE_SOURCE_DIR}/plugins/sms/smsplugin.h smsinterface) +geninterface(${CMAKE_SOURCE_DIR}/plugins/sms/conversationsdbusinterface.h conversationsinterface) add_library(kdeconnectinterfaces SHARED ${libkdeconnect_SRC}) diff --git a/interfaces/dbusinterfaces.h b/interfaces/dbusinterfaces.h --- a/interfaces/dbusinterfaces.h +++ b/interfaces/dbusinterfaces.h @@ -35,7 +35,7 @@ #include "interfaces/lockdeviceinterface.h" #include "interfaces/remotecommandsinterface.h" #include "interfaces/remotekeyboardinterface.h" -#include "interfaces/telephonyinterface.h" +#include "interfaces/smsinterface.h" #include "interfaces/conversationsinterface.h" /** @@ -210,13 +210,13 @@ void remoteStateChanged(bool state); }; -class KDECONNECTINTERFACES_EXPORT TelephonyDbusInterface - : public OrgKdeKdeconnectDeviceTelephonyInterface +class KDECONNECTINTERFACES_EXPORT SmsDbusInterface + : public OrgKdeKdeconnectDeviceSmsInterface { Q_OBJECT public: - explicit TelephonyDbusInterface(const QString& deviceId, QObject* parent = nullptr); - ~TelephonyDbusInterface() override; + explicit SmsDbusInterface(const QString& deviceId, QObject* parent = nullptr); + ~SmsDbusInterface() override; }; template diff --git a/interfaces/dbusinterfaces.cpp b/interfaces/dbusinterfaces.cpp --- a/interfaces/dbusinterfaces.cpp +++ b/interfaces/dbusinterfaces.cpp @@ -176,9 +176,9 @@ RemoteKeyboardDbusInterface::~RemoteKeyboardDbusInterface() = default; -TelephonyDbusInterface::TelephonyDbusInterface(const QString& deviceId, QObject* parent): - OrgKdeKdeconnectDeviceTelephonyInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/telephony", QDBusConnection::sessionBus(), parent) +SmsDbusInterface::SmsDbusInterface(const QString& deviceId, QObject* parent): + OrgKdeKdeconnectDeviceSmsInterface(DaemonDbusInterface::activatedService(), "/modules/kdeconnect/devices/" + deviceId + "/sms", QDBusConnection::sessionBus(), parent) { } -TelephonyDbusInterface::~TelephonyDbusInterface() = default; +SmsDbusInterface::~SmsDbusInterface() = default; diff --git a/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp b/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp --- a/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp +++ b/plasmoid/declarativeplugin/kdeconnectdeclarativeplugin.cpp @@ -75,9 +75,9 @@ return new LockDeviceDbusInterface(deviceId.toString()); } -QObject* createTelephonyInterface(const QVariant& deviceId) +QObject* createSmsInterface(const QVariant& deviceId) { - return new TelephonyDbusInterface(deviceId.toString()); + return new SmsDbusInterface(deviceId.toString()); } QObject* createDBusResponse() @@ -138,8 +138,8 @@ engine->rootContext()->setContextProperty(QStringLiteral("LockDeviceDbusInterfaceFactory") , new ObjectFactory(engine, createDeviceLockInterface)); - engine->rootContext()->setContextProperty(QStringLiteral("TelephonyDbusInterfaceFactory") - , new ObjectFactory(engine, createTelephonyInterface)); + engine->rootContext()->setContextProperty(QStringLiteral("SmsDbusInterfaceFactory") + , new ObjectFactory(engine, createSmsInterface)); engine->rootContext()->setContextProperty(QStringLiteral("DBusResponseFactory") , new ObjectFactory(engine, createDBusResponse)); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -15,6 +15,7 @@ endif() add_subdirectory(remotekeyboard) add_subdirectory(mousepad) +add_subdirectory(sms) if(NOT WIN32) add_subdirectory(runcommand) add_subdirectory(sendnotifications) diff --git a/plugins/sms/CMakeLists.txt b/plugins/sms/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/plugins/sms/CMakeLists.txt @@ -0,0 +1,22 @@ +set(kdeconnect_sms_SRCS + smsplugin.cpp + conversationsdbusinterface.cpp +) + +include_directories(${CMAKE_BINARY_DIR}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../notifications/) # needed for the sendreplydialog + +ki18n_wrap_ui(kdeconnect_sms_SRCS ../notifications/sendreplydialog.ui) + +kdeconnect_add_plugin(kdeconnect_sms JSON kdeconnect_sms.json SOURCES ../notifications/sendreplydialog.cpp ${kdeconnect_sms_SRCS}) + + +target_link_libraries(kdeconnect_sms + kdeconnectcore + kdeconnectinterfaces + Qt5::DBus + KF5::I18n + KF5::Notifications + Qt5::Widgets +) diff --git a/plugins/telephony/conversationsdbusinterface.h b/plugins/sms/conversationsdbusinterface.h rename from plugins/telephony/conversationsdbusinterface.h rename to plugins/sms/conversationsdbusinterface.h --- a/plugins/telephony/conversationsdbusinterface.h +++ b/plugins/sms/conversationsdbusinterface.h @@ -91,7 +91,7 @@ int m_lastId; - TelephonyDbusInterface m_telephonyInterface; + SmsDbusInterface m_telephonyInterface; }; #endif // CONVERSATIONSDBUSINTERFACE_H diff --git a/plugins/telephony/conversationsdbusinterface.cpp b/plugins/sms/conversationsdbusinterface.cpp rename from plugins/telephony/conversationsdbusinterface.cpp rename to plugins/sms/conversationsdbusinterface.cpp --- a/plugins/telephony/conversationsdbusinterface.cpp +++ b/plugins/sms/conversationsdbusinterface.cpp @@ -27,7 +27,7 @@ #include #include -#include "telephonyplugin.h" +#include "smsplugin.h" ConversationsDbusInterface::ConversationsDbusInterface(KdeConnectPlugin* plugin) : QDBusAbstractAdaptor(const_cast(plugin->device())) @@ -55,7 +55,7 @@ if (messagesList.isEmpty()) { // Since there are no messages in the conversation, it's likely that it is a junk ID, but go ahead anyway - qCWarning(KDECONNECT_PLUGIN_TELEPHONY) << "Got a conversationID for a conversation with no messages!" << conversationID; + qCWarning(KDECONNECT_PLUGIN_SMS) << "Got a conversationID for a conversation with no messages!" << conversationID; } m_telephonyInterface.requestConversation(conversationID); @@ -103,7 +103,7 @@ if (messagesList.isEmpty()) { // Since there are no messages in the conversation, we can't do anything sensible - qCWarning(KDECONNECT_PLUGIN_TELEPHONY) << "Got a conversationID for a conversation with no messages!"; + qCWarning(KDECONNECT_PLUGIN_SMS) << "Got a conversationID for a conversation with no messages!"; return; } const QString& address = messagesList.front().address(); diff --git a/plugins/sms/kdeconnect_sms.json b/plugins/sms/kdeconnect_sms.json new file mode 100644 --- /dev/null +++ b/plugins/sms/kdeconnect_sms.json @@ -0,0 +1,30 @@ +{ + "KPlugin": { + "Authors": [ + { + "Email": "simon@ergotech.com", + "Name": "Simon Redman" + } + ], + "Description": "Send and receive SMS", + "EnabledByDefault": true, + "Icon": "dialog-ok", + "Id": "kdeconnect_sms", + "License": "GPL", + "Name": "SMS", + "ServiceTypes": [ + "KdeConnect/Plugin" + ], + "Version": "0.1", + "Website": "https://nicolasfella.wordpress.com" + }, + "X-KdeConnect-OutgoingPacketType": [ + "kdeconnect.sms.request", + "kdeconnect.telephony.request_conversations", + "kdeconnect.telephony.request_conversation" + ], + "X-KdeConnect-SupportedPacketType": [ + "kdeconnect.telephony.message", + "kdeconnect.telephony" + ] +} diff --git a/plugins/telephony/telephonyplugin.h b/plugins/sms/smsplugin.h copy from plugins/telephony/telephonyplugin.h copy to plugins/sms/smsplugin.h --- a/plugins/telephony/telephonyplugin.h +++ b/plugins/sms/smsplugin.h @@ -1,6 +1,5 @@ /** * Copyright 2013 Albert Vaca - * Copyright 2018 Simon Redman * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -19,19 +18,22 @@ * along with this program. If not, see . */ -#ifndef TELEPHONYPLUGIN_H -#define TELEPHONYPLUGIN_H +#ifndef SMSPLUGIN_H +#define SMSPLUGIN_H -#include "conversationsdbusinterface.h" -#include "interfaces/conversationmessage.h" - -#include -#include +#include #include #include +#include "conversationsdbusinterface.h" +#include "interfaces/conversationmessage.h" + +#include "sendreplydialog.h" + +#define PACKET_TYPE_TELEPHONY QStringLiteral("kdeconnect.telephony") + /** * Packet used to indicate a batch of messages has been pushed from the remote device * @@ -51,23 +53,9 @@ * ] * } */ -#define PACKET_TYPE_TELEPHONY_MESSAGE QStringLiteral("kdeconnect.telephony.message") -/** - * Packet used for simple telephony events - * - * It contains the key "event" which maps to a string indicating the type of event: - * - "ringing" - A phone call is incoming - * - "missedCall" - An incoming call was not answered - * - "sms" - An incoming SMS message - * - Note: As of this writing (15 May 2018) the SMS interface is being improved and this type of event - * is no longer the preferred way of retrieving SMS. Use PACKET_TYPE_TELEPHONY_MESSAGE instead. - * - * Depending on the event, other fields may be defined - */ -#define PACKET_TYPE_TELEPHONY QStringLiteral("kdeconnect.telephony") +#define PACKET_TYPE_TELEPHONY_MESSAGE QStringLiteral("kdeconnect.telephony.message") -#define PACKET_TYPE_TELEPHONY_REQUEST QStringLiteral("kdeconnect.telephony.request") #define PACKET_TYPE_SMS_REQUEST QStringLiteral("kdeconnect.sms.request") /** @@ -86,20 +74,21 @@ */ #define PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATION QStringLiteral("kdeconnect.telephony.request_conversation") -Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY) +Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SMS) -class TelephonyPlugin +class Q_DECL_EXPORT SmsPlugin : public KdeConnectPlugin { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.telephony") + Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.sms") public: - explicit TelephonyPlugin(QObject* parent, const QVariantList& args); - ~TelephonyPlugin() override; + explicit SmsPlugin(QObject* parent, const QVariantList& args); + ~SmsPlugin() override; bool receivePacket(const NetworkPacket& np) override; void connected() override {} + QString dbusPath() const override; public Q_SLOTS: @@ -115,37 +104,32 @@ */ Q_SCRIPTABLE void requestConversation(const QString& conversationID) const; -public: -Q_SIGNALS: - private Q_SLOTS: - void sendMutePacket(); void showSendSmsDialog(); -protected: +private: + /** * Send to the telepathy plugin if it is available */ void forwardToTelepathy(const ConversationMessage& message); /** - * Handle a packet which contains many messages, such as PACKET_TYPE_TELEPHONY_MESSAGE + * Create a notification for incoming SMS (with the option to reply) + * This comment is being written while SMS handling is in the process of being improved. + * As such, any code in createNotification which deals with SMS is legacy support */ - bool handleBatchMessages(const NetworkPacket& np); + KNotification* createNotification(const NetworkPacket& np); -private: /** - * Create a notification for: - * - Incoming call (with the option to mute the ringing) - * - Missed call - * - Incoming SMS (with the option to reply) - * - This comment is being written while SMS handling is in the process of being improved. - * As such, any code in createNotification which deals with SMS is legacy support + * Handle a packet which contains many messages, such as PACKET_TYPE_TELEPHONY_MESSAGE */ - KNotification* createNotification(const NetworkPacket& np); + bool handleBatchMessages(const NetworkPacket& np); + QDBusInterface m_telepathyInterface; ConversationsDbusInterface* m_conversationInterface; + }; #endif diff --git a/plugins/sms/smsplugin.cpp b/plugins/sms/smsplugin.cpp new file mode 100644 --- /dev/null +++ b/plugins/sms/smsplugin.cpp @@ -0,0 +1,198 @@ +/** + * Copyright 2013 Albert Vaca + * + * This program 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 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 this program. If not, see . + */ + +#include "smsplugin.h" + +#include +#include + +#include +#include +#include + +#include +#include + +#include "sendreplydialog.h" + +K_PLUGIN_FACTORY_WITH_JSON( KdeConnectPluginFactory, "kdeconnect_sms.json", registerPlugin< SmsPlugin >(); ) + +Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_SMS, "kdeconnect.plugin.sms") + +SmsPlugin::SmsPlugin(QObject* parent, const QVariantList& args) + : KdeConnectPlugin(parent, args) + , m_telepathyInterface(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.kdeconnect"), QStringLiteral("/kdeconnect")) + , m_conversationInterface(new ConversationsDbusInterface(this)) +{ +} + +SmsPlugin::~SmsPlugin() +{ +} + +bool SmsPlugin::receivePacket(const NetworkPacket& np) +{ + if (np.get(QStringLiteral("isCancel"))) { + + //TODO: Clear the old notification + return true; + } + + const QString& event = np.get(QStringLiteral("event"), QStringLiteral("unknown")); + + // Handle old-style packets + // TODO Drop support? + if (np.type() == PACKET_TYPE_TELEPHONY) + { + if (event == QLatin1String("sms")) + { + // New-style packets should be a PACKET_TYPE_TELEPHONY_MESSAGE (15 May 2018) + qCDebug(KDECONNECT_PLUGIN_SMS) << "Handled an old-style Telephony sms packet. You should update your Android app to get the latest features!"; + ConversationMessage message(np.body()); + + // In case telepathy can handle the message, don't do anything else + if (m_telepathyInterface.isValid()) { + forwardToTelepathy(message); + return true; + } + + KNotification* n = createNotification(np); + if (n != nullptr) n->sendEvent(); + return true; + + } + } + + if (np.type() == PACKET_TYPE_TELEPHONY_MESSAGE) { + return handleBatchMessages(np); + } + + return true; +} + +KNotification* SmsPlugin::createNotification(const NetworkPacket& np) +{ + const QString event = np.get(QStringLiteral("event")); + const QString phoneNumber = np.get(QStringLiteral("phoneNumber"), i18n("unknown number")); + const QString contactName = np.get(QStringLiteral("contactName"), phoneNumber); + const QByteArray phoneThumbnail = QByteArray::fromBase64(np.get(QStringLiteral("phoneThumbnail"), "")); + const QString messageBody = np.get(QStringLiteral("messageBody"),{}); + + const QString title = device()->name(); + + QString type = QStringLiteral("smsReceived"); + QString icon = QStringLiteral("mail-receive"); + QString content = i18n("SMS from %1
%2", contactName, messageBody); + KNotification::NotificationFlags flags = KNotification::Persistent; //Note that in Unity this generates a message box! + + qCDebug(KDECONNECT_PLUGIN_SMS) << "Creating notification with type:" << type; + + KNotification* notification = new KNotification(type, flags, this); + if (!phoneThumbnail.isEmpty()) { + QPixmap photo; + photo.loadFromData(phoneThumbnail, "JPEG"); + notification->setPixmap(photo); + } else { + notification->setIconName(icon); + } + notification->setComponentName(QStringLiteral("kdeconnect")); + notification->setTitle(title); + notification->setText(content); + + notification->setActions( QStringList(i18n("Reply")) ); + notification->setProperty("phoneNumber", phoneNumber); + notification->setProperty("contactName", contactName); + notification->setProperty("originalMessage", messageBody); + connect(notification, &KNotification::action1Activated, this, &SmsPlugin::showSendSmsDialog); + + return notification; + +} + +void SmsPlugin::sendSms(const QString& phoneNumber, const QString& messageBody) +{ + NetworkPacket np(PACKET_TYPE_SMS_REQUEST, { + {"sendSms", true}, + {"phoneNumber", phoneNumber}, + {"messageBody", messageBody} + }); + qDebug() << "sending sms!"; + sendPacket(np); +} + +void SmsPlugin::showSendSmsDialog() +{ + qCDebug(KDECONNECT_PLUGIN_SMS) << "Show dialog"; + QString phoneNumber = sender()->property("phoneNumber").toString(); + QString contactName = sender()->property("contactName").toString(); + QString originalMessage = sender()->property("originalMessage").toString(); + SendReplyDialog* dialog = new SendReplyDialog(originalMessage, phoneNumber, contactName); + connect(dialog, &SendReplyDialog::sendReply, this, &SmsPlugin::sendSms); + dialog->show(); + dialog->raise(); +} + +void SmsPlugin::requestAllConversations() +{ + NetworkPacket np(PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATIONS); + + sendPacket(np); +} + +void SmsPlugin::requestConversation (const QString& conversationID) const +{ + NetworkPacket np(PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATION); + np.set("threadID", conversationID.toInt()); + + sendPacket(np); +} + +void SmsPlugin::forwardToTelepathy(const ConversationMessage& message) +{ + qCDebug(KDECONNECT_PLUGIN_SMS) << "Passing a text message to the telepathy interface"; + connect(&m_telepathyInterface, SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)), Qt::UniqueConnection); + const QString messageBody = message.body(); + const QString contactName; // TODO: When telepathy support is improved, look up the contact with KPeople + const QString phoneNumber = message.address(); + m_telepathyInterface.call(QDBus::NoBlock, QStringLiteral("sendMessage"), phoneNumber, contactName, messageBody); +} + +bool SmsPlugin::handleBatchMessages(const NetworkPacket& np) +{ + const auto messages = np.get("messages"); + + for (const QVariant& body : messages) + { + ConversationMessage message(body.toMap()); + forwardToTelepathy(message); + m_conversationInterface->addMessage(message); + } + + return true; +} + + +QString SmsPlugin::dbusPath() const +{ + return "/modules/kdeconnect/devices/" + device()->id() + "/sms"; +} + +#include "smsplugin.moc" + diff --git a/plugins/telephony/CMakeLists.txt b/plugins/telephony/CMakeLists.txt --- a/plugins/telephony/CMakeLists.txt +++ b/plugins/telephony/CMakeLists.txt @@ -1,19 +1,14 @@ set(kdeconnect_telephony_SRCS telephonyplugin.cpp - conversationsdbusinterface.cpp ) include_directories(${CMAKE_BINARY_DIR}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../notifications/) # needed for the sendreplydialog -ki18n_wrap_ui(kdeconnect_telephony_SRCS ../notifications/sendreplydialog.ui) -kdeconnect_add_plugin(kdeconnect_telephony JSON kdeconnect_telephony.json SOURCES ../notifications/sendreplydialog.cpp ${kdeconnect_telephony_SRCS}) +kdeconnect_add_plugin(kdeconnect_telephony JSON kdeconnect_telephony.json SOURCES ${kdeconnect_telephony_SRCS}) target_link_libraries(kdeconnect_telephony kdeconnectcore - kdeconnectinterfaces KF5::I18n KF5::Notifications Qt5::DBus - Qt5::Widgets ) diff --git a/plugins/telephony/kdeconnect_telephony.json b/plugins/telephony/kdeconnect_telephony.json --- a/plugins/telephony/kdeconnect_telephony.json +++ b/plugins/telephony/kdeconnect_telephony.json @@ -90,13 +90,9 @@ "Website": "http://albertvaka.wordpress.com" }, "X-KdeConnect-OutgoingPacketType": [ - "kdeconnect.telephony.request", - "kdeconnect.sms.request", - "kdeconnect.telephony.request_conversations", - "kdeconnect.telephony.request_conversation" + "kdeconnect.telephony.request" ], "X-KdeConnect-SupportedPacketType": [ - "kdeconnect.telephony", - "kdeconnect.telephony.message" + "kdeconnect.telephony" ] } diff --git a/plugins/telephony/telephonyplugin.h b/plugins/telephony/telephonyplugin.h --- a/plugins/telephony/telephonyplugin.h +++ b/plugins/telephony/telephonyplugin.h @@ -22,69 +22,25 @@ #ifndef TELEPHONYPLUGIN_H #define TELEPHONYPLUGIN_H -#include "conversationsdbusinterface.h" -#include "interfaces/conversationmessage.h" - #include #include #include #include -/** - * Packet used to indicate a batch of messages has been pushed from the remote device - * - * The body should contain the key "messages" mapping to an array of messages - * - * For example: - * { "messages" : [ - * { "event" : "sms", - * "messageBody" : "Hello", - * "phoneNumber" : "2021234567", - * "messageDate" : "1518846484880", - * "messageType" : "2", - * "threadID" : "132" - * }, - * { ... }, - * ... - * ] - * } - */ -#define PACKET_TYPE_TELEPHONY_MESSAGE QStringLiteral("kdeconnect.telephony.message") - /** * Packet used for simple telephony events * * It contains the key "event" which maps to a string indicating the type of event: * - "ringing" - A phone call is incoming * - "missedCall" - An incoming call was not answered - * - "sms" - An incoming SMS message - * - Note: As of this writing (15 May 2018) the SMS interface is being improved and this type of event - * is no longer the preferred way of retrieving SMS. Use PACKET_TYPE_TELEPHONY_MESSAGE instead. * * Depending on the event, other fields may be defined */ #define PACKET_TYPE_TELEPHONY QStringLiteral("kdeconnect.telephony") #define PACKET_TYPE_TELEPHONY_REQUEST QStringLiteral("kdeconnect.telephony.request") -#define PACKET_TYPE_SMS_REQUEST QStringLiteral("kdeconnect.sms.request") - -/** - * Packet sent to request all the most-recent messages in all conversations on the device - * - * The request packet shall contain no body - */ -#define PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATIONS QStringLiteral("kdeconnect.telephony.request_conversations") - -/** - * Packet sent to request all the messages in a particular conversation - * - * The body should contain the key "threadID" mapping to the threadID (as a string) being requested - * For example: - * { "threadID": 203 } - */ -#define PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATION QStringLiteral("kdeconnect.telephony.request_conversation") Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_TELEPHONY) @@ -102,50 +58,19 @@ void connected() override {} QString dbusPath() const override; -public Q_SLOTS: - Q_SCRIPTABLE void sendSms(const QString& phoneNumber, const QString& messageBody); - - /** - * Send a request to the remote for all of its conversations - */ - Q_SCRIPTABLE void requestAllConversations(); - - /** - * Send a request to the remote for a particular conversation - */ - Q_SCRIPTABLE void requestConversation(const QString& conversationID) const; - public: Q_SIGNALS: private Q_SLOTS: void sendMutePacket(); - void showSendSmsDialog(); - -protected: - /** - * Send to the telepathy plugin if it is available - */ - void forwardToTelepathy(const ConversationMessage& message); - - /** - * Handle a packet which contains many messages, such as PACKET_TYPE_TELEPHONY_MESSAGE - */ - bool handleBatchMessages(const NetworkPacket& np); private: /** * Create a notification for: * - Incoming call (with the option to mute the ringing) * - Missed call - * - Incoming SMS (with the option to reply) - * - This comment is being written while SMS handling is in the process of being improved. - * As such, any code in createNotification which deals with SMS is legacy support */ KNotification* createNotification(const NetworkPacket& np); - - QDBusInterface m_telepathyInterface; - ConversationsDbusInterface* m_conversationInterface; }; #endif diff --git a/plugins/telephony/telephonyplugin.cpp b/plugins/telephony/telephonyplugin.cpp --- a/plugins/telephony/telephonyplugin.cpp +++ b/plugins/telephony/telephonyplugin.cpp @@ -21,10 +21,6 @@ #include "telephonyplugin.h" -#include "sendreplydialog.h" -#include "conversationsdbusinterface.h" -#include "interfaces/conversationmessage.h" - #include #include #include @@ -38,8 +34,6 @@ TelephonyPlugin::TelephonyPlugin(QObject* parent, const QVariantList& args) : KdeConnectPlugin(parent, args) - , m_telepathyInterface(QStringLiteral("org.freedesktop.Telepathy.ConnectionManager.kdeconnect"), QStringLiteral("/kdeconnect")) - , m_conversationInterface(new ConversationsDbusInterface(this)) { } @@ -60,14 +54,6 @@ const QByteArray phoneThumbnail = QByteArray::fromBase64(np.get(QStringLiteral("phoneThumbnail"), "")); const QString messageBody = np.get(QStringLiteral("messageBody"),{}); - // In case telepathy can handle the message, don't do anything else - if (event == QLatin1String("sms") && m_telepathyInterface.isValid()) { - // Telepathy has already been tried (in receivePacket) - // There is a chance that it somehow failed, but since nobody uses Telepathy anyway... - // TODO: When upgrading telepathy, handle failure case (in case m_telepathyInterface.call returns false) - return nullptr; - } - QString content, type, icon; KNotification::NotificationFlags flags = KNotification::CloseOnTimeout; @@ -82,12 +68,6 @@ icon = QStringLiteral("call-start"); content = i18n("Missed call from %1", contactName); flags |= KNotification::Persistent; //Note that in Unity this generates a message box! - } else if (event == QLatin1String("sms")) { - type = QStringLiteral("smsReceived"); - icon = QStringLiteral("mail-receive"); - QString messageBody = np.get(QStringLiteral("messageBody"), QLatin1String("")); - content = i18n("SMS from %1
%2", contactName, messageBody); - flags |= KNotification::Persistent; //Note that in Unity this generates a message box! } else if (event == QLatin1String("talking")) { return nullptr; } else { @@ -117,16 +97,8 @@ if (event == QLatin1String("ringing")) { notification->setActions( QStringList(i18n("Mute Call")) ); connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::sendMutePacket); - } else if (event == QLatin1String("sms")) { - notification->setActions( QStringList(i18n("Reply")) ); - notification->setProperty("phoneNumber", phoneNumber); - notification->setProperty("contactName", contactName); - notification->setProperty("originalMessage", messageBody); - connect(notification, &KNotification::action1Activated, this, &TelephonyPlugin::showSendSmsDialog); } - return notification; - } bool TelephonyPlugin::receivePacket(const NetworkPacket& np) @@ -144,21 +116,13 @@ { if (event == QLatin1String("sms")) { - // New-style packets should be a PACKET_TYPE_TELEPHONY_MESSAGE (15 May 2018) - qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Handled an old-style Telephony sms packet. You should update your Android app to get the latest features!"; - ConversationMessage message(np.body()); - forwardToTelepathy(message); + return false; } KNotification* n = createNotification(np); if (n != nullptr) n->sendEvent(); return true; } - if (np.type() == PACKET_TYPE_TELEPHONY_MESSAGE) - { - return handleBatchMessages(np); - } - return true; } @@ -168,70 +132,6 @@ sendPacket(packet); } -void TelephonyPlugin::sendSms(const QString& phoneNumber, const QString& messageBody) -{ - NetworkPacket np(PACKET_TYPE_SMS_REQUEST, { - {"sendSms", true}, - {"phoneNumber", phoneNumber}, - {"messageBody", messageBody} - }); - qDebug() << "sending sms!"; - sendPacket(np); -} - -void TelephonyPlugin::showSendSmsDialog() -{ - QString phoneNumber = sender()->property("phoneNumber").toString(); - QString contactName = sender()->property("contactName").toString(); - QString originalMessage = sender()->property("originalMessage").toString(); - SendReplyDialog* dialog = new SendReplyDialog(originalMessage, phoneNumber, contactName); - connect(dialog, &SendReplyDialog::sendReply, this, &TelephonyPlugin::sendSms); - dialog->show(); - dialog->raise(); -} - -void TelephonyPlugin::requestAllConversations() -{ - NetworkPacket np(PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATIONS); - - sendPacket(np); -} - -void TelephonyPlugin::requestConversation (const QString& conversationID) const -{ - NetworkPacket np(PACKET_TYPE_TELEPHONY_REQUEST_CONVERSATION); - np.set("threadID", conversationID.toInt()); - - sendPacket(np); -} - -void TelephonyPlugin::forwardToTelepathy(const ConversationMessage& message) -{ - // In case telepathy can handle the message, don't do anything else - if (m_telepathyInterface.isValid()) { - qCDebug(KDECONNECT_PLUGIN_TELEPHONY) << "Passing a text message to the telepathy interface"; - connect(&m_telepathyInterface, SIGNAL(messageReceived(QString,QString)), SLOT(sendSms(QString,QString)), Qt::UniqueConnection); - const QString messageBody = message.body(); - const QString contactName; // TODO: When telepathy support is improved, look up the contact with KPeople - const QString phoneNumber = message.address(); - m_telepathyInterface.call(QDBus::NoBlock, QStringLiteral("sendMessage"), phoneNumber, contactName, messageBody); - } -} - -bool TelephonyPlugin::handleBatchMessages(const NetworkPacket& np) -{ - const auto messages = np.get("messages"); - - for (const QVariant& body : messages) - { - ConversationMessage message(body.toMap()); - forwardToTelepathy(message); - m_conversationInterface->addMessage(message); - } - - return true; -} - QString TelephonyPlugin::dbusPath() const { return "/modules/kdeconnect/devices/" + device()->id() + "/telephony";