Merge lp:~tiagosh/messaging-app/dual-sim2 into lp:messaging-app
- dual-sim2
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Gustavo Pichorim Boiko |
Approved revision: | 147 |
Merged at revision: | 150 |
Proposed branch: | lp:~tiagosh/messaging-app/dual-sim2 |
Merge into: | lp:messaging-app |
Diff against target: |
465 lines (+154/-54) 6 files modified
src/qml/MainPage.qml (+6/-4) src/qml/MessageDelegate.qml (+15/-1) src/qml/Messages.qml (+128/-46) src/qml/NewRecipientPage.qml (+1/-1) src/qml/ThreadDelegate.qml (+3/-1) tests/autopilot/messaging_app/emulators.py (+1/-1) |
To merge this branch: | bzr merge lp:~tiagosh/messaging-app/dual-sim2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Pichorim Boiko (community) | Approve | ||
PS Jenkins bot | continuous-integration | Needs Fixing | |
Review via email: mp+226906@code.launchpad.net |
Commit message
- Implement sim card switcher when there is more than one account available (label is hardcoded for now)
- Update some visuals to match the new spec
- Merge messages from different accounts
Description of the change
- Implement sim card switcher when there is more than one account available (label is hardcoded for now)
- Update some visuals to match the new spec
- Merge messages from different accounts
--Checklist--
Are there any related MPs required for this MP to build/function as expected? Please list.
https:/
https:/
Is your branch in sync with latest trunk (e.g. bzr pull lp:trunk -> no changes)
Yes
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator?
Yes
Did you successfully run all tests found in your component's Test Plan (https:/
Yes
If you changed the UI, was the change specified/approved by design?
Yes
If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP?
N/A
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:146
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 147. By Tiago Salem Herrmann
-
fix translation
update method name to reflect its real job
remove unused code
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:147
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Gustavo Pichorim Boiko (boiko) wrote : | # |
Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
Yes
Did CI run pass? If not, please explain why.
Yes
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
Yes
Code looks good and works as expected!
- 148. By Tiago Salem Herrmann
-
merge trunk
- 149. By Tiago Salem Herrmann
-
only show accountLabel if there is more than 1 account
- 150. By Tiago Salem Herrmann
-
increase touch area
- 151. By Tiago Salem Herrmann
-
increase font size
fix bottom edge swipe
Brendan Donegan (brendan-donegan) wrote : | # |
The CI run did not pass here - I guess the failures have been ignored because of false positives? That should really be fixed, and until then the tests should be run manually on the device. If you had done this you would have noticed you broke a test by changing the 'name' property of the Add contact icon from 'new-contact' to 'contact'.
Brendan Donegan (brendan-donegan) wrote : | # |
Also, are we planning to have any tests for the dual SIM feature?
Tiago Salem Herrmann (tiagosh) wrote : | # |
The tests failed because this MR needs changes in the history-service and telephony-service, as explained in the MR description. If you check the logs you will see that the app is not even running correctly because the new proxy model is inexistent. Also, I probably forgot to run the tests manually (only tested the functionalities on the device) and ended up breaking the test. My bad! I will fix this still today. Thank for the report.
About tests for dual sim, I believe we need to add some, but the current infrastructure (with-ofono-
Preview Diff
1 | === modified file 'src/qml/MainPage.qml' |
2 | --- src/qml/MainPage.qml 2014-06-17 13:18:57 +0000 |
3 | +++ src/qml/MainPage.qml 2014-07-17 21:29:41 +0000 |
4 | @@ -131,11 +131,12 @@ |
5 | } |
6 | } |
7 | |
8 | - SortProxyModel { |
9 | + HistoryThreadGroupingProxyModel { |
10 | id: sortProxy |
11 | sortRole: HistoryThreadModel.LastEventTimestampRole |
12 | sourceModel: threadModel |
13 | ascending: false |
14 | + groupingProperty: "participants" |
15 | } |
16 | |
17 | HistoryThreadModel { |
18 | @@ -201,7 +202,6 @@ |
19 | } |
20 | } else { |
21 | var properties = {} |
22 | - properties["threadId"] = threadId |
23 | properties["accountId"] = accountId |
24 | properties["participants"] = participants |
25 | properties["keyboardFocus"] = false |
26 | @@ -215,8 +215,10 @@ |
27 | } |
28 | onSelectionDone: { |
29 | for (var i=0; i < items.count; i++) { |
30 | - var thread = items.get(i).model |
31 | - threadModel.removeThread(thread.accountId, thread.threadId, thread.type) |
32 | + var threads = items.get(i).model.threads |
33 | + for (var j in threads) { |
34 | + threadModel.removeThread(threads[j].accountId, threads[j].threadId, threads[j].type) |
35 | + } |
36 | } |
37 | } |
38 | |
39 | |
40 | === modified file 'src/qml/MessageDelegate.qml' |
41 | --- src/qml/MessageDelegate.qml 2014-07-07 13:11:03 +0000 |
42 | +++ src/qml/MessageDelegate.qml 2014-07-17 21:29:41 +0000 |
43 | @@ -38,6 +38,7 @@ |
44 | property alias selected: internalDelegate.selected |
45 | property variant activeAttachment |
46 | property string mmsText: "" |
47 | + property string accountLabel: "" |
48 | |
49 | anchors.left: parent ? parent.left : undefined |
50 | anchors.right: parent ? parent.right: undefined |
51 | @@ -262,13 +263,26 @@ |
52 | textMessageStatus == HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming && mmsText === "" |
53 | } |
54 | |
55 | + Label { |
56 | + id: accountIndicator |
57 | + anchors { |
58 | + right: bubble.left |
59 | + rightMargin: units.gu(0.5) |
60 | + bottom: bubble.bottom |
61 | + } |
62 | + text: accountLabel |
63 | + visible: !incoming |
64 | + font.pixelSize: FontUtils.sizeToPixels("small") |
65 | + color: "green" |
66 | + } |
67 | + |
68 | // FIXME: this is just a temporary workaround while we dont have the final design |
69 | UbuntuShape { |
70 | id: warningButton |
71 | color: "yellow" |
72 | height: units.gu(3) |
73 | width: units.gu(3) |
74 | - anchors.right: bubble.left |
75 | + anchors.right: accountIndicator.left |
76 | anchors.left: undefined |
77 | anchors.verticalCenter: bubble.verticalCenter |
78 | anchors.leftMargin: 0 |
79 | |
80 | === modified file 'src/qml/Messages.qml' |
81 | --- src/qml/Messages.qml 2014-07-16 15:11:35 +0000 |
82 | +++ src/qml/Messages.qml 2014-07-17 21:29:41 +0000 |
83 | @@ -31,9 +31,8 @@ |
84 | Page { |
85 | id: messages |
86 | objectName: "messagesPage" |
87 | - property string threadId: "" |
88 | - property bool newMessage: threadId === "" |
89 | - // FIXME: we should get the account ID properly when dealing with multiple accounts |
90 | + // FIXME this info must come from system settings or telephony-service |
91 | + property var accounts: {"ofono/ofono/account0": "SIM 1", "ofono/ofono/account1": "SIM 2"} |
92 | property string accountId: telepathyHelper.accountIds[0] |
93 | property variant participants: [] |
94 | property bool groupChat: participants.length > 1 |
95 | @@ -46,6 +45,7 @@ |
96 | property var activeTransfer: null |
97 | property int activeAttachmentIndex: -1 |
98 | property var sharedAttachmentsTransfer: [] |
99 | + property string lastFilter: "" |
100 | property string text: "" |
101 | |
102 | function addAttachmentsToModel(transfer) { |
103 | @@ -64,6 +64,10 @@ |
104 | } |
105 | } |
106 | |
107 | + function checkNetwork() { |
108 | + return telepathyHelper.isAccountConnected(messages.accountId) |
109 | + } |
110 | + |
111 | ListModel { |
112 | id: attachments |
113 | } |
114 | @@ -85,7 +89,7 @@ |
115 | |
116 | flickable: null |
117 | // we need to use isReady here to know if this is a bottom edge page or not. |
118 | - __customHeaderContents: newMessage && isReady ? newMessageHeader : null |
119 | + __customHeaderContents: participants.length === 0 && isReady ? newMessageHeader : null |
120 | property bool isReady: false |
121 | signal ready |
122 | onReady: { |
123 | @@ -112,7 +116,7 @@ |
124 | if (participants.length == 1) { |
125 | return firstRecipient |
126 | } else { |
127 | - return i18n.tr("Group") |
128 | + return i18n.tr("Group (%1 members)").arg(participants.length) |
129 | } |
130 | } |
131 | return i18n.tr("New Message") |
132 | @@ -136,17 +140,37 @@ |
133 | } |
134 | |
135 | Component.onCompleted: { |
136 | - threadId = getCurrentThreadId() |
137 | + updateFilters() |
138 | addAttachmentsToModel(sharedAttachmentsTransfer) |
139 | } |
140 | |
141 | - function getCurrentThreadId() { |
142 | - if (participants.length == 0) |
143 | - return "" |
144 | - return eventModel.threadIdForParticipants(accountId, |
145 | - HistoryThreadModel.EventTypeText, |
146 | - participants, |
147 | - HistoryThreadModel.MatchPhoneNumber) |
148 | + function updateFilters() { |
149 | + if (participants.length == 0) { |
150 | + eventModel.filter = null |
151 | + return |
152 | + } |
153 | + var componentUnion = "import Ubuntu.History 0.1; HistoryUnionFilter { %1 }" |
154 | + var componentFilters = "" |
155 | + for (var i = 0; i < telepathyHelper.accountIds.length; i++) { |
156 | + var filterValue = eventModel.threadIdForParticipants(telepathyHelper.accountIds[i], |
157 | + HistoryThreadModel.EventTypeText, |
158 | + participants, |
159 | + HistoryThreadModel.MatchPhoneNumber) |
160 | + if (filterValue === "") { |
161 | + continue |
162 | + } |
163 | + componentFilters += 'HistoryFilter { filterProperty: "threadId"; filterValue: "%1" } '.arg(filterValue) |
164 | + } |
165 | + if (componentFilters === "") { |
166 | + eventModel.filter = null |
167 | + lastFilter = "" |
168 | + return |
169 | + } |
170 | + if (componentFilters != lastFilter) { |
171 | + var finalString = componentUnion.arg(componentFilters) |
172 | + eventModel.filter = Qt.createQmlObject(finalString, eventModel) |
173 | + lastFilter = componentFilters |
174 | + } |
175 | } |
176 | |
177 | function markMessageAsRead(accountId, threadId, eventId, type) { |
178 | @@ -216,6 +240,65 @@ |
179 | } |
180 | } |
181 | |
182 | + Component { |
183 | + id: noNetworkDialog |
184 | + Dialog { |
185 | + id: dialogue |
186 | + title: i18n.tr("No network") |
187 | + text: telepathyHelper.accountIds.length >= 2 ? i18n.tr("There is currently no network on %1").arg(messages.accounts[messages.accountId]) : i18n.tr("There is currently no network.") |
188 | + Button { |
189 | + objectName: "closeNoNetworkDialog" |
190 | + text: i18n.tr("Close") |
191 | + color: UbuntuColors.orange |
192 | + onClicked: { |
193 | + PopupUtils.close(dialogue) |
194 | + Qt.inputMethod.hide() |
195 | + } |
196 | + } |
197 | + } |
198 | + } |
199 | + |
200 | + Rectangle { |
201 | + id: accountList |
202 | + z: 1 |
203 | + anchors { |
204 | + left: parent.left |
205 | + right: parent.right |
206 | + top: parent.top |
207 | + } |
208 | + height: telepathyHelper.accountIds.length > 1 ? childrenRect.height : 0 |
209 | + color: "white" |
210 | + Row { |
211 | + anchors { |
212 | + top: parent.top |
213 | + horizontalCenter: parent.horizontalCenter |
214 | + } |
215 | + height: childrenRect.height |
216 | + width: childrenRect.width |
217 | + spacing: units.gu(2) |
218 | + Repeater { |
219 | + model: telepathyHelper.accountIds |
220 | + delegate: Label { |
221 | + width: paintedWidth |
222 | + height: paintedHeight |
223 | + text: messages.accounts[modelData] |
224 | + font.pixelSize: FontUtils.sizeToPixels("small") |
225 | + color: messages.accountId == modelData ? "red" : "#5d5d5d" |
226 | + MouseArea { |
227 | + anchors { |
228 | + fill: parent |
229 | + // increase touch area |
230 | + leftMargin: units.gu(-1) |
231 | + rightMargin: units.gu(-1) |
232 | + bottomMargin: units.gu(-1) |
233 | + } |
234 | + onClicked: messages.accountId = modelData |
235 | + } |
236 | + } |
237 | + } |
238 | + } |
239 | + } |
240 | + |
241 | Item { |
242 | id: newMessageHeader |
243 | anchors { |
244 | @@ -223,7 +306,6 @@ |
245 | rightMargin: units.gu(1) |
246 | right: parent.right |
247 | bottom: parent.bottom |
248 | - top: parent.top |
249 | } |
250 | visible: participants.length == 0 && isReady && messages.active |
251 | MultiRecipientInput { |
252 | @@ -248,7 +330,7 @@ |
253 | verticalCenter: parent.verticalCenter |
254 | } |
255 | |
256 | - name: "new-contact" |
257 | + name: "contact" |
258 | color: "gray" |
259 | MouseArea { |
260 | anchors.fill: parent |
261 | @@ -285,7 +367,7 @@ |
262 | ] |
263 | |
264 | anchors { |
265 | - top: parent.top |
266 | + top: accountList.bottom |
267 | topMargin: units.gu(1) |
268 | left: parent.left |
269 | right: parent.right |
270 | @@ -403,7 +485,7 @@ |
271 | } |
272 | |
273 | onParticipantsChanged: { |
274 | - threadId = getCurrentThreadId() |
275 | + updateFilters() |
276 | } |
277 | |
278 | ToolbarItems { |
279 | @@ -447,7 +529,7 @@ |
280 | objectName: "groupChatButton" |
281 | action: Action { |
282 | objectName: "groupChatAction" |
283 | - iconSource: "image://theme/navigation-menu" |
284 | + iconSource: "image://theme/contact-group" |
285 | onTriggered: { |
286 | PopupUtils.open(participantsPopover, messages.header) |
287 | } |
288 | @@ -533,16 +615,7 @@ |
289 | HistoryEventModel { |
290 | id: eventModel |
291 | type: HistoryThreadModel.EventTypeText |
292 | - filter: HistoryIntersectionFilter { |
293 | - HistoryFilter { |
294 | - filterProperty: "threadId" |
295 | - filterValue: threadId |
296 | - } |
297 | - HistoryFilter { |
298 | - filterProperty: "accountId" |
299 | - filterValue: accountId |
300 | - } |
301 | - } |
302 | + filter: null |
303 | sort: HistorySort { |
304 | sortField: "timestamp" |
305 | sortOrder: HistorySort.DescendingOrder |
306 | @@ -551,7 +624,7 @@ |
307 | |
308 | SortProxyModel { |
309 | id: sortProxy |
310 | - sourceModel: eventModel |
311 | + sourceModel: eventModel.filter ? eventModel : null |
312 | sortRole: HistoryEventModel.TimestampRole |
313 | ascending: false |
314 | } |
315 | @@ -561,7 +634,7 @@ |
316 | objectName: "messageList" |
317 | clip: true |
318 | anchors { |
319 | - top: parent.top |
320 | + top: accountList.bottom |
321 | left: parent.left |
322 | right: parent.right |
323 | bottom: bottomPanel.top |
324 | @@ -573,7 +646,7 @@ |
325 | footer: Item { |
326 | height: units.gu(2) |
327 | } |
328 | - listModel: !newMessage ? sortProxy : null |
329 | + listModel: participants.length > 0 ? sortProxy : null |
330 | verticalLayoutDirection: ListView.BottomToTop |
331 | spacing: units.gu(2) |
332 | highlightFollowsCurrentItem: false |
333 | @@ -586,6 +659,7 @@ |
334 | removable: !messages.selectionMode |
335 | selectionMode: messages.selectionMode |
336 | confirmRemoval: true |
337 | + accountLabel: telepathyHelper.accountIds.length > 1 ? messages.accounts[accountId] : "" |
338 | onClicked: { |
339 | if (messageList.isInSelectionMode) { |
340 | if (!messageList.selectItem(messageDelegate)) { |
341 | @@ -624,7 +698,7 @@ |
342 | return |
343 | } |
344 | eventModel.removeEvent(accountId, threadId, eventId, type) |
345 | - chatManager.sendMessage(messages.participants, textMessage, accountId) |
346 | + chatManager.sendMessage(messages.participants, textMessage, messages.accountId) |
347 | } |
348 | } |
349 | onSelectionDone: { |
350 | @@ -666,7 +740,7 @@ |
351 | height: units.gu(3) |
352 | width: units.gu(3) |
353 | color: "gray" |
354 | - name: "camera" |
355 | + name: "camera-app-symbolic" |
356 | MouseArea { |
357 | anchors.fill: parent |
358 | onClicked: { |
359 | @@ -825,6 +899,8 @@ |
360 | placeholderText: i18n.tr("Write a message...") |
361 | focus: textEntry.focus |
362 | font.family: "Ubuntu" |
363 | + font.pixelSize: FontUtils.sizeToPixels("medium") |
364 | + color: "#5d5d5d" |
365 | text: messages.text |
366 | } |
367 | |
368 | @@ -852,10 +928,10 @@ |
369 | text: "Send" |
370 | color: "green" |
371 | width: units.gu(7) |
372 | + height: units.gu(4) |
373 | + font.pixelSize: FontUtils.sizeToPixels("small") |
374 | enabled: { |
375 | - if (!telepathyHelper.connected) |
376 | - return false |
377 | - if (participants.length > 0 || multiRecipient.recipientCount > 0) { |
378 | + if (participants.length > 0 || multiRecipient.recipientCount > 0) { |
379 | if (textEntry.text != "" || textEntry.inputMethodComposing || attachments.count > 0) { |
380 | return true |
381 | } |
382 | @@ -863,26 +939,32 @@ |
383 | return false |
384 | } |
385 | onClicked: { |
386 | + if (!checkNetwork()) { |
387 | + Qt.inputMethod.hide() |
388 | + PopupUtils.open(noNetworkDialog) |
389 | + return |
390 | + } |
391 | // make sure we flush everything we have prepared in the OSK preedit |
392 | Qt.inputMethod.commit(); |
393 | if (textEntry.text == "" && attachments.count == 0) { |
394 | return |
395 | } |
396 | - if (participants.length == 0 && multiRecipient.recipientCount > 0) { |
397 | - participants = multiRecipient.recipients |
398 | - } |
399 | if (messages.accountId == "") { |
400 | // FIXME: handle dual sim |
401 | messages.accountId = telepathyHelper.accountIds[0] |
402 | } |
403 | - if (messages.newMessage) { |
404 | - // create the new thread and get the threadId |
405 | - messages.threadId = eventModel.threadIdForParticipants(messages.accountId, |
406 | - HistoryThreadModel.EventTypeText, |
407 | - participants, |
408 | - HistoryThreadModel.MatchPhoneNumber, |
409 | - true) |
410 | + // dont change the participants list |
411 | + if (participants.length == 0) { |
412 | + participants = multiRecipient.recipients |
413 | } |
414 | + // create the new thread and update the threadId list |
415 | + eventModel.threadIdForParticipants(messages.accountId, |
416 | + HistoryThreadModel.EventTypeText, |
417 | + participants, |
418 | + HistoryThreadModel.MatchPhoneNumber, |
419 | + true) |
420 | + |
421 | + updateFilters() |
422 | messages.pendingMessage = true |
423 | if (attachments.count > 0) { |
424 | var newAttachments = [] |
425 | |
426 | === modified file 'src/qml/NewRecipientPage.qml' |
427 | --- src/qml/NewRecipientPage.qml 2014-07-16 15:11:35 +0000 |
428 | +++ src/qml/NewRecipientPage.qml 2014-07-17 21:29:41 +0000 |
429 | @@ -42,7 +42,7 @@ |
430 | } |
431 | onTextChanged: contactList.currentIndex = -1 |
432 | inputMethodHints: Qt.ImhNoPredictiveText |
433 | - placeholderText: i18n.tr("Type a name or phone to search") |
434 | + placeholderText: i18n.tr("Type to search by name or number") |
435 | } |
436 | |
437 | ContactListView { |
438 | |
439 | === modified file 'src/qml/ThreadDelegate.qml' |
440 | --- src/qml/ThreadDelegate.qml 2014-07-06 22:06:24 +0000 |
441 | +++ src/qml/ThreadDelegate.qml 2014-07-17 21:29:41 +0000 |
442 | @@ -180,7 +180,9 @@ |
443 | font.weight: Font.Light |
444 | } |
445 | onItemRemoved: { |
446 | - threadModel.removeThread(accountId, threadId, type) |
447 | + for (var i in threads) { |
448 | + threadModel.removeThread(threads[i].accountId, threads[i].threadId, threads[i].type) |
449 | + } |
450 | } |
451 | |
452 | Item { |
453 | |
454 | === modified file 'tests/autopilot/messaging_app/emulators.py' |
455 | --- tests/autopilot/messaging_app/emulators.py 2014-07-15 16:32:01 +0000 |
456 | +++ tests/autopilot/messaging_app/emulators.py 2014-07-17 21:29:41 +0000 |
457 | @@ -449,7 +449,7 @@ |
458 | ThreadDelegate, objectName='thread{}'.format(participants)) |
459 | self.pointing_device.click_object(thread) |
460 | root = self.get_root_instance() |
461 | - return root.wait_select_single(Messages, threadId=thread.threadId) |
462 | + return root.wait_select_single(Messages, participants=participants) |
463 | |
464 | |
465 | class Messages(toolkit_emulators.UbuntuUIToolkitEmulatorBase): |
The code is looking good, there are just a few minor things that need to be fixed. Please check the inline diff comments.