Merge lp:~renatofilho/messaging-app/rtm-fit-finish2 into lp:messaging-app

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Tiago Salem Herrmann
Approved revision: 245
Merged at revision: 189
Proposed branch: lp:~renatofilho/messaging-app/rtm-fit-finish2
Merge into: lp:messaging-app
Prerequisite: lp:~tiagosh/messaging-app/dual-sim-settings
Diff against target: 2189 lines (+955/-652)
26 files modified
src/qml/KeyboardRectangle.qml (+1/-1)
src/qml/MMS/MMSBase.qml (+5/-74)
src/qml/MMS/MMSContact.qml (+58/-78)
src/qml/MMS/MMSDefault.qml (+3/-41)
src/qml/MMS/MMSImage.qml (+42/-24)
src/qml/MMS/MMSVideo.qml (+5/-40)
src/qml/MMS/Previewer.qml (+2/-2)
src/qml/MMS/PreviewerContact.qml (+5/-3)
src/qml/MMS/PreviewerImage.qml (+2/-2)
src/qml/MMS/PreviewerVideo.qml (+2/-2)
src/qml/MMSDelegate.qml (+198/-0)
src/qml/MainPage.qml (+1/-1)
src/qml/MessageBubble.qml (+27/-19)
src/qml/MessageDateSection.qml (+38/-0)
src/qml/MessageDelegate.qml (+39/-235)
src/qml/MessageDelegateFactory.qml (+203/-0)
src/qml/MessageInfoDialog.qml (+124/-0)
src/qml/Messages.qml (+80/-100)
src/qml/MultiRecipientInput.qml (+1/-1)
src/qml/NewRecipientPage.qml (+1/-1)
src/qml/SMSDelegate.qml (+75/-0)
src/qml/StandardAnimation.qml (+1/-1)
src/qml/ThreadDelegate.qml (+29/-13)
src/qml/messaging-app.qml (+2/-2)
tests/autopilot/messaging_app/emulators.py (+6/-7)
tests/qml/tst_MessageBubble.qml (+5/-5)
To merge this branch: bzr merge lp:~renatofilho/messaging-app/rtm-fit-finish2
Reviewer Review Type Date Requested Status
Tiago Salem Herrmann (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+230504@code.launchpad.net

This proposal supersedes a proposal from 2014-07-31.

Commit message

- Fixed wrong icon for group chat
- Implemented handling of not sent sms/mms swipe for more options
- RETRY for failed messages should go as well into the left tug
- Move selection tick to the center of the item
- Set a limit for message input field maximum height
- Once user types in a name into the “add contact” field and there is a matching list, the “compose message” entry field can disappear
- Handle the message as only one item for swipe acctions
- Created sections for dates on chat window
- Fixed vcard attachment visuals based on designer spec
- Make timestamp visible on image attachments if it is the only item of the message
- Display Account name together with timestamp (Temporary solution)
- Show message info dialog

Description of the change

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Renato Araujo Oliveira Filho (renatofilho) wrote :

Are there any related MPs required for this MP to build/function as expected? YES
  - lp:~tiagosh/messaging-app/dual-sim-settings
  - https://code.launchpad.net/~renatofilho/history-service/export-qml-sortproxymodel/+merge/229802

Is your branch in sync with latest trunk? 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 on device or emulator? YES

If you changed the UI, was the change specified/approved by design? YES

If you changed UI labels, did you update the pot file? NO PACKAGE CHANGE
If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP?

Revision history for this message
Tiago Salem Herrmann (tiagosh) 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

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/qml/KeyboardRectangle.qml'
2--- src/qml/KeyboardRectangle.qml 2014-07-25 16:22:54 +0000
3+++ src/qml/KeyboardRectangle.qml 2014-08-12 15:32:18 +0000
4@@ -16,7 +16,7 @@
5 * along with this program. If not, see <http://www.gnu.org/licenses/>.
6 */
7
8-import QtQuick 2.0
9+import QtQuick 2.2
10
11 Item {
12 id: keyboardRect
13
14=== modified file 'src/qml/MMS/MMSBase.qml'
15--- src/qml/MMS/MMSBase.qml 2014-07-31 19:58:34 +0000
16+++ src/qml/MMS/MMSBase.qml 2014-08-12 15:32:18 +0000
17@@ -16,82 +16,13 @@
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 import QtQuick 2.2
21-import Ubuntu.Components 1.1
22-import Ubuntu.Contacts 0.1
23
24-ListItemWithActions {
25+Item {
26 id: baseDelegate
27
28 property var attachment
29- property bool parentSelected: false
30- property bool incoming
31- property bool showInfo: false
32-
33- signal itemRemoved()
34- signal attachmentClicked()
35-
36- function checkClick(bubble, mouse) {
37- var itemX1 = bubble.x
38- var itemX2 = itemX1+bubble.width
39- var itemY1 = bubble.y
40- var itemY2 = itemY1+bubble.height
41- if (mouse.x >= itemX1 && mouse.x <= itemX2 &&
42- mouse.y >= itemY1 && mouse.y <= itemY2) {
43- return true
44- }
45- return false
46- }
47-
48- Component.onCompleted: {
49- visibleAttachments++
50- }
51- Component.onDestruction: {
52- visibleAttachments--
53- }
54-
55- leftSideAction: Action {
56- iconName: "delete"
57- text: i18n.tr("Delete")
58- onTriggered: baseDelegate.itemRemoved()
59- }
60-
61- internalAnchors {
62- topMargin: 0
63- bottomMargin: 0
64- }
65-
66- color: parentSelected ? selectedColor : Theme.palette.normal.background
67- states: [
68- State {
69- when: incoming
70- name: "incoming"
71- AnchorChanges {
72- target: bubble
73- anchors.left: parent.left
74- anchors.right: undefined
75- }
76- PropertyChanges {
77- target: bubble
78- anchors.leftMargin: units.gu(1)
79- anchors.rightMargin: 0
80- }
81- },
82- State {
83- when: !incoming
84- name: "outgoing"
85- AnchorChanges {
86- target: bubble
87- anchors.left: undefined
88- anchors.right: parent.right
89- }
90- PropertyChanges {
91- target: bubble
92- anchors.leftMargin: 0
93- anchors.rightMargin: units.gu(1)
94- }
95- }
96- ]
97-
98- onSwippingChanged: messageList.updateSwippedItem(baseDelegate)
99- onSwipeStateChanged: messageList.updateSwippedItem(baseDelegate)
100+ property string previewer
101+ property bool incoming: false
102+ property bool lastItem: false
103+ property string timestamp
104 }
105
106=== modified file 'src/qml/MMS/MMSContact.qml'
107--- src/qml/MMS/MMSContact.qml 2014-07-31 19:01:23 +0000
108+++ src/qml/MMS/MMSContact.qml 2014-08-12 15:32:18 +0000
109@@ -16,93 +16,73 @@
110 * along with this program. If not, see <http://www.gnu.org/licenses/>.
111 */
112
113-import QtQuick 2.0
114-import Ubuntu.Components 0.1
115+import QtQuick 2.2
116+import Ubuntu.Components 1.1
117 import Ubuntu.Contacts 0.1
118-import ".."
119+import Ubuntu.History 0.1
120
121 MMSBase {
122 id: vcardDelegate
123- property string previewer: "MMS/PreviewerContact.qml"
124- onItemClicked: {
125- if (checkClick(bubble, mouse)) {
126- attachmentClicked()
127- }
128- }
129- states: [
130- State {
131- name: "incoming"
132- AnchorChanges {
133- target: bubble
134- anchors.left: parent.left
135- anchors.right: undefined
136- }
137- PropertyChanges {
138- target: bubble
139- anchors.leftMargin: units.gu(1)
140- anchors.rightMargin: units.gu(1)
141- }
142- AnchorChanges {
143- target: contactName
144- anchors.left: bubble.right
145- anchors.right: undefined
146- }
147- PropertyChanges {
148- target: contactName
149- anchors.leftMargin: units.gu(2)
150- anchors.rightMargin: units.gu(2)
151- }
152- },
153- State {
154- name: "outgoing"
155- AnchorChanges {
156- target: bubble
157- anchors.left: undefined
158- anchors.right: parent.right
159- }
160- PropertyChanges {
161- target: bubble
162- anchors.leftMargin: units.gu(1)
163- anchors.rightMargin: units.gu(1)
164- }
165- AnchorChanges {
166- target: contactName
167- anchors.left: undefined
168- anchors.right: bubble.left
169- }
170- PropertyChanges {
171- target: contactName
172- anchors.leftMargin: units.gu(2)
173- anchors.rightMargin: units.gu(2)
174- }
175- }
176- ]
177- height: bubble.height + units.gu(2)
178- Item {
179+
180+ readonly property bool error: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
181+ readonly property bool sending: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||
182+ textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming
183+
184+ previewer: "MMS/PreviewerContact.qml"
185+ height: units.gu(8)
186+ width: units.gu(27)
187+
188+ Rectangle {
189 id: bubble
190- anchors.top: parent.top
191- width: avatar.width
192- height: avatar.height
193+
194+ anchors.fill: parent
195+ color: {
196+ if (error) {
197+ return "#fc4949"
198+ } else if (sending) {
199+ return "#b2b2b2"
200+ } else if (incoming) {
201+ return "#ffffff"
202+ } else {
203+ return "#3fb24f"
204+ }
205+ }
206+ radius: height * 0.1
207+
208 ContactAvatar {
209 id: avatar
210
211+ anchors {
212+ top: parent.top
213+ topMargin: units.gu(1)
214+ bottom: parent.bottom
215+ bottomMargin: units.gu(1)
216+ left: parent.left
217+ leftMargin: units.gu(1)
218+ }
219 fallbackAvatarUrl: "image://theme/contact"
220 fallbackDisplayName: contactName.name
221- anchors.centerIn: parent
222- height: units.gu(6)
223- width: units.gu(6)
224- }
225- }
226- Label {
227- id: contactName
228- property string name: application.contactNameFromVCard(attachment.filePath)
229- anchors.bottom: bubble.bottom
230- anchors.left: incoming ? bubble.right : undefined
231- anchors.right: !incoming ? bubble.left : undefined
232- anchors.rightMargin: !incoming ? units.gu(1) : undefined
233- anchors.leftMargin: incoming ? units.gu(1) : undefined
234- text: name !== "" ? name : i18n.tr("Unknown contact")
235- height: paintedHeight
236- width: paintedWidth
237+ width: height
238+ }
239+
240+ Label {
241+ id: contactName
242+
243+ property string name: application.contactNameFromVCard(attachment.filePath)
244+
245+ anchors {
246+ left: avatar.right
247+ leftMargin: units.gu(1)
248+ top: avatar.top
249+ bottom: avatar.bottom
250+ right: parent.right
251+ rightMargin: units.gu(1)
252+ }
253+
254+ verticalAlignment: Text.AlignVCenter
255+ text: name !== "" ? name : i18n.tr("Unknown contact")
256+ elide: Text.ElideRight
257+ color: vcardDelegate.incoming ? UbuntuColors.darkGrey : "#ffffff"
258+ }
259 }
260 }
261
262=== modified file 'src/qml/MMS/MMSDefault.qml'
263--- src/qml/MMS/MMSDefault.qml 2014-07-31 19:01:23 +0000
264+++ src/qml/MMS/MMSDefault.qml 2014-08-12 15:32:18 +0000
265@@ -16,54 +16,16 @@
266 * along with this program. If not, see <http://www.gnu.org/licenses/>.
267 */
268
269-import QtQuick 2.0
270-import Ubuntu.Components 0.1
271+import QtQuick 2.2
272+import Ubuntu.Components 1.1
273 import ".."
274
275 MMSBase {
276 id: defaultDelegate
277- property var attachment
278- property bool incoming
279- property string previewer: ""
280- property string textColor: incoming ? "#333333" : "#ffffff"
281+
282 anchors.left: parent.left
283 anchors.right: parent.right
284- onItemClicked: {
285- if (checkClick(bubble, mouse)) {
286- attachmentClicked()
287- }
288- }
289- state: incoming ? "incoming" : "outgoing"
290- states: [
291- State {
292- name: "incoming"
293- AnchorChanges {
294- target: bubble
295- anchors.left: parent.left
296- anchors.right: undefined
297- }
298- PropertyChanges {
299- target: bubble
300- anchors.leftMargin: units.gu(1)
301- anchors.rightMargin: units.gu(1)
302- }
303- },
304- State {
305- name: "outgoing"
306- AnchorChanges {
307- target: bubble
308- anchors.left: undefined
309- anchors.right: parent.right
310- }
311- PropertyChanges {
312- target: bubble
313- anchors.leftMargin: units.gu(1)
314- anchors.rightMargin: units.gu(1)
315- }
316- }
317- ]
318 height: bubble.height + units.gu(1)
319- clip: true
320 Item {
321 id: bubble
322 anchors.top: parent.top
323
324=== modified file 'src/qml/MMS/MMSImage.qml'
325--- src/qml/MMS/MMSImage.qml 2014-07-31 19:01:23 +0000
326+++ src/qml/MMS/MMSImage.qml 2014-08-12 15:32:18 +0000
327@@ -16,27 +16,19 @@
328 * along with this program. If not, see <http://www.gnu.org/licenses/>.
329 */
330
331-import QtQuick 2.0
332+import QtQuick 2.2
333 import Ubuntu.Components 1.1
334-import Ubuntu.Contacts 0.1
335-import ".."
336
337 MMSBase {
338 id: imageDelegate
339- property string previewer: "MMS/PreviewerImage.qml"
340- onItemClicked: {
341- if (checkClick(bubble, mouse)) {
342- attachmentClicked()
343- }
344- }
345
346+ previewer: "MMS/PreviewerImage.qml"
347 height: imageAttachment.height
348+ width: imageAttachment.width
349+
350 UbuntuShape {
351 id: bubble
352- anchors {
353- top: parent.top
354- bottom: parent.bottom
355- }
356+ anchors.top: parent.top
357 width: image.width
358 height: image.height
359
360@@ -49,16 +41,42 @@
361 smooth: true
362 source: attachment.filePath
363 visible: false
364- }
365- }
366-
367- Loader {
368- active: (index == visibleAttachments-1) && !incoming && mmsText == "" && (inProgress || failed)
369- visible: active
370- height: active ? item.height : 0
371- sourceComponent: statusIcon
372- anchors.right: bubble.left
373- anchors.rightMargin: units.gu(1)
374- anchors.verticalCenter: bubble.verticalCenter
375+ asynchronous: true
376+
377+ onStatusChanged: {
378+ if (status === Image.Error) {
379+ source = "image://theme/image-missing"
380+ width = 128
381+ height = 128
382+ }
383+ }
384+ }
385+
386+ Rectangle {
387+ visible: imageDelegate.lastItem
388+ gradient: Gradient {
389+ GradientStop { position: 0.0; color: "transparent" }
390+ GradientStop { position: 1.0; color: "gray" }
391+ }
392+
393+ anchors {
394+ bottom: parent.bottom
395+ left: parent.left
396+ right: parent.right
397+ }
398+ height: units.gu(2)
399+ radius: bubble.height * 0.1
400+ Label {
401+ anchors{
402+ left: parent.left
403+ bottom: parent.bottom
404+ leftMargin: incoming ? units.gu(2) : units.gu(1)
405+ bottomMargin: units.gu(0.5)
406+ }
407+ fontSize: "xx-small"
408+ text: Qt.formatDateTime(timestamp, "hh:mm AP")
409+ color: "white"
410+ }
411+ }
412 }
413 }
414
415=== modified file 'src/qml/MMS/MMSVideo.qml'
416--- src/qml/MMS/MMSVideo.qml 2014-07-31 19:01:23 +0000
417+++ src/qml/MMS/MMSVideo.qml 2014-08-12 15:32:18 +0000
418@@ -16,54 +16,19 @@
419 * along with this program. If not, see <http://www.gnu.org/licenses/>.
420 */
421
422-import QtQuick 2.0
423-import Ubuntu.Components 0.1
424+import QtQuick 2.2
425+import Ubuntu.Components 1.1
426 import QtMultimedia 5.0
427 import ".."
428
429 MMSBase {
430 id: videoDelegate
431- property var attachment
432- property bool incoming
433- property string previewer: "MMS/PreviewerVideo.qml"
434+
435+ previewer: "MMS/PreviewerVideo.qml"
436 anchors.left: parent.left
437 anchors.right: parent.right
438- onItemClicked: {
439- if (checkClick(bubble, mouse)) {
440- attachmentClicked()
441- }
442- }
443- state: incoming ? "incoming" : "outgoing"
444- states: [
445- State {
446- name: "incoming"
447- AnchorChanges {
448- target: bubble
449- anchors.left: parent.left
450- anchors.right: undefined
451- }
452- PropertyChanges {
453- target: bubble
454- anchors.leftMargin: units.gu(1)
455- anchors.rightMargin: units.gu(1)
456- }
457- },
458- State {
459- name: "outgoing"
460- AnchorChanges {
461- target: bubble
462- anchors.left: undefined
463- anchors.right: parent.right
464- }
465- PropertyChanges {
466- target: bubble
467- anchors.leftMargin: units.gu(1)
468- anchors.rightMargin: units.gu(1)
469- }
470- }
471- ]
472 height: bubble.height + units.gu(1)
473- clip: true
474+
475 Item {
476 id: bubble
477 anchors.top: parent.top
478
479=== modified file 'src/qml/MMS/Previewer.qml'
480--- src/qml/MMS/Previewer.qml 2014-06-13 19:39:49 +0000
481+++ src/qml/MMS/Previewer.qml 2014-08-12 15:32:18 +0000
482@@ -16,8 +16,8 @@
483 * along with this program. If not, see <http://www.gnu.org/licenses/>.
484 */
485
486-import QtQuick 2.0
487-import Ubuntu.Components 0.1
488+import QtQuick 2.2
489+import Ubuntu.Components 1.1
490 import Ubuntu.Content 0.1
491 import ".."
492
493
494=== modified file 'src/qml/MMS/PreviewerContact.qml'
495--- src/qml/MMS/PreviewerContact.qml 2014-07-30 18:23:16 +0000
496+++ src/qml/MMS/PreviewerContact.qml 2014-08-12 15:32:18 +0000
497@@ -16,12 +16,14 @@
498 * along with this program. If not, see <http://www.gnu.org/licenses/>.
499 */
500
501-import QtQuick 2.0
502-import Ubuntu.Components 0.1
503+import QtQuick 2.2
504+import Ubuntu.Components 1.1
505 import Ubuntu.Content 0.1
506 import ".."
507
508 Previewer {
509- title: application.contactNameFromVCard(attachment.filePath)
510+ property string contactName: application.contactNameFromVCard(attachment.filePath)
511+
512+ title: contactName !== "" ? contactName : i18n.tr("Unknown contact")
513 clip: true
514 }
515
516=== modified file 'src/qml/MMS/PreviewerImage.qml'
517--- src/qml/MMS/PreviewerImage.qml 2014-06-13 19:39:49 +0000
518+++ src/qml/MMS/PreviewerImage.qml 2014-08-12 15:32:18 +0000
519@@ -16,8 +16,8 @@
520 * along with this program. If not, see <http://www.gnu.org/licenses/>.
521 */
522
523-import QtQuick 2.0
524-import Ubuntu.Components 0.1
525+import QtQuick 2.2
526+import Ubuntu.Components 1.1
527 import Ubuntu.Content 0.1
528 import ".."
529
530
531=== modified file 'src/qml/MMS/PreviewerVideo.qml'
532--- src/qml/MMS/PreviewerVideo.qml 2014-05-30 21:16:51 +0000
533+++ src/qml/MMS/PreviewerVideo.qml 2014-08-12 15:32:18 +0000
534@@ -16,8 +16,8 @@
535 * along with this program. If not, see <http://www.gnu.org/licenses/>.
536 */
537
538-import QtQuick 2.0
539-import Ubuntu.Components 0.1
540+import QtQuick 2.2
541+import Ubuntu.Components 1.1
542 import QtMultimedia 5.0
543 import ".."
544
545
546=== added file 'src/qml/MMSDelegate.qml'
547--- src/qml/MMSDelegate.qml 1970-01-01 00:00:00 +0000
548+++ src/qml/MMSDelegate.qml 2014-08-12 15:32:18 +0000
549@@ -0,0 +1,198 @@
550+/*
551+ * Copyright 2012, 2013, 2014 Canonical Ltd.
552+ *
553+ * This file is part of messaging-app.
554+ *
555+ * messaging-app is free software; you can redistribute it and/or modify
556+ * it under the terms of the GNU General Public License as published by
557+ * the Free Software Foundation; version 3.
558+ *
559+ * messaging-app is distributed in the hope that it will be useful,
560+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
561+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
562+ * GNU General Public License for more details.
563+ *
564+ * You should have received a copy of the GNU General Public License
565+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
566+ */
567+
568+import QtQuick 2.2
569+import Ubuntu.Components 1.1
570+
571+MessageDelegate {
572+ id: root
573+
574+ property var dataAttachments: []
575+ property var textAttachements: []
576+
577+ function clicked(mouse)
578+ {
579+ var childPoint = root.mapToItem(attachmentsView, mouse.x, mouse.y)
580+ var attachment = attachmentsView.childAt(childPoint.x, childPoint.y)
581+ if (attachment && attachment.item && attachment.item.previewer) {
582+ var properties = {}
583+ properties["attachment"] = attachment.item.attachment
584+ mainStack.push(Qt.resolvedUrl(attachment.item.previewer), properties)
585+ }
586+ }
587+
588+ function deleteMessage()
589+ {
590+ eventModel.removeEvent(accountId, threadId, eventId, type)
591+ }
592+
593+ function resendMessage()
594+ {
595+ var newAttachments = []
596+ for (var i = 0; i < attachments.length; i++) {
597+ var attachment = []
598+ var item = textMessageAttachments[i]
599+ // we dont include smil files. they will be auto generated
600+ if (item.contentType.toLowerCase() === "application/smil") {
601+ continue
602+ }
603+ attachment.push(item.attachmentId)
604+ attachment.push(item.contentType)
605+ attachment.push(item.filePath)
606+ newAttachments.push(attachment)
607+ }
608+ eventModel.removeEvent(accountId, threadId, eventId, type)
609+ chatManager.sendMMS(participants, textMessage, newAttachments, messages.accountId)
610+ }
611+
612+ function copyMessage()
613+ {
614+ if (bubble.visible) {
615+ Clipboard.push(bubble.messageText)
616+ }
617+ }
618+
619+ onAttachmentsChanged: {
620+ dataAttachments = []
621+ textAttachements = []
622+ for (var i=0; i < attachments.length; i++) {
623+ var attachment = attachments[i]
624+ if (startsWith(attachment.contentType, "text/plain") ) {
625+ textAttachements.push(attachment)
626+ } else if (startsWith(attachment.contentType, "image/")) {
627+ dataAttachments.push({"type": "image",
628+ "data": attachment,
629+ "delegateSource": "MMS/MMSImage.qml",
630+ })
631+ } else if (startsWith(attachment.contentType, "video/")) {
632+ // TODO: implement proper video attachment support
633+ // dataAttachments.push({type: "video",
634+ // data: attachment,
635+ // delegateSource: "MMS/MMSVideo.qml",
636+ // })
637+ } else if (startsWith(attachment.contentType, "application/smil") ||
638+ startsWith(attachment.contentType, "application/x-smil")) {
639+ // TODO: implement support for this kind of attachment
640+ // dataAttachments.push({type: "application",
641+ // data: attachment,
642+ // delegateSource: "",
643+ // })
644+ } else if (startsWith(attachment.contentType, "text/vcard") ||
645+ startsWith(attachment.contentType, "text/x-vcard")) {
646+ dataAttachments.push({"type": "vcard",
647+ "data": attachment,
648+ "delegateSource": "MMS/MMSContact.qml"
649+ })
650+ } else {
651+ console.log("No MMS render for " + attachment.contentType)
652+ }
653+ }
654+ }
655+ height: attachmentsView.height
656+ _lastItem: bubble.visible ? bubble : attachmentsRepeater.itemAt(attachmentsRepeater - 1)
657+ Column {
658+ id: attachmentsView
659+
660+ anchors {
661+ top: parent.top
662+ left: parent.left
663+ right: parent.right
664+ }
665+ height: childrenRect.height
666+
667+ Repeater {
668+ id: attachmentsRepeater
669+ model: dataAttachments
670+
671+ Loader {
672+ id: attachmentLoader
673+ asynchronous: true
674+ states: [
675+ State {
676+ when: root.incoming
677+ name: "incoming"
678+ AnchorChanges {
679+ target: attachmentLoader
680+ anchors.left: parent.left
681+ }
682+ PropertyChanges {
683+ target: attachmentLoader
684+ anchors.leftMargin: units.gu(1)
685+ anchors.rightMargin: 0
686+ }
687+ },
688+ State {
689+ when: !root.incoming
690+ name: "outgoing"
691+ AnchorChanges {
692+ target: attachmentLoader
693+ anchors.right: parent.right
694+ }
695+ PropertyChanges {
696+ target: attachmentLoader
697+ anchors.leftMargin: 0
698+ anchors.rightMargin: units.gu(1)
699+ }
700+ }
701+ ]
702+
703+ Component.onCompleted: {
704+ var initialProperties = {
705+ "incoming": root.incoming,
706+ "attachment": modelData.data,
707+ "timestamp": timestamp,
708+ "lastItem": (index === (attachmentsRepeater.count - 1)) && (textAttachements.length === 0)
709+ }
710+ setSource(modelData.delegateSource, initialProperties)
711+ }
712+ }
713+ }
714+
715+ // TODO: is possible to have more than one text ???
716+ MessageBubble {
717+ id: bubble
718+
719+ property string textData: application.readTextFile(root.textAttachements[0].filePath)
720+
721+ states: [
722+ State {
723+ when: root.incoming
724+ name: "incoming"
725+ AnchorChanges {
726+ target: bubble
727+ anchors.left: parent.left
728+ }
729+ },
730+ State {
731+ name: "outgoing"
732+ when: !root.incoming
733+ AnchorChanges {
734+ target: bubble
735+ anchors.right: parent.right
736+ }
737+ }
738+ ]
739+ visible: (root.textAttachements.length > 0)
740+ messageText: textData.length > 0 ? textData : i18n.tr("Missing message data")
741+ messageTimeStamp: root.timestamp
742+ messageStatus: textMessageStatus
743+ messageIncoming: root.incoming
744+ accountName: root.accountLabel
745+ }
746+ }
747+}
748
749=== modified file 'src/qml/MainPage.qml'
750--- src/qml/MainPage.qml 2014-08-12 15:32:18 +0000
751+++ src/qml/MainPage.qml 2014-08-12 15:32:18 +0000
752@@ -16,7 +16,7 @@
753 * along with this program. If not, see <http://www.gnu.org/licenses/>.
754 */
755
756-import QtQuick 2.0
757+import QtQuick 2.2
758 import Ubuntu.Components 1.1
759 import Ubuntu.Components.ListItems 0.1 as ListItem
760 import Ubuntu.History 0.1
761
762=== modified file 'src/qml/MessageBubble.qml'
763--- src/qml/MessageBubble.qml 2014-08-01 02:36:29 +0000
764+++ src/qml/MessageBubble.qml 2014-08-12 15:32:18 +0000
765@@ -27,15 +27,16 @@
766 id: root
767
768 property int messageStatus: -1
769- property bool incoming: false
770+ property bool messageIncoming: false
771 property alias sender: senderName.text
772 property string messageText
773 property var messageTimeStamp
774- property int maxDelegateWidth: units.gu(30)
775+ property int maxDelegateWidth: units.gu(27)
776+ property string accountName
777
778 readonly property bool error: (messageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
779 readonly property bool sending: (messageStatus === HistoryThreadModel.MessageStatusUnknown ||
780- messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming
781+ messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !messageIncoming
782
783 function selectBubble() {
784 var fileName = "assets/conversation_";
785@@ -43,7 +44,7 @@
786 fileName += "error.sci"
787 } else if (sending) {
788 fileName += "pending.sci"
789- } else if (incoming) {
790+ } else if (messageIncoming) {
791 fileName += "incoming.sci";
792 } else {
793 fileName += "outgoing.sci";
794@@ -63,11 +64,11 @@
795 return text.replace(phoneExp, '<a href="tel:///$1">$1</a>');
796 }
797
798- onIncomingChanged: source = selectBubble()
799+ onMessageIncomingChanged: source = selectBubble()
800 source: selectBubble()
801- height: childrenRect.height + units.gu(2)
802+ height: senderName.height + textLabel.height + textTimestamp.height + units.gu(3)
803 width: Math.min(units.gu(27),
804- Math.max(textLabel.text.length, textTimestamp.text.length) * units.gu(1))
805+ Math.max(textLabel.contentWidth, textTimestamp.contentWidth))
806 + border.left + border.right
807 Label {
808 id: senderName
809@@ -76,7 +77,7 @@
810 top: parent.top
811 topMargin: units.gu(1)
812 left: parent.left
813- leftMargin: incoming ? units.gu(2) : units.gu(1)
814+ leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
815 }
816 height: text === "" ? 0 : paintedHeight
817 fontSize: "large"
818@@ -91,17 +92,15 @@
819 top: sender == "" ? parent.top : senderName.bottom
820 topMargin: units.gu(1)
821 left: parent.left
822- leftMargin: incoming ? units.gu(2) : units.gu(1)
823- right: parent.right
824- rightMargin: incoming ? units.gu(1) : units.gu(1)
825+ leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
826 }
827 width: maxDelegateWidth
828 fontSize: "medium"
829- height: text === "" ? 0 : paintedHeight
830+ height: contentHeight
831 onLinkActivated: Qt.openUrlExternally(link)
832 text: root.parseText(messageText)
833 wrapMode: Text.Wrap
834- color: root.incoming ? UbuntuColors.darkGrey : "white"
835+ color: root.messageIncoming ? UbuntuColors.darkGrey : "white"
836 }
837
838 Label {
839@@ -110,16 +109,25 @@
840
841 anchors{
842 top: textLabel.bottom
843- topMargin: units.gu(0.5)
844+ topMargin: units.gu(1)
845 left: parent.left
846- leftMargin: incoming ? units.gu(2) : units.gu(1)
847+ leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
848 }
849
850 visible: !root.sending
851- height: visible ? paintedHeight : 0
852+ height: units.gu(2)
853+ width: visible ? maxDelegateWidth : 0
854 fontSize: "xx-small"
855- color: root.incoming ? UbuntuColors.lightGrey : "white"
856- opacity: root.incoming ? 1.0 : 0.8
857- text: Qt.formatDateTime(messageTimeStamp, "hh:mm AP")
858+ color: root.messageIncoming ? UbuntuColors.lightGrey : "white"
859+ opacity: root.messageIncoming ? 1.0 : 0.8
860+ elide: Text.ElideRight
861+ text: {
862+ var str = Qt.formatDateTime(messageTimeStamp, "hh:mm AP")
863+ if (root.accountName.length === 0) {
864+ return str
865+ }
866+ str += " @ %1".arg(root.accountName)
867+ return str
868+ }
869 }
870 }
871
872=== added file 'src/qml/MessageDateSection.qml'
873--- src/qml/MessageDateSection.qml 1970-01-01 00:00:00 +0000
874+++ src/qml/MessageDateSection.qml 2014-08-12 15:32:18 +0000
875@@ -0,0 +1,38 @@
876+/*
877+ * Copyright 2012, 2013, 2014 Canonical Ltd.
878+ *
879+ * This file is part of messaging-app.
880+ *
881+ * messaging-app is free software; you can redistribute it and/or modify
882+ * it under the terms of the GNU General Public License as published by
883+ * the Free Software Foundation; version 3.
884+ *
885+ * messaging-app is distributed in the hope that it will be useful,
886+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
887+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
888+ * GNU General Public License for more details.
889+ *
890+ * You should have received a copy of the GNU General Public License
891+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
892+ */
893+
894+import QtQuick 2.2
895+import Ubuntu.Components 1.1
896+import Ubuntu.Components.ListItems 0.1 as ListItem
897+
898+Item {
899+ property alias text: label.text
900+
901+ height: units.gu(3)
902+ Label {
903+ id: label
904+
905+ anchors.fill: parent
906+ elide: Text.ElideRight
907+ verticalAlignment: Text.AlignVCenter
908+ fontSize: "small"
909+ }
910+ ListItem.ThinDivider {
911+ anchors.bottom: parent.bottom
912+ }
913+}
914
915=== modified file 'src/qml/MessageDelegate.qml'
916--- src/qml/MessageDelegate.qml 2014-07-31 19:58:54 +0000
917+++ src/qml/MessageDelegate.qml 2014-08-12 15:32:18 +0000
918@@ -16,242 +16,46 @@
919 * along with this program. If not, see <http://www.gnu.org/licenses/>.
920 */
921
922-import QtQuick 2.0
923-import Ubuntu.Components 1.1
924-import Ubuntu.Components.Popups 0.1
925-import Ubuntu.History 0.1
926-import Ubuntu.Telephony 0.1
927-import Ubuntu.Content 0.1
928-import Ubuntu.Contacts 0.1
929-
930-import "dateUtils.js" as DateUtils
931+import QtQuick 2.2
932
933 Item {
934 id: messageDelegate
935-
936- property alias incoming: bubble.incoming
937- property string textColor: incoming ? "#333333" : "white"
938- property bool unread: false
939- property variant activeAttachment
940- property string mmsText: ""
941- property string mmsTextId: ""
942- property string accountLabel: ""
943- property bool selectionMode: false
944- property bool selected: false
945- property bool inProgress: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||
946- textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed)
947- property bool failed: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
948- property int visibleAttachments: 0
949-
950- signal resend()
951- signal itemPressAndHold(QtObject obj)
952- signal itemClicked(QtObject obj)
953-
954- anchors {
955- left: parent ? parent.left : undefined
956- right: parent ? parent.right: undefined
957- }
958- height: attachments.height + bubbleItem.height
959-
960- Component {
961- id: statusIcon
962- Item {
963- height: units.gu(4)
964- width: units.gu(4)
965- visible: !incoming && !messageDelegate.selectionMode
966- ActivityIndicator {
967- id: indicator
968-
969- anchors.centerIn: parent
970- height: units.gu(2)
971- width: units.gu(2)
972- visible: running && !selectionMode
973- // if temporarily failed or unknown status, then show the spinner
974- running: inProgress
975- }
976-
977- Item {
978- id: retrybutton
979-
980- anchors.fill: parent
981- Icon {
982- id: icon
983-
984- name: "reload"
985- color: "red"
986- height: units.gu(2)
987- width: units.gu(2)
988- anchors {
989- centerIn: parent
990- verticalCenterOffset: units.gu(-1)
991- }
992- }
993-
994- Label {
995- text: i18n.tr("Failed!")
996- fontSize: "small"
997- color: "red"
998- anchors {
999- horizontalCenter: retrybutton.horizontalCenter
1000- top: icon.bottom
1001- }
1002- }
1003- visible: failed
1004- MouseArea {
1005- id: retrybuttonMouseArea
1006-
1007- anchors.fill: parent
1008- onClicked: messageDelegate.resend()
1009- }
1010- }
1011- }
1012- }
1013-
1014- Column {
1015- id: attachments
1016- anchors {
1017- top: parent.top
1018- left: parent.left
1019- right: parent.right
1020- }
1021- height: childrenRect.height
1022- Repeater {
1023- id: attachmentsRepeater
1024-
1025- model: textMessageAttachments
1026- Loader {
1027- anchors {
1028- left: parent ? parent.left : undefined
1029- right: parent ? parent.right : undefined
1030- }
1031- height: item ? item.height : 0
1032- source: {
1033- if (startsWith(modelData.contentType, "image/")) {
1034- return "MMS/MMSImage.qml"
1035- } else if (startsWith(modelData.contentType, "video/")) {
1036- return "MMS/MMSVideo.qml"
1037- } else if (startsWith(modelData.contentType, "application/smil") ||
1038- startsWith(modelData.contentType, "application/x-smil")) {
1039- return ""
1040- } else if (startsWith(modelData.contentType, "text/plain") ) {
1041- mmsText = application.readTextFile(modelData.filePath)
1042- mmsTextId = modelData.attachmentId
1043- return ""
1044- } else if (startsWith(modelData.contentType, "text/vcard") ||
1045- startsWith(modelData.contentType, "text/x-vcard")) {
1046- return "MMS/MMSContact.qml"
1047- } else {
1048- console.log("No MMS render for " + modelData.contentType)
1049- return "MMS/MMSDefault.qml"
1050- }
1051- }
1052- onStatusChanged: {
1053- if (status == Loader.Ready) {
1054- item.attachment = modelData
1055- item.incoming = incoming
1056- }
1057- }
1058- Connections {
1059- target: item
1060- onItemRemoved: {
1061- eventModel.removeEventAttachment(accountId, threadId, eventId, type, modelData.attachmentId)
1062- if (visibleAttachments == 1 && mmsText === "") {
1063- // this is the last attachment. remove the whole event
1064- eventModel.removeEvent(accountId, threadId, eventId, type)
1065- return
1066- }
1067- }
1068- }
1069- Connections {
1070- target: item
1071- onItemPressAndHold: itemPressAndHold(bubbleItem)
1072- }
1073- Binding {
1074- target: item
1075- property: "parentSelected"
1076- value: messageDelegate.selected
1077- }
1078- Connections {
1079- target: item
1080- onAttachmentClicked: {
1081- if (item.previewer === "") {
1082- activeAttachment = modelData
1083- PopupUtils.open(popoverSaveAttachmentComponent, item)
1084- return
1085- }
1086-
1087- var properties = {}
1088- properties["attachment"] = item.attachment
1089- mainStack.push(Qt.resolvedUrl(item.previewer), properties)
1090- }
1091- }
1092- }
1093- }
1094- }
1095-
1096- ListItemWithActions {
1097- id: bubbleItem
1098-
1099- anchors {
1100- top: attachments.bottom
1101- left: parent.left
1102- right: parent.right
1103- }
1104- internalAnchors {
1105- topMargin: 0
1106- bottomMargin: 0
1107- }
1108-
1109- height: bubble.visible ? bubble.height : 0
1110- leftSideAction: Action {
1111- iconName: "delete"
1112- text: i18n.tr("Delete")
1113- onTriggered: {
1114- // if there are no attachments, remove the whole message
1115- if (visibleAttachments == 0) {
1116- eventModel.removeEvent(accountId, threadId, eventId, type)
1117- return
1118- }
1119- // check if this is an mms text and we have more attachments
1120- if (mmsText !== "" && visibleAttachments > 1) {
1121- // remove only the text attachment if we have more attachments
1122- eventModel.removeEventAttachment(accountId, threadId, eventId, type, mmsTextId)
1123- mmsText = ""
1124- mmsTextId = ""
1125- return
1126- }
1127- }
1128- }
1129-
1130- selected: messageDelegate.selected
1131- selectionMode: messageDelegate.selectionMode
1132- onItemPressAndHold: messageDelegate.itemPressAndHold(bubbleItem)
1133- onItemClicked: messageDelegate.itemClicked(bubbleItem)
1134- onSwippingChanged: messageList.updateSwippedItem(bubbleItem)
1135- onSwipeStateChanged: messageList.updateSwippedItem(bubbleItem)
1136-
1137- MessageBubble {
1138- id: bubble
1139-
1140- anchors {
1141- top: parent.top
1142- left: incoming ? parent.left : undefined
1143- right: incoming ? undefined : parent.right
1144- }
1145- visible: (messageText !== "")
1146- messageText: textMessage !== "" ? textMessage : mmsText
1147- messageTimeStamp: timestamp
1148- messageStatus: textMessageStatus
1149- }
1150-
1151- Loader {
1152- id: statusIconLoader
1153- active: !incoming && !messageDelegate.selectionMode && bubble.visible && (inProgress || failed)
1154- sourceComponent: statusIcon
1155- anchors.right: bubble.left
1156- anchors.rightMargin: units.gu(1)
1157- anchors.verticalCenter: bubble.verticalCenter
1158- }
1159- }
1160-
1161+ objectName: "messageDelegate"
1162+
1163+ property bool incoming
1164+ property var attachments
1165+ property string accountId
1166+ property var threadId
1167+ property var eventId
1168+ property var type
1169+ property string text
1170+ property var timestamp
1171+ property string accountLabel
1172+ property var _lastItem: messageDelegate
1173+
1174+
1175+ function deleteMessage()
1176+ {
1177+ //virtual implemented by each Message type
1178+ }
1179+
1180+ function copyMessage()
1181+ {
1182+ //virtual implemented by each Message type
1183+ }
1184+
1185+ function resendMessage()
1186+ {
1187+ //virtual implemented by each Message type
1188+ }
1189+
1190+ function showMessageDetails(mouse)
1191+ {
1192+ //virtual implemented by each Message type
1193+ }
1194+
1195+ function clicked(mouse)
1196+ {
1197+ //virtual implemented by each Message type
1198+ }
1199 }
1200
1201=== added file 'src/qml/MessageDelegateFactory.qml'
1202--- src/qml/MessageDelegateFactory.qml 1970-01-01 00:00:00 +0000
1203+++ src/qml/MessageDelegateFactory.qml 2014-08-12 15:32:18 +0000
1204@@ -0,0 +1,203 @@
1205+/*
1206+ * Copyright 2012, 2013, 2014 Canonical Ltd.
1207+ *
1208+ * This file is part of messaging-app.
1209+ *
1210+ * messaging-app is free software; you can redistribute it and/or modify
1211+ * it under the terms of the GNU General Public License as published by
1212+ * the Free Software Foundation; version 3.
1213+ *
1214+ * messaging-app is distributed in the hope that it will be useful,
1215+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1216+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1217+ * GNU General Public License for more details.
1218+ *
1219+ * You should have received a copy of the GNU General Public License
1220+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1221+ */
1222+
1223+import QtQuick 2.2
1224+import Ubuntu.Components 1.1
1225+import Ubuntu.Contacts 0.1
1226+import Ubuntu.History 0.1
1227+
1228+ListItemWithActions {
1229+ id: root
1230+
1231+ property bool incoming: false
1232+ property var _lastItem: loader.status === Loader.Ready ? loader.item._lastItem : null
1233+ property list<Action> _availableActions
1234+ property string accountLabel
1235+
1236+ signal deleteMessage()
1237+ signal resendMessage()
1238+ signal copyMessage()
1239+ signal showMessageDetails()
1240+
1241+ triggerActionOnMouseRelease: true
1242+ width: messageList.width
1243+ leftSideAction: Action {
1244+ iconName: "delete"
1245+ text: i18n.tr("Delete")
1246+ onTriggered: deleteMessage()
1247+ }
1248+
1249+ // WORKAROUND: to filter actions on rightSideActions property based on message status
1250+ _availableActions: [
1251+ Action {
1252+ id: reloadAction
1253+
1254+ iconName: "reload"
1255+ text: i18n.tr("Retry")
1256+ onTriggered: resendMessage()
1257+ },
1258+ Action {
1259+ id: copyAction
1260+
1261+ iconName: "edit-copy"
1262+ text: i18n.tr("Copy")
1263+ onTriggered: copyMessage()
1264+ },
1265+ Action {
1266+ id: infoAction
1267+
1268+ iconName: "info"
1269+ text: i18n.tr("Info")
1270+ onTriggered: {
1271+ // FIXME: Is that the corect way to do that?
1272+ var messageType = textMessageAttachments.length > 0 ? i18n.tr("MMS") : i18n.tr("SMS")
1273+ var messageInfo = {"type": messageType,
1274+ "senderId": senderId,
1275+ "timestamp": timestamp,
1276+ "textReadTimestamp": textReadTimestamp,
1277+ "status": textMessageStatus}
1278+ messageInfoDialog.showMessageInfo(messageInfo)
1279+ }
1280+ }
1281+ ]
1282+
1283+ rightSideActions: {
1284+ var actions = []
1285+ if (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) {
1286+ actions.push(reloadAction)
1287+ }
1288+ actions.push(copyAction)
1289+ actions.push(infoAction)
1290+ return actions
1291+ }
1292+
1293+ height: loader.height + units.gu(1)
1294+ internalAnchors {
1295+ topMargin: units.gu(0.5)
1296+ bottomMargin: units.gu(0.5)
1297+ }
1298+
1299+ onItemClicked: {
1300+ if (!selectionMode && (loader.status === Loader.Ready)) {
1301+ loader.item.clicked(mouse)
1302+ }
1303+ }
1304+
1305+ Loader {
1306+ id: loader
1307+
1308+ onStatusChanged: {
1309+ if (status === Loader.Ready) {
1310+ //signals
1311+ root.resendMessage.connect(item.resendMessage)
1312+ root.deleteMessage.connect(item.deleteMessage)
1313+ root.copyMessage.connect(item.copyMessage)
1314+ root.showMessageDetails(item.showMessageDetails)
1315+ }
1316+ }
1317+ anchors {
1318+ left: parent.left
1319+ right: parent.right
1320+ }
1321+ height: status == Loader.Ready ? item.height : 0
1322+ Component.onCompleted: {
1323+ var initialProperties = {
1324+ "incoming": root.incoming,
1325+ "accountLabel": accountLabel,
1326+ "attachments": textMessageAttachments,
1327+ "accountId": accountId,
1328+ "threadId": threadId,
1329+ "eventId": eventId,
1330+ "type": type,
1331+ "text": textMessage,
1332+ "timestamp": timestamp
1333+ }
1334+ if (textMessageAttachments.length > 0) {
1335+ setSource(Qt.resolvedUrl("MMSDelegate.qml"), initialProperties)
1336+ } else {
1337+ setSource(Qt.resolvedUrl("SMSDelegate.qml"), initialProperties)
1338+ }
1339+ }
1340+ }
1341+
1342+ Item {
1343+ id: statusIcon
1344+
1345+ height: units.gu(4)
1346+ width: units.gu(4)
1347+ parent: _lastItem
1348+ anchors {
1349+ verticalCenter: parent ? parent.verticalCenter : undefined
1350+ right: parent ? parent.left : undefined
1351+ rightMargin: units.gu(2)
1352+ }
1353+
1354+ visible: !incoming && !selectionMode
1355+ ActivityIndicator {
1356+ id: indicator
1357+
1358+ anchors.centerIn: parent
1359+ height: units.gu(2)
1360+ width: units.gu(2)
1361+ visible: running && !selectionMode
1362+ // if temporarily failed or unknown status, then show the spinner
1363+ running: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||
1364+ textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed)
1365+ }
1366+
1367+ Item {
1368+ id: retrybutton
1369+
1370+ anchors.fill: parent
1371+ Icon {
1372+ id: icon
1373+
1374+ name: "reload"
1375+ color: "red"
1376+ height: units.gu(2)
1377+ width: units.gu(2)
1378+ anchors {
1379+ centerIn: parent
1380+ verticalCenterOffset: units.gu(-1)
1381+ }
1382+ }
1383+
1384+ Label {
1385+ text: i18n.tr("Failed!")
1386+ fontSize: "small"
1387+ color: "red"
1388+ anchors {
1389+ horizontalCenter: retrybutton.horizontalCenter
1390+ top: icon.bottom
1391+ }
1392+ }
1393+ visible: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
1394+ MouseArea {
1395+ id: retrybuttonMouseArea
1396+
1397+ anchors.fill: parent
1398+ onClicked: root.resendMessage()
1399+ }
1400+ }
1401+
1402+
1403+ MessageInfoDialog {
1404+ id: messageInfoDialog
1405+ }
1406+ }
1407+}
1408
1409=== added file 'src/qml/MessageInfoDialog.qml'
1410--- src/qml/MessageInfoDialog.qml 1970-01-01 00:00:00 +0000
1411+++ src/qml/MessageInfoDialog.qml 2014-08-12 15:32:18 +0000
1412@@ -0,0 +1,124 @@
1413+/*
1414+ * Copyright 2012, 2013, 2014 Canonical Ltd.
1415+ *
1416+ * This file is part of messaging-app.
1417+ *
1418+ * messaging-app is free software; you can redistribute it and/or modify
1419+ * it under the terms of the GNU General Public License as published by
1420+ * the Free Software Foundation; version 3.
1421+ *
1422+ * messaging-app is distributed in the hope that it will be useful,
1423+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1424+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1425+ * GNU General Public License for more details.
1426+ *
1427+ * You should have received a copy of the GNU General Public License
1428+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1429+ */
1430+
1431+import QtQuick 2.2
1432+import Ubuntu.Components 1.1
1433+import Ubuntu.Components.Popups 0.1
1434+import Ubuntu.History 0.1
1435+
1436+
1437+Item {
1438+ id: root
1439+
1440+ property QtObject activeDialog: null
1441+ property var activeMessage: null
1442+
1443+ function showMessageInfo(message)
1444+ {
1445+ if (!activeDialog) {
1446+ activeMessage = message
1447+ activeDialog = PopupUtils.open(messageInfoDialog, messages)
1448+ }
1449+ }
1450+
1451+ Component {
1452+ id: messageInfoDialog
1453+
1454+ Dialog {
1455+ id: dialogue
1456+
1457+ parent: messages
1458+
1459+ function statusToString(status)
1460+ {
1461+ switch(status)
1462+ {
1463+ case HistoryThreadModel.MessageStatusDelivered:
1464+ return i18n.tr("Delivered")
1465+ case HistoryThreadModel.MessageStatusTemporarilyFailed:
1466+ return i18n.tr("Temporarily Failed")
1467+ case HistoryThreadModel.MessageStatusPermanentlyFailed:
1468+ return i18n.tr("Failed")
1469+ case HistoryThreadModel.MessageStatusAccepted:
1470+ return i18n.tr("Accepted")
1471+ case HistoryThreadModel.MessageStatusRead:
1472+ return i18n.tr("Read")
1473+ case HistoryThreadModel.MessageStatusDeleted:
1474+ return i18n.tr("Deleted")
1475+ case HistoryThreadModel.MessageStatusPending:
1476+ return i18n.tr("Pending")
1477+ case HistoryThreadModel.MessageStatusUnknown:
1478+ //FIXME: Received messages has Unknown status is that correct??
1479+ if (root.activeMessage.senderId !== "self") {
1480+ return i18n.tr("Received")
1481+ } else {
1482+ return i18n.tr("Unknown")
1483+ }
1484+ default:
1485+ return i18n.tr("Unknown")
1486+ }
1487+ }
1488+
1489+
1490+ title: i18n.tr("Message info")
1491+
1492+ anchors.centerIn: parent
1493+ height: childrenRect.height
1494+ width: childrenRect.width
1495+
1496+ Label {
1497+ text: "<b>%1:</b> %2".arg(i18n.tr("Type")).arg(root.activeMessage.type)
1498+ }
1499+
1500+ Label {
1501+ text: "<b>%1:</b> %2".arg(i18n.tr("From")).arg(root.activeMessage.senderId !== "self" ? root.activeMessage.senderId : i18n.tr("Myself"))
1502+ }
1503+
1504+ Label {
1505+ text: "<b>%1:</b> %2".arg(i18n.tr("Sent")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate))
1506+ visible: (root.activeMessage.senderId === "self")
1507+ }
1508+
1509+ Label {
1510+ text: "<b>%1:</b> %2".arg(i18n.tr("Received")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate))
1511+ visible: (root.activeMessage.senderId !== "self")
1512+ }
1513+
1514+ Label {
1515+ text: "<b>%1:</b> %2".arg(i18n.tr("Read")).arg(Qt.formatDateTime(root.activeMessage.textReadTimestamp, Qt.DefaultLocaleShortDate))
1516+ visible: (root.activeMessage.senderId !== "self") && (root.activeMessage.textReadTimestamp > 0)
1517+ }
1518+
1519+ Label {
1520+ text: "<b>%1:</b> %2".arg(i18n.tr("Status")).arg(statusToString(root.activeMessage.status))
1521+ }
1522+
1523+ Button {
1524+ text: i18n.tr("Close")
1525+ onClicked: {
1526+ PopupUtils.close(root.activeDialog)
1527+ }
1528+ }
1529+
1530+ Component.onDestruction: {
1531+ root.activeDialog = null
1532+ root.activeMessage = null
1533+ }
1534+ }
1535+ }
1536+}
1537
1538=== modified file 'src/qml/Messages.qml'
1539--- src/qml/Messages.qml 2014-08-12 15:32:18 +0000
1540+++ src/qml/Messages.qml 2014-08-12 15:32:18 +0000
1541@@ -16,7 +16,7 @@
1542 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1543 */
1544
1545-import QtQuick 2.0
1546+import QtQuick 2.2
1547 import QtQuick.Window 2.0
1548 import QtContacts 5.0
1549 import Ubuntu.Components 1.1
1550@@ -28,12 +28,16 @@
1551 import Ubuntu.Contacts 0.1
1552 import QtContacts 5.0
1553
1554+import "dateUtils.js" as DateUtils
1555+
1556 Page {
1557 id: messages
1558 objectName: "messagesPage"
1559+
1560 // this property can be overriden by the user using the account switcher,
1561 // in the suru divider
1562 property QtObject account: mainView.defaultAccount
1563+
1564 property variant participants: []
1565 property bool groupChat: participants.length > 1
1566 property bool keyboardFocus: true
1567@@ -41,7 +45,6 @@
1568 // FIXME: MainView should provide if the view is in portait or landscape
1569 property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
1570 property bool landscape: orientationAngle == 90 || orientationAngle == 270
1571- property bool pendingMessage: false
1572 property var activeTransfer: null
1573 property int activeAttachmentIndex: -1
1574 property var sharedAttachmentsTransfer: []
1575@@ -111,7 +114,7 @@
1576
1577 title: {
1578 if (selectionMode) {
1579- return i18n.tr("Edit")
1580+ return i18n.tr(" ")
1581 }
1582
1583 if (landscape) {
1584@@ -127,7 +130,7 @@
1585 if (participants.length == 1) {
1586 return firstRecipient
1587 } else {
1588- return i18n.tr("Group (%1 members)").arg(participants.length)
1589+ return i18n.tr("Group (%1)").arg(participants.length)
1590 }
1591 }
1592 return i18n.tr("New Message")
1593@@ -269,7 +272,7 @@
1594 return -1
1595 }
1596 for (var i in telepathyHelper.accounts) {
1597- if (telepathyHelper.accounts[i].accountId == messages.account.accountId) {
1598+ if (telepathyHelper.accounts[i].accountId === messages.account.accountId) {
1599 return i
1600 }
1601 }
1602@@ -277,9 +280,7 @@
1603 }
1604 Connections {
1605 target: messages.head.sections
1606- onSelectedIndexChanged: {
1607- messages.account = telepathyHelper.accounts[head.sections.selectedIndex]
1608- }
1609+ onSelectedIndexChanged: messages.account = telepathyHelper.accounts[head.sections.selectedIndex]
1610 }
1611
1612 Component {
1613@@ -295,30 +296,13 @@
1614 filterTerm: multiRecipient.searchString
1615 showSections: false
1616 autoHideKeyboard: false
1617-
1618- states: [
1619- State {
1620- name: "empty"
1621- when: contactSearch.count === 0
1622- PropertyChanges {
1623- target: contactSearch
1624- height: 0
1625- }
1626- }
1627- ]
1628-
1629 anchors {
1630 top: parent.top
1631 topMargin: units.gu(1)
1632 left: parent.left
1633 right: parent.right
1634- bottom: bottomPanel.top
1635- }
1636-
1637- Behavior on height {
1638- UbuntuNumberAnimation { }
1639- }
1640-
1641+ bottom: parent.bottom
1642+ }
1643 InvalidFilter {
1644 id: invalidFilter
1645 }
1646@@ -377,7 +361,7 @@
1647 }
1648 height: units.gu(2)
1649 text: {
1650- // this is necessary to keep the string in the original format
1651+ // this is necessary to keep the string in the original foverdrawormat
1652 var originalText = contact.displayLabel.label
1653 var lowerSearchText = multiRecipient.searchString.toLowerCase()
1654 var lowerText = originalText.toLowerCase()
1655@@ -422,16 +406,27 @@
1656 }
1657
1658 Loader {
1659- active: multiRecipient.searchString !== "" && multiRecipient.focus
1660- sourceComponent: contactSearchComponent
1661+ property int resultCount: (status === Loader.Ready) ? item.view.count : 0
1662+
1663+ sourceComponent: (multiRecipient.searchString !== "") && multiRecipient.focus ? contactSearchComponent : null
1664 clip: true
1665 anchors {
1666 top: parent.top
1667 left: parent.left
1668 right: parent.right
1669- bottom: bottomPanel.top
1670 }
1671+ height: resultCount > 0 ? parent.height - keyboard.height : 0
1672 z: 1
1673+ // WORKAROUND: we need to use opacity here visible FALSE cause the item to not load
1674+ opacity: height > 0 ? 1.0 : 0.0
1675+ Behavior on height {
1676+ UbuntuNumberAnimation { }
1677+ }
1678+
1679+ Rectangle {
1680+ anchors.fill: parent
1681+ color: Theme.palette.normal.background
1682+ }
1683 }
1684
1685 ContactWatcher {
1686@@ -488,7 +483,13 @@
1687 Action {
1688 objectName: "selectionModeSelectAllAction"
1689 iconName: "select"
1690- onTriggered: messageList.selectAll()
1691+ onTriggered: {
1692+ if (messageList.selectedItems.count === messageList.count) {
1693+ messageList.clearSelection()
1694+ } else {
1695+ messageList.selectAll()
1696+ }
1697+ }
1698 },
1699 Action {
1700 objectName: "selectionModeDeleteAction"
1701@@ -645,86 +646,66 @@
1702 header: Item {
1703 height: units.gu(1)
1704 }
1705-
1706- spacing: units.gu(1)
1707 listModel: participants.length > 0 ? sortProxy : null
1708 verticalLayoutDirection: ListView.BottomToTop
1709- highlightFollowsCurrentItem: false
1710- /*add: Transition {
1711- UbuntuNumberAnimation {
1712- properties: "anchors.leftMargin"
1713- from: -width
1714- to: 0
1715- }
1716- UbuntuNumberAnimation {
1717- properties: "anchors.rightMargin"
1718- from: -width
1719- to: 0
1720- }
1721- }*/
1722+ highlightFollowsCurrentItem: true
1723+ currentIndex: 0
1724+ // keep the last item as currentItem
1725
1726- listDelegate: MessageDelegate {
1727+ listDelegate: Column {
1728 id: messageDelegate
1729- objectName: "message%1".arg(index)
1730- incoming: senderId != "self"
1731- // TODO: we have several items inside
1732- selected: messageList.isSelected(messageDelegate)
1733- unread: newEvent
1734- selectionMode: messages.selectionMode
1735- accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : ""
1736- // TODO: need select only the item
1737- onItemClicked: {
1738- if (messageList.isInSelectionMode) {
1739- if (!messageList.selectItem(messageDelegate)) {
1740- messageList.deselectItem(messageDelegate)
1741- }
1742- }
1743- }
1744- onItemPressAndHold: {
1745- messageList.startSelection()
1746- messageList.selectItem(messageDelegate)
1747- }
1748-
1749- Component.onCompleted: {
1750- if (newEvent) {
1751- messages.markMessageAsRead(accountId, threadId, eventId, type);
1752- }
1753- }
1754- onResend: {
1755- // resend this message and remove the old one
1756- if (textMessageAttachments.length > 0) {
1757- var newAttachments = []
1758- for (var i = 0; i < textMessageAttachments.length; i++) {
1759- var attachment = []
1760- var item = textMessageAttachments[i]
1761- // we dont include smil files. they will be auto generated
1762- if (item.contentType.toLowerCase() == "application/smil") {
1763- continue
1764+
1765+ // WORKAROUND: we can not use sections because the verticalLayoutDirection is ListView.BottomToTop the sections will appear
1766+ // bellow the item
1767+ MessageDateSection {
1768+ text: DateUtils.friendlyDay(timestamp)
1769+ anchors {
1770+ left: parent.left
1771+ right: parent.right
1772+ leftMargin: units.gu(2)
1773+ rightMargin: units.gu(2)
1774+ }
1775+ visible: (index === messageList.count) || !DateUtils.areSameDay(sortProxy.get(index+1).timestamp, timestamp)
1776+ }
1777+
1778+ MessageDelegateFactory {
1779+ objectName: "message%1".arg(index)
1780+ incoming: senderId != "self"
1781+ // TODO: we have several items inside
1782+ selected: messageList.isSelected(messageDelegate)
1783+ selectionMode: messages.selectionMode
1784+ accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : ""
1785+ // TODO: need select only the item
1786+ onItemClicked: {
1787+ if (messageList.isInSelectionMode) {
1788+ if (!messageList.selectItem(messageDelegate)) {
1789+ messageList.deselectItem(messageDelegate)
1790 }
1791- attachment.push(item.attachmentId)
1792- attachment.push(item.contentType)
1793- attachment.push(item.filePath)
1794- newAttachments.push(attachment)
1795- }
1796- eventModel.removeEvent(accountId, threadId, eventId, type)
1797- chatManager.sendMMS(participants, textMessage, newAttachments, messages.account.accountId)
1798- return
1799- }
1800- eventModel.removeEvent(accountId, threadId, eventId, type)
1801- chatManager.sendMessage(messages.participants, textMessage, messages.account.accountId)
1802+ }
1803+ }
1804+ onItemPressAndHold: {
1805+ messageList.startSelection()
1806+ messageList.selectItem(messageDelegate)
1807+ }
1808+
1809+ Component.onCompleted: {
1810+ if (newEvent) {
1811+ messages.markMessageAsRead(accountId, threadId, eventId, type);
1812+ }
1813+ }
1814 }
1815 }
1816+
1817 onSelectionDone: {
1818 for (var i=0; i < items.count; i++) {
1819 var event = items.get(i).model
1820 eventModel.removeEvent(event.accountId, event.threadId, event.eventId, event.type)
1821 }
1822 }
1823+
1824 onCountChanged: {
1825- if (messages.pendingMessage) {
1826- messageList.contentY = 0
1827- messages.pendingMessage = false
1828- }
1829+ currentIndex = 0
1830+ positionViewAtBeginning()
1831 }
1832 }
1833
1834@@ -909,7 +890,7 @@
1835 height: units.gu(4.3)
1836 style: MultiRecipientFieldStyle {}
1837 autoSize: true
1838- maximumLineCount: 0
1839+ maximumLineCount: attachments.count == 0 ? 8 : 4
1840 placeholderText: i18n.tr("Write a message...")
1841 focus: textEntry.focus
1842 font.family: "Ubuntu"
1843@@ -984,7 +965,6 @@
1844 true)
1845
1846 updateFilters()
1847- messages.pendingMessage = true
1848 if (attachments.count > 0) {
1849 var newAttachments = []
1850 for (var i = 0; i < attachments.count; i++) {
1851
1852=== modified file 'src/qml/MultiRecipientInput.qml'
1853--- src/qml/MultiRecipientInput.qml 2014-07-30 16:19:08 +0000
1854+++ src/qml/MultiRecipientInput.qml 2014-08-12 15:32:18 +0000
1855@@ -16,7 +16,7 @@
1856 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1857 */
1858
1859-import QtQuick 2.0
1860+import QtQuick 2.2
1861 import Ubuntu.Components 1.1
1862 import Ubuntu.Contacts 0.1
1863 import Ubuntu.Telephony 0.1
1864
1865=== modified file 'src/qml/NewRecipientPage.qml'
1866--- src/qml/NewRecipientPage.qml 2014-08-01 14:51:29 +0000
1867+++ src/qml/NewRecipientPage.qml 2014-08-12 15:32:18 +0000
1868@@ -16,7 +16,7 @@
1869 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1870 */
1871
1872-import QtQuick 2.0
1873+import QtQuick 2.2
1874 import Ubuntu.Components 1.1
1875 import Ubuntu.Contacts 0.1
1876 import QtContacts 5.0
1877
1878=== added file 'src/qml/SMSDelegate.qml'
1879--- src/qml/SMSDelegate.qml 1970-01-01 00:00:00 +0000
1880+++ src/qml/SMSDelegate.qml 2014-08-12 15:32:18 +0000
1881@@ -0,0 +1,75 @@
1882+/*
1883+ * Copyright 2012, 2013, 2014 Canonical Ltd.
1884+ *
1885+ * This file is part of messaging-app.
1886+ *
1887+ * messaging-app is free software; you can redistribute it and/or modify
1888+ * it under the terms of the GNU General Public License as published by
1889+ * the Free Software Foundation; version 3.
1890+ *
1891+ * messaging-app is distributed in the hope that it will be useful,
1892+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1893+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1894+ * GNU General Public License for more details.
1895+ *
1896+ * You should have received a copy of the GNU General Public License
1897+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1898+ */
1899+
1900+import QtQuick 2.2
1901+import Ubuntu.Components 1.1
1902+
1903+import "dateUtils.js" as DateUtils
1904+
1905+MessageDelegate {
1906+ id: root
1907+
1908+ function deleteMessage()
1909+ {
1910+ eventModel.removeEvent(accountId, threadId, eventId, type)
1911+ }
1912+
1913+ function resendMessage()
1914+ {
1915+ eventModel.removeEvent(accountId, threadId, eventId, type)
1916+ chatManager.sendMessage(messages.participants, textMessage, messages.accountId)
1917+ }
1918+
1919+ function copyMessage()
1920+ {
1921+ Clipboard.push(bubble.messageText)
1922+ }
1923+
1924+ height: bubble.height
1925+ _lastItem: bubble
1926+
1927+ MessageBubble {
1928+ id: bubble
1929+
1930+ states: [
1931+ State {
1932+ name: "incoming"
1933+ when: incoming
1934+ AnchorChanges {
1935+ target: bubble
1936+ anchors.left: parent.left
1937+ }
1938+ },
1939+ State {
1940+ name: "outgoing"
1941+ when: !incoming
1942+ AnchorChanges {
1943+ target: bubble
1944+ anchors.right: parent.right
1945+ }
1946+ }
1947+
1948+ ]
1949+ visible: (root.text !== "")
1950+ messageIncoming: root.incoming
1951+ messageText: root.text
1952+ messageTimeStamp: root.timestamp
1953+ accountName: root.accountLabel
1954+ messageStatus: textMessageStatus
1955+ }
1956+}
1957
1958=== modified file 'src/qml/StandardAnimation.qml'
1959--- src/qml/StandardAnimation.qml 2013-07-17 21:47:45 +0000
1960+++ src/qml/StandardAnimation.qml 2014-08-12 15:32:18 +0000
1961@@ -16,7 +16,7 @@
1962 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1963 */
1964
1965-import QtQuick 2.0
1966+import QtQuick 2.2
1967
1968 NumberAnimation {
1969 duration: 300
1970
1971=== modified file 'src/qml/ThreadDelegate.qml'
1972--- src/qml/ThreadDelegate.qml 2014-08-12 15:32:18 +0000
1973+++ src/qml/ThreadDelegate.qml 2014-08-12 15:32:18 +0000
1974@@ -16,7 +16,7 @@
1975 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1976 */
1977
1978-import QtQuick 2.0
1979+import QtQuick 2.2
1980 import Ubuntu.Components 1.1
1981 import Ubuntu.Components.Popups 0.1
1982 import Ubuntu.Telephony 0.1
1983@@ -44,7 +44,6 @@
1984 return firstRecipient
1985 }
1986
1987- property bool selectionMode: false
1988 property string textMessage: {
1989 // check if this is an mms, if so, search for the actual text
1990 var imageCount = 0
1991@@ -111,9 +110,17 @@
1992 ContactAvatar {
1993 id: avatar
1994
1995- fallbackAvatarUrl: groupChat ? "image://theme/contact-group" : delegateHelper.avatar !== "" ? delegateHelper.avatar : "image://theme/contact"
1996+ fallbackAvatarUrl: {
1997+ if (groupChat) {
1998+ return "image://theme/contact-group"
1999+ } else if (delegateHelper.avatar !== "") {
2000+ return delegateHelper.avatar
2001+ } else {
2002+ return "image://theme/contact"
2003+ }
2004+ }
2005 fallbackDisplayName: delegateHelper.alias
2006- showAvatarPicture: (delegateHelper.avatar !== "") || (initials.length === 0) || groupChat
2007+ showAvatarPicture: groupChat || (delegateHelper.avatar !== "") || (initials.length === 0)
2008 anchors {
2009 left: parent.left
2010 top: parent.top
2011@@ -127,24 +134,35 @@
2012 id: contactName
2013 anchors {
2014 top: avatar.top
2015+ topMargin: units.gu(0.5)
2016 left: avatar.right
2017 leftMargin: units.gu(1)
2018 }
2019- fontSize: "medium"
2020 color: UbuntuColors.lightAubergine
2021 text: groupChat ? groupChatLabel : unknownContact ? delegateHelper.phoneNumber : delegateHelper.alias
2022 }
2023
2024- Label {
2025+ Row {
2026 id: time
2027+
2028 anchors {
2029 verticalCenter: contactName.verticalCenter
2030 right: parent.right
2031 }
2032- fontSize: "x-small"
2033- text: Qt.formatDateTime(eventTimestamp,"h:mm ap")
2034+ Label {
2035+ fontSize: "x-small"
2036+ font.weight: Font.DemiBold
2037+ opacity: 0.70
2038+ text: Qt.formatDateTime(eventTimestamp,"h:mm")
2039+ }
2040+ Label {
2041+ fontSize: "x-small"
2042+ opacity: 0.70
2043+ text: Qt.formatDateTime(eventTimestamp," ap")
2044+ }
2045 }
2046-
2047+
2048+
2049 UbuntuShape {
2050 id: unreadCountIndicator
2051 height: units.gu(2)
2052@@ -181,20 +199,18 @@
2053
2054 Label {
2055 id: latestMessage
2056- height: units.gu(3)
2057+
2058 anchors {
2059 top: contactName.bottom
2060 topMargin: units.gu(0.5)
2061 left: contactName.left
2062 right: time.left
2063 rightMargin: units.gu(3)
2064+ bottom: avatar.bottom
2065 }
2066 elide: Text.ElideRight
2067- maximumLineCount: 2
2068 fontSize: "x-small"
2069- wrapMode: Text.WordWrap
2070 text: textMessage
2071- font.weight: Font.Light
2072 }
2073
2074 Item {
2075
2076=== modified file 'src/qml/assets/conversation_incoming@27.png'
2077Binary files src/qml/assets/conversation_incoming@27.png 2014-07-07 13:09:42 +0000 and src/qml/assets/conversation_incoming@27.png 2014-08-12 15:32:18 +0000 differ
2078=== modified file 'src/qml/messaging-app.qml'
2079--- src/qml/messaging-app.qml 2014-08-12 15:32:18 +0000
2080+++ src/qml/messaging-app.qml 2014-08-12 15:32:18 +0000
2081@@ -16,7 +16,7 @@
2082 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2083 */
2084
2085-import QtQuick 2.0
2086+import QtQuick 2.2
2087 import Qt.labs.settings 1.0
2088 import Ubuntu.Components 1.1
2089 import Ubuntu.Components.ListItems 0.1 as ListItem
2090@@ -54,7 +54,7 @@
2091 Connections {
2092 target: telepathyHelper
2093 onSetupReady: {
2094- if (multipleAccounts && !telepathyHelper.defaultMessagingAccount &&
2095+ if (multipleAccounts && !telepathyHelper.defaultMessagingAccount &&
2096 settings.mainViewDontAskCount < 3 && mainStack.depth === 1) {
2097 PopupUtils.open(Qt.createComponent("Dialogs/NoDefaultSIMCardDialog.qml").createObject(mainView))
2098 }
2099
2100=== modified file 'tests/autopilot/messaging_app/emulators.py'
2101--- tests/autopilot/messaging_app/emulators.py 2014-08-12 15:32:18 +0000
2102+++ tests/autopilot/messaging_app/emulators.py 2014-08-12 15:32:18 +0000
2103@@ -57,8 +57,8 @@
2104 """
2105
2106 time.sleep(2) # message is not always found on slow emulator
2107- for message in self.select_many(MessageDelegate):
2108- for item in self.select_many('Label'):
2109+ for message in self.select_many(MessageDelegateFactory):
2110+ for item in message.select_many('Label'):
2111 if "text" in item.get_properties():
2112 if item.get_properties()['text'] == text:
2113 return message
2114@@ -280,7 +280,7 @@
2115 def enable_messages_selection_mode(self):
2116 """Enable the selection mode on the messages page by pressing and
2117 holding the first item"""
2118- message = self.wait_select_single("MessageDelegate",
2119+ message = self.wait_select_single("MessageDelegateFactory",
2120 objectName="message0")
2121 self.long_press(message)
2122
2123@@ -475,8 +475,7 @@
2124
2125 def _get_message_delegate(self, index):
2126 return self.wait_select_single(
2127- 'MessageDelegate', objectName='message{}'.format(index),
2128- unread=False)
2129+ 'MessageDelegateFactory', objectName='message{}'.format(index))
2130
2131 def _long_press_to_select_message(self, message):
2132 # XXX We used to leave the pointing device pressed for three seconds,
2133@@ -539,5 +538,5 @@
2134 """Autopilot helper for ThreadDelegate."""
2135
2136
2137-class MessageDelegate(ListItemWithActions):
2138- """Autopilot helper for the MessageDelegate."""
2139+class MessageDelegateFactory(ListItemWithActions):
2140+ """Autopilot helper for the MessageDelegateFactory."""
2141
2142=== modified file 'tests/qml/tst_MessageBubble.qml'
2143--- tests/qml/tst_MessageBubble.qml 2014-07-31 17:24:57 +0000
2144+++ tests/qml/tst_MessageBubble.qml 2014-08-12 15:32:18 +0000
2145@@ -34,7 +34,7 @@
2146
2147 height: parent.height / 3
2148
2149- incoming: true
2150+ messageIncoming: true
2151 }
2152
2153 MessageBubble {
2154@@ -44,7 +44,7 @@
2155 anchors.top: incomingMessageBubble.bottom
2156 height: parent.height / 3
2157
2158- incoming: false
2159+ messageIncoming: false
2160 }
2161
2162 MessageBubble {
2163@@ -54,7 +54,7 @@
2164 anchors.top: outgoingMessageBubble.bottom
2165 height: parent.height / 3
2166
2167- incoming: true
2168+ messageIncoming: true
2169 }
2170
2171 UbuntuTestCase {
2172@@ -67,7 +67,7 @@
2173 }
2174
2175 function cleanup() {
2176- changeIncomingMessageBubble.incoming = true;
2177+ changeIncomingMessageBubble.messageIncoming = true;
2178 }
2179
2180 function getFileName(filePath) {
2181@@ -93,7 +93,7 @@
2182 function test_changeIncomingMustUpdateSource() {
2183 var changeIncomingMessageBubble = findChild(
2184 root, 'changeIncomingMessageBubble');
2185- changeIncomingMessageBubble.incoming = false;
2186+ changeIncomingMessageBubble.messageIncoming = false;
2187 compare(
2188 getFileName(changeIncomingMessageBubble.source),
2189 'conversation_outgoing.sci');

Subscribers

People subscribed via source and target branches