Details
- Reviewers
nicolasfella apol - Group Reviewers
KDE Connect - Maniphest Tasks
- T6651: Redundant SMS Notifications
T8338: Message History - Commits
- R224:280a3883e0e5: Initalizer list for Message
R224:95f06b359920: Merge remote-tracking branch 'origin/master' into sms-history
R224:31e93ef7bf20: (WIP) Upgrade Telephony plugin to read SMS history (KDE side)
Setup:
- Build corresponding Android-side diff (D11698)
- Build this diff
Step 1: Does anything at all work?
- Put a breakpoint in the handleBatchMessages method of the telephony plugin, ideally after constructing a Message object
- Use DBus to poke /modules/kdeconnect/devices/<deviceID>/telephony.requestAllConversations()
- Verify that the constructed Message is one you sent or received and that it is the most recent in the corresponding conversation
Step 2: DBus
- Open the Interface org.kde.kdeconnect.device.conversations of /modules/kdeconnect/devices/<deviceId>
- Poke activeConversations and verify an empty array is returned
- Poke requestAllConversationThreads
- Poke activeConversations and verify that a list of numbers has been returned. These are conversationIds
- Use a conversationId to call getFirstFromConversation
- Verify that the returned Message object is one which you recognize
- Note that if the message is an MMS it will be blank and meaningless. Try a different conversationId. MMS support "coming soon!"
Step 3: SMS App
- Use ccmake (or similar) to set SMSAPP_ENABLE to ON
- Build the project
- Run ./bin/kdeconnect-sms
- Verify that the app shows a list of everyone you have an SMS conversation with (MMS messages are stripped out)
- If you have the Contacts plugin working, verify that most contacts have their name and photo instead of their phone number
Diff Detail
- Repository
- R224 KDE Connect
- Branch
- sms-history
- Lint
No Linters Available - Unit
No Unit Test Coverage
plugins/telephony/telephonyMessage.h | ||
---|---|---|
27 ↗ | (On Diff #31082) | Uppercase for all class names, please |
plugins/telephony/telephonyMessage.h | ||
---|---|---|
27 ↗ | (On Diff #31082) | In general you should favor composition over inheritance, you should read about that a bit. That said, I don't quite get it's purpose. Does it store a single message like the name suggests? In that case a QMap doesn't make any sense to me. A class with QStrings address and body should be enough. If it is intended to store multiple messages the naming should reflect that. Also a QList or QMap in the TelephonyPlugin should be enough |
Rename class, restructure to container, and add interface
- Rename telephonyMessage to Message
- Change Message from extending QMap to instead be a container class
- Add interface for messages
plugins/telephony/telephonyMessage.h | ||
---|---|---|
27 ↗ | (On Diff #31082) | A Message (was) a mapping of field names to field values. This makes it very extensible since anybody who wants to add more data just has to add another key/value. However, you are right that this is not a very readable way to implement such a container. The other advantage of extending QMap is that you get all the DBus marshalling/demarshalling for free. However, the model framework we have in place takes care of this, I think, using properties. I am still working out how that interface needs to work. It does store a single message, but in order to work with the model framework (or DBus) the model being represented needs to be represented by its own class. For a similar example, see the Notification class in plugins/notifications/notification.{cpp,h} |
Looking much better, but there is still room for improvement. Passing a QVariantMap in the constructor is IMHO a violation of the law of demeter. The constructor should not make assumptions/rely on the content of args. It should ask directly for what it wants, that is a String body and a String address. I assume you want to be extensible this way, but adding a third property, say an image that is being sent would still need changes in the class. That would be a violation of the open-closed principle, that states that a class should be closed for modification but open for extension. Taking the example of an image message: Instead of cramming all the logic into Message one should create a class ImageMessage that extends Message and takes the image as a third constructor argument.
plugins/telephony/message.cpp | ||
---|---|---|
28 | You can use initializer list here |
I don't disagree, but here is my thinking: Making a lot of individual arguments (this Message classs will need a few more, "type" at a minimum, and I like the concept of an ImageMessage) and passing them to the constructor offloads the logic of how a Message needs to be constructed from Message to the user. In other words, every place I want to construct a Message will have duplicate code. You're right that there is some worry about fragility by passing an unconstrained map of arguments.
plugins/telephony/message.h | ||
---|---|---|
33 ↗ | (On Diff #31113) | How is the type going to be used? Is it constant through the lifecycle of the message object or does a message object has evolving states? |
plugins/telephony/message.h | ||
---|---|---|
33 ↗ | (On Diff #31113) | It is constant through the life of the message. The Android documentation is not good, so I don't know what all the possible types actually mean, but the most important is that TYPE_SENT means the message was sent by us and TYPE_INBOX means the message was received by us |
Not sure if I'm overly nitpicky here 😆
Will a message be always constructed from a QVariantMap? If not it would make more sense to ask for the actual parameters. To avoid code duplication one could make a helper method like
Message Message::fromQVariant(QVariant args) {}
Hopefully one day I will make arc do what I want on the first try :)
I think that is a fair suggestion, but what does such a method offer vs. a constructor which takes a QVariantMap?
At the moment, the only way I see a Message being created is from a QVariantMap, since the only way to get a message is from a network packet, and network packets contain QVariantMaps
Test plan should include some steps to reproduce the desired behavior and see what is already implemented and what not
plugins/telephony/telephonyplugin.cpp | ||
---|---|---|
58 ↗ | (On Diff #31082) | "->this" is weird, never seen it in a KDE Project |
61 ↗ | (On Diff #31082) | Else if? |
104 ↗ | (On Diff #31082) | Use new syntax if possible |
112 ↗ | (On Diff #31082) | returning false here is not necessary |
plugins/telephony/message.h | ||
---|---|---|
33 ↗ | (On Diff #32504) | Usually enums start with a capital letter and values are camelCased. Also no need to specify the value for each. |
59 ↗ | (On Diff #32504) | const? and the m_address too? |
plugins/telephony/telephonyplugin.cpp | ||
106 ↗ | (On Diff #31082) | Shouldn't initialize if it's empty. |
109 ↗ | (On Diff #31082) | return reply? |
121 ↗ | (On Diff #31082) | const |
123 ↗ | (On Diff #31082) | const QVariant & |
plugins/telephony/telephonyplugin.h | ||
80 ↗ | (On Diff #31082) | requestAllConversations()? |
plugins/telephony/message.h | ||
---|---|---|
33 ↗ | (On Diff #32504) | I have specified the values since they come from Android's values for the same field, just to be clear that they are the same (even though I know they would automatically be). Do you think this is a good idea? |
plugins/telephony/telephonyplugin.cpp | ||
61 ↗ | (On Diff #31082) | At this revision I hadn't figured out what to do with old-style packets. I have decided to support them fully (meaning old Android apps would continue to function as they currently do) and return at the end of the if block. Does this work for you? |
104 ↗ | (On Diff #31082) | The messageReceived method being used as the sender of this connection is on the other side of the DBus interface (telepathy-kdeconnect/connection.h line 55). I don't know how or if the new syntax can be used in this case |
Update based on reviews
- Add remaining Telephony Message fields
- Address review suggestions for const data
- Correct naming convention of message.Type enum
- Clean up forwardToTelepathy method
- Rename sendAllConversationsRequest to requestAllConversations
- Remove this->
- Re-add createNotification method
- Reenable support for old-style packets which generate notificatinos (SMS, incoming call, missed call)
- Remove extra redundant telepathy code from notifications handling
- Add header comment to createNotification
- Add header comment for PACKET_TYPE_TELEPHONY
Would you consider (when you're ready) updating the README to be a little more complete, since you're probably quite familiar with the expected packet formats?
plugins/telephony/message.h | ||
---|---|---|
28 ↗ | (On Diff #34254) | Mark CONSTANT if it's not going to change. |
40 ↗ | (On Diff #34254) | Enums usually start with capital letter: MessageTypeAll |
58 ↗ | (On Diff #34254) | getters in Qt usually don't have a get prefix: getBody() -> body() |
plugins/telephony/telephonyplugin.cpp | ||
40–41 ↗ | (On Diff #31082) | Shouldn't this be !m_telepathyInterface.isValid()? |
41 ↗ | (On Diff #31082) | Instead of passing "" or QLatin1String(""), pass QString() or even {}. |
Sure. Putting it somewhere centralized is probably a good idea. If you want to look at it now, currently all of that documentation lives in header comments on the various PACKET_TYPE_* fields
plugins/telephony/telephonyplugin.cpp | ||
---|---|---|
40–41 ↗ | (On Diff #31082) | No, this is handling the case where the telepathy interface was valid. If the message has been passed to telepathy, it does not keep trying to process it using a notification |
Lots of Model work. SMS app is now able to display a list of convesations (which is far more exciting than it sounds)
plugins/telephony/message.h | ||
---|---|---|
28 ↗ | (On Diff #34254) | Annoyingly this class has become mutable because I am required (I think) for the DBus support to implement operator=, so the properties are no longer constant |
Hey careful there. You merged master instead of rebasing somewhere in between. Can someone clean the branch before merging?
Are you sure? I rebased the branch onto master before using arc to push it here (but the branch is still in crazy land). How would I tell if it's messed up?
Okay, having just had my first experience landing a commit from the Contacts plugin, I now see what you're saying. Are you happy with what you're seeing here on Phabricator? I can land exactly this with no trouble.