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
=== modified file 'src/qml/KeyboardRectangle.qml'
--- src/qml/KeyboardRectangle.qml 2014-07-25 16:22:54 +0000
+++ src/qml/KeyboardRectangle.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
2020
21Item {21Item {
22 id: keyboardRect22 id: keyboardRect
2323
=== modified file 'src/qml/MMS/MMSBase.qml'
--- src/qml/MMS/MMSBase.qml 2014-07-31 19:58:34 +0000
+++ src/qml/MMS/MMSBase.qml 2014-08-12 15:32:18 +0000
@@ -16,82 +16,13 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
18import QtQuick 2.218import QtQuick 2.2
19import Ubuntu.Components 1.1
20import Ubuntu.Contacts 0.1
2119
22ListItemWithActions {20Item {
23 id: baseDelegate21 id: baseDelegate
2422
25 property var attachment23 property var attachment
26 property bool parentSelected: false24 property string previewer
27 property bool incoming25 property bool incoming: false
28 property bool showInfo: false26 property bool lastItem: false
2927 property string timestamp
30 signal itemRemoved()
31 signal attachmentClicked()
32
33 function checkClick(bubble, mouse) {
34 var itemX1 = bubble.x
35 var itemX2 = itemX1+bubble.width
36 var itemY1 = bubble.y
37 var itemY2 = itemY1+bubble.height
38 if (mouse.x >= itemX1 && mouse.x <= itemX2 &&
39 mouse.y >= itemY1 && mouse.y <= itemY2) {
40 return true
41 }
42 return false
43 }
44
45 Component.onCompleted: {
46 visibleAttachments++
47 }
48 Component.onDestruction: {
49 visibleAttachments--
50 }
51
52 leftSideAction: Action {
53 iconName: "delete"
54 text: i18n.tr("Delete")
55 onTriggered: baseDelegate.itemRemoved()
56 }
57
58 internalAnchors {
59 topMargin: 0
60 bottomMargin: 0
61 }
62
63 color: parentSelected ? selectedColor : Theme.palette.normal.background
64 states: [
65 State {
66 when: incoming
67 name: "incoming"
68 AnchorChanges {
69 target: bubble
70 anchors.left: parent.left
71 anchors.right: undefined
72 }
73 PropertyChanges {
74 target: bubble
75 anchors.leftMargin: units.gu(1)
76 anchors.rightMargin: 0
77 }
78 },
79 State {
80 when: !incoming
81 name: "outgoing"
82 AnchorChanges {
83 target: bubble
84 anchors.left: undefined
85 anchors.right: parent.right
86 }
87 PropertyChanges {
88 target: bubble
89 anchors.leftMargin: 0
90 anchors.rightMargin: units.gu(1)
91 }
92 }
93 ]
94
95 onSwippingChanged: messageList.updateSwippedItem(baseDelegate)
96 onSwipeStateChanged: messageList.updateSwippedItem(baseDelegate)
97}28}
9829
=== modified file 'src/qml/MMS/MMSContact.qml'
--- src/qml/MMS/MMSContact.qml 2014-07-31 19:01:23 +0000
+++ src/qml/MMS/MMSContact.qml 2014-08-12 15:32:18 +0000
@@ -16,93 +16,73 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import Ubuntu.Contacts 0.121import Ubuntu.Contacts 0.1
22import ".."22import Ubuntu.History 0.1
2323
24MMSBase {24MMSBase {
25 id: vcardDelegate25 id: vcardDelegate
26 property string previewer: "MMS/PreviewerContact.qml"26
27 onItemClicked: {27 readonly property bool error: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
28 if (checkClick(bubble, mouse)) {28 readonly property bool sending: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||
29 attachmentClicked()29 textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming
30 }30
31 }31 previewer: "MMS/PreviewerContact.qml"
32 states: [32 height: units.gu(8)
33 State {33 width: units.gu(27)
34 name: "incoming"34
35 AnchorChanges {35 Rectangle {
36 target: bubble
37 anchors.left: parent.left
38 anchors.right: undefined
39 }
40 PropertyChanges {
41 target: bubble
42 anchors.leftMargin: units.gu(1)
43 anchors.rightMargin: units.gu(1)
44 }
45 AnchorChanges {
46 target: contactName
47 anchors.left: bubble.right
48 anchors.right: undefined
49 }
50 PropertyChanges {
51 target: contactName
52 anchors.leftMargin: units.gu(2)
53 anchors.rightMargin: units.gu(2)
54 }
55 },
56 State {
57 name: "outgoing"
58 AnchorChanges {
59 target: bubble
60 anchors.left: undefined
61 anchors.right: parent.right
62 }
63 PropertyChanges {
64 target: bubble
65 anchors.leftMargin: units.gu(1)
66 anchors.rightMargin: units.gu(1)
67 }
68 AnchorChanges {
69 target: contactName
70 anchors.left: undefined
71 anchors.right: bubble.left
72 }
73 PropertyChanges {
74 target: contactName
75 anchors.leftMargin: units.gu(2)
76 anchors.rightMargin: units.gu(2)
77 }
78 }
79 ]
80 height: bubble.height + units.gu(2)
81 Item {
82 id: bubble36 id: bubble
83 anchors.top: parent.top37
84 width: avatar.width38 anchors.fill: parent
85 height: avatar.height39 color: {
40 if (error) {
41 return "#fc4949"
42 } else if (sending) {
43 return "#b2b2b2"
44 } else if (incoming) {
45 return "#ffffff"
46 } else {
47 return "#3fb24f"
48 }
49 }
50 radius: height * 0.1
51
86 ContactAvatar {52 ContactAvatar {
87 id: avatar53 id: avatar
8854
55 anchors {
56 top: parent.top
57 topMargin: units.gu(1)
58 bottom: parent.bottom
59 bottomMargin: units.gu(1)
60 left: parent.left
61 leftMargin: units.gu(1)
62 }
89 fallbackAvatarUrl: "image://theme/contact"63 fallbackAvatarUrl: "image://theme/contact"
90 fallbackDisplayName: contactName.name64 fallbackDisplayName: contactName.name
91 anchors.centerIn: parent65 width: height
92 height: units.gu(6)66 }
93 width: units.gu(6)67
94 }68 Label {
95 }69 id: contactName
96 Label {70
97 id: contactName71 property string name: application.contactNameFromVCard(attachment.filePath)
98 property string name: application.contactNameFromVCard(attachment.filePath)72
99 anchors.bottom: bubble.bottom73 anchors {
100 anchors.left: incoming ? bubble.right : undefined74 left: avatar.right
101 anchors.right: !incoming ? bubble.left : undefined75 leftMargin: units.gu(1)
102 anchors.rightMargin: !incoming ? units.gu(1) : undefined76 top: avatar.top
103 anchors.leftMargin: incoming ? units.gu(1) : undefined77 bottom: avatar.bottom
104 text: name !== "" ? name : i18n.tr("Unknown contact")78 right: parent.right
105 height: paintedHeight79 rightMargin: units.gu(1)
106 width: paintedWidth80 }
81
82 verticalAlignment: Text.AlignVCenter
83 text: name !== "" ? name : i18n.tr("Unknown contact")
84 elide: Text.ElideRight
85 color: vcardDelegate.incoming ? UbuntuColors.darkGrey : "#ffffff"
86 }
107 }87 }
108}88}
10989
=== modified file 'src/qml/MMS/MMSDefault.qml'
--- src/qml/MMS/MMSDefault.qml 2014-07-31 19:01:23 +0000
+++ src/qml/MMS/MMSDefault.qml 2014-08-12 15:32:18 +0000
@@ -16,54 +16,16 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import ".."21import ".."
2222
23MMSBase {23MMSBase {
24 id: defaultDelegate24 id: defaultDelegate
25 property var attachment25
26 property bool incoming
27 property string previewer: ""
28 property string textColor: incoming ? "#333333" : "#ffffff"
29 anchors.left: parent.left26 anchors.left: parent.left
30 anchors.right: parent.right27 anchors.right: parent.right
31 onItemClicked: {
32 if (checkClick(bubble, mouse)) {
33 attachmentClicked()
34 }
35 }
36 state: incoming ? "incoming" : "outgoing"
37 states: [
38 State {
39 name: "incoming"
40 AnchorChanges {
41 target: bubble
42 anchors.left: parent.left
43 anchors.right: undefined
44 }
45 PropertyChanges {
46 target: bubble
47 anchors.leftMargin: units.gu(1)
48 anchors.rightMargin: units.gu(1)
49 }
50 },
51 State {
52 name: "outgoing"
53 AnchorChanges {
54 target: bubble
55 anchors.left: undefined
56 anchors.right: parent.right
57 }
58 PropertyChanges {
59 target: bubble
60 anchors.leftMargin: units.gu(1)
61 anchors.rightMargin: units.gu(1)
62 }
63 }
64 ]
65 height: bubble.height + units.gu(1)28 height: bubble.height + units.gu(1)
66 clip: true
67 Item {29 Item {
68 id: bubble30 id: bubble
69 anchors.top: parent.top31 anchors.top: parent.top
7032
=== modified file 'src/qml/MMS/MMSImage.qml'
--- src/qml/MMS/MMSImage.qml 2014-07-31 19:01:23 +0000
+++ src/qml/MMS/MMSImage.qml 2014-08-12 15:32:18 +0000
@@ -16,27 +16,19 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.120import Ubuntu.Components 1.1
21import Ubuntu.Contacts 0.1
22import ".."
2321
24MMSBase {22MMSBase {
25 id: imageDelegate23 id: imageDelegate
26 property string previewer: "MMS/PreviewerImage.qml"
27 onItemClicked: {
28 if (checkClick(bubble, mouse)) {
29 attachmentClicked()
30 }
31 }
3224
25 previewer: "MMS/PreviewerImage.qml"
33 height: imageAttachment.height26 height: imageAttachment.height
27 width: imageAttachment.width
28
34 UbuntuShape {29 UbuntuShape {
35 id: bubble30 id: bubble
36 anchors {31 anchors.top: parent.top
37 top: parent.top
38 bottom: parent.bottom
39 }
40 width: image.width32 width: image.width
41 height: image.height33 height: image.height
4234
@@ -49,16 +41,42 @@
49 smooth: true41 smooth: true
50 source: attachment.filePath42 source: attachment.filePath
51 visible: false43 visible: false
52 }44 asynchronous: true
53 }45
5446 onStatusChanged: {
55 Loader {47 if (status === Image.Error) {
56 active: (index == visibleAttachments-1) && !incoming && mmsText == "" && (inProgress || failed)48 source = "image://theme/image-missing"
57 visible: active49 width = 128
58 height: active ? item.height : 050 height = 128
59 sourceComponent: statusIcon51 }
60 anchors.right: bubble.left52 }
61 anchors.rightMargin: units.gu(1)53 }
62 anchors.verticalCenter: bubble.verticalCenter54
55 Rectangle {
56 visible: imageDelegate.lastItem
57 gradient: Gradient {
58 GradientStop { position: 0.0; color: "transparent" }
59 GradientStop { position: 1.0; color: "gray" }
60 }
61
62 anchors {
63 bottom: parent.bottom
64 left: parent.left
65 right: parent.right
66 }
67 height: units.gu(2)
68 radius: bubble.height * 0.1
69 Label {
70 anchors{
71 left: parent.left
72 bottom: parent.bottom
73 leftMargin: incoming ? units.gu(2) : units.gu(1)
74 bottomMargin: units.gu(0.5)
75 }
76 fontSize: "xx-small"
77 text: Qt.formatDateTime(timestamp, "hh:mm AP")
78 color: "white"
79 }
80 }
63 }81 }
64}82}
6583
=== modified file 'src/qml/MMS/MMSVideo.qml'
--- src/qml/MMS/MMSVideo.qml 2014-07-31 19:01:23 +0000
+++ src/qml/MMS/MMSVideo.qml 2014-08-12 15:32:18 +0000
@@ -16,54 +16,19 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import QtMultimedia 5.021import QtMultimedia 5.0
22import ".."22import ".."
2323
24MMSBase {24MMSBase {
25 id: videoDelegate25 id: videoDelegate
26 property var attachment26
27 property bool incoming27 previewer: "MMS/PreviewerVideo.qml"
28 property string previewer: "MMS/PreviewerVideo.qml"
29 anchors.left: parent.left28 anchors.left: parent.left
30 anchors.right: parent.right29 anchors.right: parent.right
31 onItemClicked: {
32 if (checkClick(bubble, mouse)) {
33 attachmentClicked()
34 }
35 }
36 state: incoming ? "incoming" : "outgoing"
37 states: [
38 State {
39 name: "incoming"
40 AnchorChanges {
41 target: bubble
42 anchors.left: parent.left
43 anchors.right: undefined
44 }
45 PropertyChanges {
46 target: bubble
47 anchors.leftMargin: units.gu(1)
48 anchors.rightMargin: units.gu(1)
49 }
50 },
51 State {
52 name: "outgoing"
53 AnchorChanges {
54 target: bubble
55 anchors.left: undefined
56 anchors.right: parent.right
57 }
58 PropertyChanges {
59 target: bubble
60 anchors.leftMargin: units.gu(1)
61 anchors.rightMargin: units.gu(1)
62 }
63 }
64 ]
65 height: bubble.height + units.gu(1)30 height: bubble.height + units.gu(1)
66 clip: true31
67 Item {32 Item {
68 id: bubble33 id: bubble
69 anchors.top: parent.top34 anchors.top: parent.top
7035
=== modified file 'src/qml/MMS/Previewer.qml'
--- src/qml/MMS/Previewer.qml 2014-06-13 19:39:49 +0000
+++ src/qml/MMS/Previewer.qml 2014-08-12 15:32:18 +0000
@@ -16,8 +16,8 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import Ubuntu.Content 0.121import Ubuntu.Content 0.1
22import ".."22import ".."
2323
2424
=== modified file 'src/qml/MMS/PreviewerContact.qml'
--- src/qml/MMS/PreviewerContact.qml 2014-07-30 18:23:16 +0000
+++ src/qml/MMS/PreviewerContact.qml 2014-08-12 15:32:18 +0000
@@ -16,12 +16,14 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import Ubuntu.Content 0.121import Ubuntu.Content 0.1
22import ".."22import ".."
2323
24Previewer {24Previewer {
25 title: application.contactNameFromVCard(attachment.filePath)25 property string contactName: application.contactNameFromVCard(attachment.filePath)
26
27 title: contactName !== "" ? contactName : i18n.tr("Unknown contact")
26 clip: true28 clip: true
27}29}
2830
=== modified file 'src/qml/MMS/PreviewerImage.qml'
--- src/qml/MMS/PreviewerImage.qml 2014-06-13 19:39:49 +0000
+++ src/qml/MMS/PreviewerImage.qml 2014-08-12 15:32:18 +0000
@@ -16,8 +16,8 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import Ubuntu.Content 0.121import Ubuntu.Content 0.1
22import ".."22import ".."
2323
2424
=== modified file 'src/qml/MMS/PreviewerVideo.qml'
--- src/qml/MMS/PreviewerVideo.qml 2014-05-30 21:16:51 +0000
+++ src/qml/MMS/PreviewerVideo.qml 2014-08-12 15:32:18 +0000
@@ -16,8 +16,8 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 0.120import Ubuntu.Components 1.1
21import QtMultimedia 5.021import QtMultimedia 5.0
22import ".."22import ".."
2323
2424
=== added file 'src/qml/MMSDelegate.qml'
--- src/qml/MMSDelegate.qml 1970-01-01 00:00:00 +0000
+++ src/qml/MMSDelegate.qml 2014-08-12 15:32:18 +0000
@@ -0,0 +1,198 @@
1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.2
20import Ubuntu.Components 1.1
21
22MessageDelegate {
23 id: root
24
25 property var dataAttachments: []
26 property var textAttachements: []
27
28 function clicked(mouse)
29 {
30 var childPoint = root.mapToItem(attachmentsView, mouse.x, mouse.y)
31 var attachment = attachmentsView.childAt(childPoint.x, childPoint.y)
32 if (attachment && attachment.item && attachment.item.previewer) {
33 var properties = {}
34 properties["attachment"] = attachment.item.attachment
35 mainStack.push(Qt.resolvedUrl(attachment.item.previewer), properties)
36 }
37 }
38
39 function deleteMessage()
40 {
41 eventModel.removeEvent(accountId, threadId, eventId, type)
42 }
43
44 function resendMessage()
45 {
46 var newAttachments = []
47 for (var i = 0; i < attachments.length; i++) {
48 var attachment = []
49 var item = textMessageAttachments[i]
50 // we dont include smil files. they will be auto generated
51 if (item.contentType.toLowerCase() === "application/smil") {
52 continue
53 }
54 attachment.push(item.attachmentId)
55 attachment.push(item.contentType)
56 attachment.push(item.filePath)
57 newAttachments.push(attachment)
58 }
59 eventModel.removeEvent(accountId, threadId, eventId, type)
60 chatManager.sendMMS(participants, textMessage, newAttachments, messages.accountId)
61 }
62
63 function copyMessage()
64 {
65 if (bubble.visible) {
66 Clipboard.push(bubble.messageText)
67 }
68 }
69
70 onAttachmentsChanged: {
71 dataAttachments = []
72 textAttachements = []
73 for (var i=0; i < attachments.length; i++) {
74 var attachment = attachments[i]
75 if (startsWith(attachment.contentType, "text/plain") ) {
76 textAttachements.push(attachment)
77 } else if (startsWith(attachment.contentType, "image/")) {
78 dataAttachments.push({"type": "image",
79 "data": attachment,
80 "delegateSource": "MMS/MMSImage.qml",
81 })
82 } else if (startsWith(attachment.contentType, "video/")) {
83 // TODO: implement proper video attachment support
84 // dataAttachments.push({type: "video",
85 // data: attachment,
86 // delegateSource: "MMS/MMSVideo.qml",
87 // })
88 } else if (startsWith(attachment.contentType, "application/smil") ||
89 startsWith(attachment.contentType, "application/x-smil")) {
90 // TODO: implement support for this kind of attachment
91 // dataAttachments.push({type: "application",
92 // data: attachment,
93 // delegateSource: "",
94 // })
95 } else if (startsWith(attachment.contentType, "text/vcard") ||
96 startsWith(attachment.contentType, "text/x-vcard")) {
97 dataAttachments.push({"type": "vcard",
98 "data": attachment,
99 "delegateSource": "MMS/MMSContact.qml"
100 })
101 } else {
102 console.log("No MMS render for " + attachment.contentType)
103 }
104 }
105 }
106 height: attachmentsView.height
107 _lastItem: bubble.visible ? bubble : attachmentsRepeater.itemAt(attachmentsRepeater - 1)
108 Column {
109 id: attachmentsView
110
111 anchors {
112 top: parent.top
113 left: parent.left
114 right: parent.right
115 }
116 height: childrenRect.height
117
118 Repeater {
119 id: attachmentsRepeater
120 model: dataAttachments
121
122 Loader {
123 id: attachmentLoader
124 asynchronous: true
125 states: [
126 State {
127 when: root.incoming
128 name: "incoming"
129 AnchorChanges {
130 target: attachmentLoader
131 anchors.left: parent.left
132 }
133 PropertyChanges {
134 target: attachmentLoader
135 anchors.leftMargin: units.gu(1)
136 anchors.rightMargin: 0
137 }
138 },
139 State {
140 when: !root.incoming
141 name: "outgoing"
142 AnchorChanges {
143 target: attachmentLoader
144 anchors.right: parent.right
145 }
146 PropertyChanges {
147 target: attachmentLoader
148 anchors.leftMargin: 0
149 anchors.rightMargin: units.gu(1)
150 }
151 }
152 ]
153
154 Component.onCompleted: {
155 var initialProperties = {
156 "incoming": root.incoming,
157 "attachment": modelData.data,
158 "timestamp": timestamp,
159 "lastItem": (index === (attachmentsRepeater.count - 1)) && (textAttachements.length === 0)
160 }
161 setSource(modelData.delegateSource, initialProperties)
162 }
163 }
164 }
165
166 // TODO: is possible to have more than one text ???
167 MessageBubble {
168 id: bubble
169
170 property string textData: application.readTextFile(root.textAttachements[0].filePath)
171
172 states: [
173 State {
174 when: root.incoming
175 name: "incoming"
176 AnchorChanges {
177 target: bubble
178 anchors.left: parent.left
179 }
180 },
181 State {
182 name: "outgoing"
183 when: !root.incoming
184 AnchorChanges {
185 target: bubble
186 anchors.right: parent.right
187 }
188 }
189 ]
190 visible: (root.textAttachements.length > 0)
191 messageText: textData.length > 0 ? textData : i18n.tr("Missing message data")
192 messageTimeStamp: root.timestamp
193 messageStatus: textMessageStatus
194 messageIncoming: root.incoming
195 accountName: root.accountLabel
196 }
197 }
198}
0199
=== modified file 'src/qml/MainPage.qml'
--- src/qml/MainPage.qml 2014-08-12 15:32:18 +0000
+++ src/qml/MainPage.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.120import Ubuntu.Components 1.1
21import Ubuntu.Components.ListItems 0.1 as ListItem21import Ubuntu.Components.ListItems 0.1 as ListItem
22import Ubuntu.History 0.122import Ubuntu.History 0.1
2323
=== modified file 'src/qml/MessageBubble.qml'
--- src/qml/MessageBubble.qml 2014-08-01 02:36:29 +0000
+++ src/qml/MessageBubble.qml 2014-08-12 15:32:18 +0000
@@ -27,15 +27,16 @@
27 id: root27 id: root
2828
29 property int messageStatus: -129 property int messageStatus: -1
30 property bool incoming: false30 property bool messageIncoming: false
31 property alias sender: senderName.text31 property alias sender: senderName.text
32 property string messageText32 property string messageText
33 property var messageTimeStamp33 property var messageTimeStamp
34 property int maxDelegateWidth: units.gu(30)34 property int maxDelegateWidth: units.gu(27)
35 property string accountName
3536
36 readonly property bool error: (messageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)37 readonly property bool error: (messageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
37 readonly property bool sending: (messageStatus === HistoryThreadModel.MessageStatusUnknown ||38 readonly property bool sending: (messageStatus === HistoryThreadModel.MessageStatusUnknown ||
38 messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming39 messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !messageIncoming
3940
40 function selectBubble() {41 function selectBubble() {
41 var fileName = "assets/conversation_";42 var fileName = "assets/conversation_";
@@ -43,7 +44,7 @@
43 fileName += "error.sci"44 fileName += "error.sci"
44 } else if (sending) {45 } else if (sending) {
45 fileName += "pending.sci"46 fileName += "pending.sci"
46 } else if (incoming) {47 } else if (messageIncoming) {
47 fileName += "incoming.sci";48 fileName += "incoming.sci";
48 } else {49 } else {
49 fileName += "outgoing.sci";50 fileName += "outgoing.sci";
@@ -63,11 +64,11 @@
63 return text.replace(phoneExp, '<a href="tel:///$1">$1</a>');64 return text.replace(phoneExp, '<a href="tel:///$1">$1</a>');
64 }65 }
6566
66 onIncomingChanged: source = selectBubble()67 onMessageIncomingChanged: source = selectBubble()
67 source: selectBubble()68 source: selectBubble()
68 height: childrenRect.height + units.gu(2)69 height: senderName.height + textLabel.height + textTimestamp.height + units.gu(3)
69 width: Math.min(units.gu(27),70 width: Math.min(units.gu(27),
70 Math.max(textLabel.text.length, textTimestamp.text.length) * units.gu(1))71 Math.max(textLabel.contentWidth, textTimestamp.contentWidth))
71 + border.left + border.right72 + border.left + border.right
72 Label {73 Label {
73 id: senderName74 id: senderName
@@ -76,7 +77,7 @@
76 top: parent.top77 top: parent.top
77 topMargin: units.gu(1)78 topMargin: units.gu(1)
78 left: parent.left79 left: parent.left
79 leftMargin: incoming ? units.gu(2) : units.gu(1)80 leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
80 }81 }
81 height: text === "" ? 0 : paintedHeight82 height: text === "" ? 0 : paintedHeight
82 fontSize: "large"83 fontSize: "large"
@@ -91,17 +92,15 @@
91 top: sender == "" ? parent.top : senderName.bottom92 top: sender == "" ? parent.top : senderName.bottom
92 topMargin: units.gu(1)93 topMargin: units.gu(1)
93 left: parent.left94 left: parent.left
94 leftMargin: incoming ? units.gu(2) : units.gu(1)95 leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
95 right: parent.right
96 rightMargin: incoming ? units.gu(1) : units.gu(1)
97 }96 }
98 width: maxDelegateWidth97 width: maxDelegateWidth
99 fontSize: "medium"98 fontSize: "medium"
100 height: text === "" ? 0 : paintedHeight99 height: contentHeight
101 onLinkActivated: Qt.openUrlExternally(link)100 onLinkActivated: Qt.openUrlExternally(link)
102 text: root.parseText(messageText)101 text: root.parseText(messageText)
103 wrapMode: Text.Wrap102 wrapMode: Text.Wrap
104 color: root.incoming ? UbuntuColors.darkGrey : "white"103 color: root.messageIncoming ? UbuntuColors.darkGrey : "white"
105 }104 }
106105
107 Label {106 Label {
@@ -110,16 +109,25 @@
110109
111 anchors{110 anchors{
112 top: textLabel.bottom111 top: textLabel.bottom
113 topMargin: units.gu(0.5)112 topMargin: units.gu(1)
114 left: parent.left113 left: parent.left
115 leftMargin: incoming ? units.gu(2) : units.gu(1)114 leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1)
116 }115 }
117116
118 visible: !root.sending117 visible: !root.sending
119 height: visible ? paintedHeight : 0118 height: units.gu(2)
119 width: visible ? maxDelegateWidth : 0
120 fontSize: "xx-small"120 fontSize: "xx-small"
121 color: root.incoming ? UbuntuColors.lightGrey : "white"121 color: root.messageIncoming ? UbuntuColors.lightGrey : "white"
122 opacity: root.incoming ? 1.0 : 0.8122 opacity: root.messageIncoming ? 1.0 : 0.8
123 text: Qt.formatDateTime(messageTimeStamp, "hh:mm AP")123 elide: Text.ElideRight
124 text: {
125 var str = Qt.formatDateTime(messageTimeStamp, "hh:mm AP")
126 if (root.accountName.length === 0) {
127 return str
128 }
129 str += " @ %1".arg(root.accountName)
130 return str
131 }
124 }132 }
125}133}
126134
=== added file 'src/qml/MessageDateSection.qml'
--- src/qml/MessageDateSection.qml 1970-01-01 00:00:00 +0000
+++ src/qml/MessageDateSection.qml 2014-08-12 15:32:18 +0000
@@ -0,0 +1,38 @@
1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.2
20import Ubuntu.Components 1.1
21import Ubuntu.Components.ListItems 0.1 as ListItem
22
23Item {
24 property alias text: label.text
25
26 height: units.gu(3)
27 Label {
28 id: label
29
30 anchors.fill: parent
31 elide: Text.ElideRight
32 verticalAlignment: Text.AlignVCenter
33 fontSize: "small"
34 }
35 ListItem.ThinDivider {
36 anchors.bottom: parent.bottom
37 }
38}
039
=== modified file 'src/qml/MessageDelegate.qml'
--- src/qml/MessageDelegate.qml 2014-07-31 19:58:54 +0000
+++ src/qml/MessageDelegate.qml 2014-08-12 15:32:18 +0000
@@ -16,242 +16,46 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.1
21import Ubuntu.Components.Popups 0.1
22import Ubuntu.History 0.1
23import Ubuntu.Telephony 0.1
24import Ubuntu.Content 0.1
25import Ubuntu.Contacts 0.1
26
27import "dateUtils.js" as DateUtils
2820
29Item {21Item {
30 id: messageDelegate22 id: messageDelegate
3123 objectName: "messageDelegate"
32 property alias incoming: bubble.incoming24
33 property string textColor: incoming ? "#333333" : "white"25 property bool incoming
34 property bool unread: false26 property var attachments
35 property variant activeAttachment27 property string accountId
36 property string mmsText: ""28 property var threadId
37 property string mmsTextId: ""29 property var eventId
38 property string accountLabel: ""30 property var type
39 property bool selectionMode: false31 property string text
40 property bool selected: false32 property var timestamp
41 property bool inProgress: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||33 property string accountLabel
42 textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed)34 property var _lastItem: messageDelegate
43 property bool failed: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)35
44 property int visibleAttachments: 036
4537 function deleteMessage()
46 signal resend()38 {
47 signal itemPressAndHold(QtObject obj)39 //virtual implemented by each Message type
48 signal itemClicked(QtObject obj)40 }
4941
50 anchors {42 function copyMessage()
51 left: parent ? parent.left : undefined43 {
52 right: parent ? parent.right: undefined44 //virtual implemented by each Message type
53 }45 }
54 height: attachments.height + bubbleItem.height46
5547 function resendMessage()
56 Component {48 {
57 id: statusIcon49 //virtual implemented by each Message type
58 Item {50 }
59 height: units.gu(4)51
60 width: units.gu(4)52 function showMessageDetails(mouse)
61 visible: !incoming && !messageDelegate.selectionMode53 {
62 ActivityIndicator {54 //virtual implemented by each Message type
63 id: indicator55 }
6456
65 anchors.centerIn: parent57 function clicked(mouse)
66 height: units.gu(2)58 {
67 width: units.gu(2)59 //virtual implemented by each Message type
68 visible: running && !selectionMode60 }
69 // if temporarily failed or unknown status, then show the spinner
70 running: inProgress
71 }
72
73 Item {
74 id: retrybutton
75
76 anchors.fill: parent
77 Icon {
78 id: icon
79
80 name: "reload"
81 color: "red"
82 height: units.gu(2)
83 width: units.gu(2)
84 anchors {
85 centerIn: parent
86 verticalCenterOffset: units.gu(-1)
87 }
88 }
89
90 Label {
91 text: i18n.tr("Failed!")
92 fontSize: "small"
93 color: "red"
94 anchors {
95 horizontalCenter: retrybutton.horizontalCenter
96 top: icon.bottom
97 }
98 }
99 visible: failed
100 MouseArea {
101 id: retrybuttonMouseArea
102
103 anchors.fill: parent
104 onClicked: messageDelegate.resend()
105 }
106 }
107 }
108 }
109
110 Column {
111 id: attachments
112 anchors {
113 top: parent.top
114 left: parent.left
115 right: parent.right
116 }
117 height: childrenRect.height
118 Repeater {
119 id: attachmentsRepeater
120
121 model: textMessageAttachments
122 Loader {
123 anchors {
124 left: parent ? parent.left : undefined
125 right: parent ? parent.right : undefined
126 }
127 height: item ? item.height : 0
128 source: {
129 if (startsWith(modelData.contentType, "image/")) {
130 return "MMS/MMSImage.qml"
131 } else if (startsWith(modelData.contentType, "video/")) {
132 return "MMS/MMSVideo.qml"
133 } else if (startsWith(modelData.contentType, "application/smil") ||
134 startsWith(modelData.contentType, "application/x-smil")) {
135 return ""
136 } else if (startsWith(modelData.contentType, "text/plain") ) {
137 mmsText = application.readTextFile(modelData.filePath)
138 mmsTextId = modelData.attachmentId
139 return ""
140 } else if (startsWith(modelData.contentType, "text/vcard") ||
141 startsWith(modelData.contentType, "text/x-vcard")) {
142 return "MMS/MMSContact.qml"
143 } else {
144 console.log("No MMS render for " + modelData.contentType)
145 return "MMS/MMSDefault.qml"
146 }
147 }
148 onStatusChanged: {
149 if (status == Loader.Ready) {
150 item.attachment = modelData
151 item.incoming = incoming
152 }
153 }
154 Connections {
155 target: item
156 onItemRemoved: {
157 eventModel.removeEventAttachment(accountId, threadId, eventId, type, modelData.attachmentId)
158 if (visibleAttachments == 1 && mmsText === "") {
159 // this is the last attachment. remove the whole event
160 eventModel.removeEvent(accountId, threadId, eventId, type)
161 return
162 }
163 }
164 }
165 Connections {
166 target: item
167 onItemPressAndHold: itemPressAndHold(bubbleItem)
168 }
169 Binding {
170 target: item
171 property: "parentSelected"
172 value: messageDelegate.selected
173 }
174 Connections {
175 target: item
176 onAttachmentClicked: {
177 if (item.previewer === "") {
178 activeAttachment = modelData
179 PopupUtils.open(popoverSaveAttachmentComponent, item)
180 return
181 }
182
183 var properties = {}
184 properties["attachment"] = item.attachment
185 mainStack.push(Qt.resolvedUrl(item.previewer), properties)
186 }
187 }
188 }
189 }
190 }
191
192 ListItemWithActions {
193 id: bubbleItem
194
195 anchors {
196 top: attachments.bottom
197 left: parent.left
198 right: parent.right
199 }
200 internalAnchors {
201 topMargin: 0
202 bottomMargin: 0
203 }
204
205 height: bubble.visible ? bubble.height : 0
206 leftSideAction: Action {
207 iconName: "delete"
208 text: i18n.tr("Delete")
209 onTriggered: {
210 // if there are no attachments, remove the whole message
211 if (visibleAttachments == 0) {
212 eventModel.removeEvent(accountId, threadId, eventId, type)
213 return
214 }
215 // check if this is an mms text and we have more attachments
216 if (mmsText !== "" && visibleAttachments > 1) {
217 // remove only the text attachment if we have more attachments
218 eventModel.removeEventAttachment(accountId, threadId, eventId, type, mmsTextId)
219 mmsText = ""
220 mmsTextId = ""
221 return
222 }
223 }
224 }
225
226 selected: messageDelegate.selected
227 selectionMode: messageDelegate.selectionMode
228 onItemPressAndHold: messageDelegate.itemPressAndHold(bubbleItem)
229 onItemClicked: messageDelegate.itemClicked(bubbleItem)
230 onSwippingChanged: messageList.updateSwippedItem(bubbleItem)
231 onSwipeStateChanged: messageList.updateSwippedItem(bubbleItem)
232
233 MessageBubble {
234 id: bubble
235
236 anchors {
237 top: parent.top
238 left: incoming ? parent.left : undefined
239 right: incoming ? undefined : parent.right
240 }
241 visible: (messageText !== "")
242 messageText: textMessage !== "" ? textMessage : mmsText
243 messageTimeStamp: timestamp
244 messageStatus: textMessageStatus
245 }
246
247 Loader {
248 id: statusIconLoader
249 active: !incoming && !messageDelegate.selectionMode && bubble.visible && (inProgress || failed)
250 sourceComponent: statusIcon
251 anchors.right: bubble.left
252 anchors.rightMargin: units.gu(1)
253 anchors.verticalCenter: bubble.verticalCenter
254 }
255 }
256
257}61}
25862
=== added file 'src/qml/MessageDelegateFactory.qml'
--- src/qml/MessageDelegateFactory.qml 1970-01-01 00:00:00 +0000
+++ src/qml/MessageDelegateFactory.qml 2014-08-12 15:32:18 +0000
@@ -0,0 +1,203 @@
1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.2
20import Ubuntu.Components 1.1
21import Ubuntu.Contacts 0.1
22import Ubuntu.History 0.1
23
24ListItemWithActions {
25 id: root
26
27 property bool incoming: false
28 property var _lastItem: loader.status === Loader.Ready ? loader.item._lastItem : null
29 property list<Action> _availableActions
30 property string accountLabel
31
32 signal deleteMessage()
33 signal resendMessage()
34 signal copyMessage()
35 signal showMessageDetails()
36
37 triggerActionOnMouseRelease: true
38 width: messageList.width
39 leftSideAction: Action {
40 iconName: "delete"
41 text: i18n.tr("Delete")
42 onTriggered: deleteMessage()
43 }
44
45 // WORKAROUND: to filter actions on rightSideActions property based on message status
46 _availableActions: [
47 Action {
48 id: reloadAction
49
50 iconName: "reload"
51 text: i18n.tr("Retry")
52 onTriggered: resendMessage()
53 },
54 Action {
55 id: copyAction
56
57 iconName: "edit-copy"
58 text: i18n.tr("Copy")
59 onTriggered: copyMessage()
60 },
61 Action {
62 id: infoAction
63
64 iconName: "info"
65 text: i18n.tr("Info")
66 onTriggered: {
67 // FIXME: Is that the corect way to do that?
68 var messageType = textMessageAttachments.length > 0 ? i18n.tr("MMS") : i18n.tr("SMS")
69 var messageInfo = {"type": messageType,
70 "senderId": senderId,
71 "timestamp": timestamp,
72 "textReadTimestamp": textReadTimestamp,
73 "status": textMessageStatus}
74 messageInfoDialog.showMessageInfo(messageInfo)
75 }
76 }
77 ]
78
79 rightSideActions: {
80 var actions = []
81 if (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) {
82 actions.push(reloadAction)
83 }
84 actions.push(copyAction)
85 actions.push(infoAction)
86 return actions
87 }
88
89 height: loader.height + units.gu(1)
90 internalAnchors {
91 topMargin: units.gu(0.5)
92 bottomMargin: units.gu(0.5)
93 }
94
95 onItemClicked: {
96 if (!selectionMode && (loader.status === Loader.Ready)) {
97 loader.item.clicked(mouse)
98 }
99 }
100
101 Loader {
102 id: loader
103
104 onStatusChanged: {
105 if (status === Loader.Ready) {
106 //signals
107 root.resendMessage.connect(item.resendMessage)
108 root.deleteMessage.connect(item.deleteMessage)
109 root.copyMessage.connect(item.copyMessage)
110 root.showMessageDetails(item.showMessageDetails)
111 }
112 }
113 anchors {
114 left: parent.left
115 right: parent.right
116 }
117 height: status == Loader.Ready ? item.height : 0
118 Component.onCompleted: {
119 var initialProperties = {
120 "incoming": root.incoming,
121 "accountLabel": accountLabel,
122 "attachments": textMessageAttachments,
123 "accountId": accountId,
124 "threadId": threadId,
125 "eventId": eventId,
126 "type": type,
127 "text": textMessage,
128 "timestamp": timestamp
129 }
130 if (textMessageAttachments.length > 0) {
131 setSource(Qt.resolvedUrl("MMSDelegate.qml"), initialProperties)
132 } else {
133 setSource(Qt.resolvedUrl("SMSDelegate.qml"), initialProperties)
134 }
135 }
136 }
137
138 Item {
139 id: statusIcon
140
141 height: units.gu(4)
142 width: units.gu(4)
143 parent: _lastItem
144 anchors {
145 verticalCenter: parent ? parent.verticalCenter : undefined
146 right: parent ? parent.left : undefined
147 rightMargin: units.gu(2)
148 }
149
150 visible: !incoming && !selectionMode
151 ActivityIndicator {
152 id: indicator
153
154 anchors.centerIn: parent
155 height: units.gu(2)
156 width: units.gu(2)
157 visible: running && !selectionMode
158 // if temporarily failed or unknown status, then show the spinner
159 running: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown ||
160 textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed)
161 }
162
163 Item {
164 id: retrybutton
165
166 anchors.fill: parent
167 Icon {
168 id: icon
169
170 name: "reload"
171 color: "red"
172 height: units.gu(2)
173 width: units.gu(2)
174 anchors {
175 centerIn: parent
176 verticalCenterOffset: units.gu(-1)
177 }
178 }
179
180 Label {
181 text: i18n.tr("Failed!")
182 fontSize: "small"
183 color: "red"
184 anchors {
185 horizontalCenter: retrybutton.horizontalCenter
186 top: icon.bottom
187 }
188 }
189 visible: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed)
190 MouseArea {
191 id: retrybuttonMouseArea
192
193 anchors.fill: parent
194 onClicked: root.resendMessage()
195 }
196 }
197
198
199 MessageInfoDialog {
200 id: messageInfoDialog
201 }
202 }
203}
0204
=== added file 'src/qml/MessageInfoDialog.qml'
--- src/qml/MessageInfoDialog.qml 1970-01-01 00:00:00 +0000
+++ src/qml/MessageInfoDialog.qml 2014-08-12 15:32:18 +0000
@@ -0,0 +1,124 @@
1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.2
20import Ubuntu.Components 1.1
21import Ubuntu.Components.Popups 0.1
22import Ubuntu.History 0.1
23
24
25Item {
26 id: root
27
28 property QtObject activeDialog: null
29 property var activeMessage: null
30
31 function showMessageInfo(message)
32 {
33 if (!activeDialog) {
34 activeMessage = message
35 activeDialog = PopupUtils.open(messageInfoDialog, messages)
36 }
37 }
38
39 Component {
40 id: messageInfoDialog
41
42 Dialog {
43 id: dialogue
44
45 parent: messages
46
47 function statusToString(status)
48 {
49 switch(status)
50 {
51 case HistoryThreadModel.MessageStatusDelivered:
52 return i18n.tr("Delivered")
53 case HistoryThreadModel.MessageStatusTemporarilyFailed:
54 return i18n.tr("Temporarily Failed")
55 case HistoryThreadModel.MessageStatusPermanentlyFailed:
56 return i18n.tr("Failed")
57 case HistoryThreadModel.MessageStatusAccepted:
58 return i18n.tr("Accepted")
59 case HistoryThreadModel.MessageStatusRead:
60 return i18n.tr("Read")
61 case HistoryThreadModel.MessageStatusDeleted:
62 return i18n.tr("Deleted")
63 case HistoryThreadModel.MessageStatusPending:
64 return i18n.tr("Pending")
65 case HistoryThreadModel.MessageStatusUnknown:
66 //FIXME: Received messages has Unknown status is that correct??
67 if (root.activeMessage.senderId !== "self") {
68 return i18n.tr("Received")
69 } else {
70 return i18n.tr("Unknown")
71 }
72 default:
73 return i18n.tr("Unknown")
74 }
75 }
76
77
78 title: i18n.tr("Message info")
79
80 anchors.centerIn: parent
81 height: childrenRect.height
82 width: childrenRect.width
83
84 Label {
85 text: "<b>%1:</b> %2".arg(i18n.tr("Type")).arg(root.activeMessage.type)
86 }
87
88 Label {
89 text: "<b>%1:</b> %2".arg(i18n.tr("From")).arg(root.activeMessage.senderId !== "self" ? root.activeMessage.senderId : i18n.tr("Myself"))
90 }
91
92 Label {
93 text: "<b>%1:</b> %2".arg(i18n.tr("Sent")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate))
94 visible: (root.activeMessage.senderId === "self")
95 }
96
97 Label {
98 text: "<b>%1:</b> %2".arg(i18n.tr("Received")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate))
99 visible: (root.activeMessage.senderId !== "self")
100 }
101
102 Label {
103 text: "<b>%1:</b> %2".arg(i18n.tr("Read")).arg(Qt.formatDateTime(root.activeMessage.textReadTimestamp, Qt.DefaultLocaleShortDate))
104 visible: (root.activeMessage.senderId !== "self") && (root.activeMessage.textReadTimestamp > 0)
105 }
106
107 Label {
108 text: "<b>%1:</b> %2".arg(i18n.tr("Status")).arg(statusToString(root.activeMessage.status))
109 }
110
111 Button {
112 text: i18n.tr("Close")
113 onClicked: {
114 PopupUtils.close(root.activeDialog)
115 }
116 }
117
118 Component.onDestruction: {
119 root.activeDialog = null
120 root.activeMessage = null
121 }
122 }
123 }
124}
0125
=== modified file 'src/qml/Messages.qml'
--- src/qml/Messages.qml 2014-08-12 15:32:18 +0000
+++ src/qml/Messages.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import QtQuick.Window 2.020import QtQuick.Window 2.0
21import QtContacts 5.021import QtContacts 5.0
22import Ubuntu.Components 1.122import Ubuntu.Components 1.1
@@ -28,12 +28,16 @@
28import Ubuntu.Contacts 0.128import Ubuntu.Contacts 0.1
29import QtContacts 5.029import QtContacts 5.0
3030
31import "dateUtils.js" as DateUtils
32
31Page {33Page {
32 id: messages34 id: messages
33 objectName: "messagesPage"35 objectName: "messagesPage"
36
34 // this property can be overriden by the user using the account switcher,37 // this property can be overriden by the user using the account switcher,
35 // in the suru divider38 // in the suru divider
36 property QtObject account: mainView.defaultAccount39 property QtObject account: mainView.defaultAccount
40
37 property variant participants: []41 property variant participants: []
38 property bool groupChat: participants.length > 142 property bool groupChat: participants.length > 1
39 property bool keyboardFocus: true43 property bool keyboardFocus: true
@@ -41,7 +45,6 @@
41 // FIXME: MainView should provide if the view is in portait or landscape45 // FIXME: MainView should provide if the view is in portait or landscape
42 property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)46 property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
43 property bool landscape: orientationAngle == 90 || orientationAngle == 27047 property bool landscape: orientationAngle == 90 || orientationAngle == 270
44 property bool pendingMessage: false
45 property var activeTransfer: null48 property var activeTransfer: null
46 property int activeAttachmentIndex: -149 property int activeAttachmentIndex: -1
47 property var sharedAttachmentsTransfer: []50 property var sharedAttachmentsTransfer: []
@@ -111,7 +114,7 @@
111114
112 title: {115 title: {
113 if (selectionMode) {116 if (selectionMode) {
114 return i18n.tr("Edit")117 return i18n.tr(" ")
115 }118 }
116119
117 if (landscape) {120 if (landscape) {
@@ -127,7 +130,7 @@
127 if (participants.length == 1) {130 if (participants.length == 1) {
128 return firstRecipient131 return firstRecipient
129 } else {132 } else {
130 return i18n.tr("Group (%1 members)").arg(participants.length)133 return i18n.tr("Group (%1)").arg(participants.length)
131 }134 }
132 }135 }
133 return i18n.tr("New Message")136 return i18n.tr("New Message")
@@ -269,7 +272,7 @@
269 return -1272 return -1
270 }273 }
271 for (var i in telepathyHelper.accounts) {274 for (var i in telepathyHelper.accounts) {
272 if (telepathyHelper.accounts[i].accountId == messages.account.accountId) {275 if (telepathyHelper.accounts[i].accountId === messages.account.accountId) {
273 return i276 return i
274 }277 }
275 }278 }
@@ -277,9 +280,7 @@
277 }280 }
278 Connections {281 Connections {
279 target: messages.head.sections282 target: messages.head.sections
280 onSelectedIndexChanged: {283 onSelectedIndexChanged: messages.account = telepathyHelper.accounts[head.sections.selectedIndex]
281 messages.account = telepathyHelper.accounts[head.sections.selectedIndex]
282 }
283 }284 }
284285
285 Component {286 Component {
@@ -295,30 +296,13 @@
295 filterTerm: multiRecipient.searchString296 filterTerm: multiRecipient.searchString
296 showSections: false297 showSections: false
297 autoHideKeyboard: false298 autoHideKeyboard: false
298
299 states: [
300 State {
301 name: "empty"
302 when: contactSearch.count === 0
303 PropertyChanges {
304 target: contactSearch
305 height: 0
306 }
307 }
308 ]
309
310 anchors {299 anchors {
311 top: parent.top300 top: parent.top
312 topMargin: units.gu(1)301 topMargin: units.gu(1)
313 left: parent.left302 left: parent.left
314 right: parent.right303 right: parent.right
315 bottom: bottomPanel.top304 bottom: parent.bottom
316 }305 }
317
318 Behavior on height {
319 UbuntuNumberAnimation { }
320 }
321
322 InvalidFilter {306 InvalidFilter {
323 id: invalidFilter307 id: invalidFilter
324 }308 }
@@ -377,7 +361,7 @@
377 }361 }
378 height: units.gu(2)362 height: units.gu(2)
379 text: {363 text: {
380 // this is necessary to keep the string in the original format364 // this is necessary to keep the string in the original foverdrawormat
381 var originalText = contact.displayLabel.label365 var originalText = contact.displayLabel.label
382 var lowerSearchText = multiRecipient.searchString.toLowerCase()366 var lowerSearchText = multiRecipient.searchString.toLowerCase()
383 var lowerText = originalText.toLowerCase()367 var lowerText = originalText.toLowerCase()
@@ -422,16 +406,27 @@
422 }406 }
423407
424 Loader {408 Loader {
425 active: multiRecipient.searchString !== "" && multiRecipient.focus409 property int resultCount: (status === Loader.Ready) ? item.view.count : 0
426 sourceComponent: contactSearchComponent410
411 sourceComponent: (multiRecipient.searchString !== "") && multiRecipient.focus ? contactSearchComponent : null
427 clip: true412 clip: true
428 anchors {413 anchors {
429 top: parent.top414 top: parent.top
430 left: parent.left415 left: parent.left
431 right: parent.right416 right: parent.right
432 bottom: bottomPanel.top
433 }417 }
418 height: resultCount > 0 ? parent.height - keyboard.height : 0
434 z: 1419 z: 1
420 // WORKAROUND: we need to use opacity here visible FALSE cause the item to not load
421 opacity: height > 0 ? 1.0 : 0.0
422 Behavior on height {
423 UbuntuNumberAnimation { }
424 }
425
426 Rectangle {
427 anchors.fill: parent
428 color: Theme.palette.normal.background
429 }
435 }430 }
436431
437 ContactWatcher {432 ContactWatcher {
@@ -488,7 +483,13 @@
488 Action {483 Action {
489 objectName: "selectionModeSelectAllAction"484 objectName: "selectionModeSelectAllAction"
490 iconName: "select"485 iconName: "select"
491 onTriggered: messageList.selectAll()486 onTriggered: {
487 if (messageList.selectedItems.count === messageList.count) {
488 messageList.clearSelection()
489 } else {
490 messageList.selectAll()
491 }
492 }
492 },493 },
493 Action {494 Action {
494 objectName: "selectionModeDeleteAction"495 objectName: "selectionModeDeleteAction"
@@ -645,86 +646,66 @@
645 header: Item {646 header: Item {
646 height: units.gu(1)647 height: units.gu(1)
647 }648 }
648
649 spacing: units.gu(1)
650 listModel: participants.length > 0 ? sortProxy : null649 listModel: participants.length > 0 ? sortProxy : null
651 verticalLayoutDirection: ListView.BottomToTop650 verticalLayoutDirection: ListView.BottomToTop
652 highlightFollowsCurrentItem: false651 highlightFollowsCurrentItem: true
653 /*add: Transition {652 currentIndex: 0
654 UbuntuNumberAnimation {653 // keep the last item as currentItem
655 properties: "anchors.leftMargin"
656 from: -width
657 to: 0
658 }
659 UbuntuNumberAnimation {
660 properties: "anchors.rightMargin"
661 from: -width
662 to: 0
663 }
664 }*/
665654
666 listDelegate: MessageDelegate {655 listDelegate: Column {
667 id: messageDelegate656 id: messageDelegate
668 objectName: "message%1".arg(index)657
669 incoming: senderId != "self"658 // WORKAROUND: we can not use sections because the verticalLayoutDirection is ListView.BottomToTop the sections will appear
670 // TODO: we have several items inside659 // bellow the item
671 selected: messageList.isSelected(messageDelegate)660 MessageDateSection {
672 unread: newEvent661 text: DateUtils.friendlyDay(timestamp)
673 selectionMode: messages.selectionMode662 anchors {
674 accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : ""663 left: parent.left
675 // TODO: need select only the item664 right: parent.right
676 onItemClicked: {665 leftMargin: units.gu(2)
677 if (messageList.isInSelectionMode) {666 rightMargin: units.gu(2)
678 if (!messageList.selectItem(messageDelegate)) {667 }
679 messageList.deselectItem(messageDelegate)668 visible: (index === messageList.count) || !DateUtils.areSameDay(sortProxy.get(index+1).timestamp, timestamp)
680 }669 }
681 }670
682 }671 MessageDelegateFactory {
683 onItemPressAndHold: {672 objectName: "message%1".arg(index)
684 messageList.startSelection()673 incoming: senderId != "self"
685 messageList.selectItem(messageDelegate)674 // TODO: we have several items inside
686 }675 selected: messageList.isSelected(messageDelegate)
687676 selectionMode: messages.selectionMode
688 Component.onCompleted: {677 accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : ""
689 if (newEvent) {678 // TODO: need select only the item
690 messages.markMessageAsRead(accountId, threadId, eventId, type);679 onItemClicked: {
691 }680 if (messageList.isInSelectionMode) {
692 }681 if (!messageList.selectItem(messageDelegate)) {
693 onResend: {682 messageList.deselectItem(messageDelegate)
694 // resend this message and remove the old one
695 if (textMessageAttachments.length > 0) {
696 var newAttachments = []
697 for (var i = 0; i < textMessageAttachments.length; i++) {
698 var attachment = []
699 var item = textMessageAttachments[i]
700 // we dont include smil files. they will be auto generated
701 if (item.contentType.toLowerCase() == "application/smil") {
702 continue
703 }683 }
704 attachment.push(item.attachmentId)684 }
705 attachment.push(item.contentType)685 }
706 attachment.push(item.filePath)686 onItemPressAndHold: {
707 newAttachments.push(attachment)687 messageList.startSelection()
708 }688 messageList.selectItem(messageDelegate)
709 eventModel.removeEvent(accountId, threadId, eventId, type)689 }
710 chatManager.sendMMS(participants, textMessage, newAttachments, messages.account.accountId)690
711 return691 Component.onCompleted: {
712 }692 if (newEvent) {
713 eventModel.removeEvent(accountId, threadId, eventId, type)693 messages.markMessageAsRead(accountId, threadId, eventId, type);
714 chatManager.sendMessage(messages.participants, textMessage, messages.account.accountId)694 }
695 }
715 }696 }
716 }697 }
698
717 onSelectionDone: {699 onSelectionDone: {
718 for (var i=0; i < items.count; i++) {700 for (var i=0; i < items.count; i++) {
719 var event = items.get(i).model701 var event = items.get(i).model
720 eventModel.removeEvent(event.accountId, event.threadId, event.eventId, event.type)702 eventModel.removeEvent(event.accountId, event.threadId, event.eventId, event.type)
721 }703 }
722 }704 }
705
723 onCountChanged: {706 onCountChanged: {
724 if (messages.pendingMessage) {707 currentIndex = 0
725 messageList.contentY = 0708 positionViewAtBeginning()
726 messages.pendingMessage = false
727 }
728 }709 }
729 }710 }
730711
@@ -909,7 +890,7 @@
909 height: units.gu(4.3)890 height: units.gu(4.3)
910 style: MultiRecipientFieldStyle {}891 style: MultiRecipientFieldStyle {}
911 autoSize: true892 autoSize: true
912 maximumLineCount: 0893 maximumLineCount: attachments.count == 0 ? 8 : 4
913 placeholderText: i18n.tr("Write a message...")894 placeholderText: i18n.tr("Write a message...")
914 focus: textEntry.focus895 focus: textEntry.focus
915 font.family: "Ubuntu"896 font.family: "Ubuntu"
@@ -984,7 +965,6 @@
984 true)965 true)
985966
986 updateFilters()967 updateFilters()
987 messages.pendingMessage = true
988 if (attachments.count > 0) {968 if (attachments.count > 0) {
989 var newAttachments = []969 var newAttachments = []
990 for (var i = 0; i < attachments.count; i++) {970 for (var i = 0; i < attachments.count; i++) {
991971
=== modified file 'src/qml/MultiRecipientInput.qml'
--- src/qml/MultiRecipientInput.qml 2014-07-30 16:19:08 +0000
+++ src/qml/MultiRecipientInput.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.120import Ubuntu.Components 1.1
21import Ubuntu.Contacts 0.121import Ubuntu.Contacts 0.1
22import Ubuntu.Telephony 0.122import Ubuntu.Telephony 0.1
2323
=== modified file 'src/qml/NewRecipientPage.qml'
--- src/qml/NewRecipientPage.qml 2014-08-01 14:51:29 +0000
+++ src/qml/NewRecipientPage.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.120import Ubuntu.Components 1.1
21import Ubuntu.Contacts 0.121import Ubuntu.Contacts 0.1
22import QtContacts 5.022import QtContacts 5.0
2323
=== added file 'src/qml/SMSDelegate.qml'
--- src/qml/SMSDelegate.qml 1970-01-01 00:00:00 +0000
+++ src/qml/SMSDelegate.qml 2014-08-12 15:32:18 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.2
20import Ubuntu.Components 1.1
21
22import "dateUtils.js" as DateUtils
23
24MessageDelegate {
25 id: root
26
27 function deleteMessage()
28 {
29 eventModel.removeEvent(accountId, threadId, eventId, type)
30 }
31
32 function resendMessage()
33 {
34 eventModel.removeEvent(accountId, threadId, eventId, type)
35 chatManager.sendMessage(messages.participants, textMessage, messages.accountId)
36 }
37
38 function copyMessage()
39 {
40 Clipboard.push(bubble.messageText)
41 }
42
43 height: bubble.height
44 _lastItem: bubble
45
46 MessageBubble {
47 id: bubble
48
49 states: [
50 State {
51 name: "incoming"
52 when: incoming
53 AnchorChanges {
54 target: bubble
55 anchors.left: parent.left
56 }
57 },
58 State {
59 name: "outgoing"
60 when: !incoming
61 AnchorChanges {
62 target: bubble
63 anchors.right: parent.right
64 }
65 }
66
67 ]
68 visible: (root.text !== "")
69 messageIncoming: root.incoming
70 messageText: root.text
71 messageTimeStamp: root.timestamp
72 accountName: root.accountLabel
73 messageStatus: textMessageStatus
74 }
75}
076
=== modified file 'src/qml/StandardAnimation.qml'
--- src/qml/StandardAnimation.qml 2013-07-17 21:47:45 +0000
+++ src/qml/StandardAnimation.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
2020
21NumberAnimation {21NumberAnimation {
22 duration: 30022 duration: 300
2323
=== modified file 'src/qml/ThreadDelegate.qml'
--- src/qml/ThreadDelegate.qml 2014-08-12 15:32:18 +0000
+++ src/qml/ThreadDelegate.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Ubuntu.Components 1.120import Ubuntu.Components 1.1
21import Ubuntu.Components.Popups 0.121import Ubuntu.Components.Popups 0.1
22import Ubuntu.Telephony 0.122import Ubuntu.Telephony 0.1
@@ -44,7 +44,6 @@
44 return firstRecipient44 return firstRecipient
45 }45 }
4646
47 property bool selectionMode: false
48 property string textMessage: {47 property string textMessage: {
49 // check if this is an mms, if so, search for the actual text48 // check if this is an mms, if so, search for the actual text
50 var imageCount = 049 var imageCount = 0
@@ -111,9 +110,17 @@
111 ContactAvatar {110 ContactAvatar {
112 id: avatar111 id: avatar
113112
114 fallbackAvatarUrl: groupChat ? "image://theme/contact-group" : delegateHelper.avatar !== "" ? delegateHelper.avatar : "image://theme/contact"113 fallbackAvatarUrl: {
114 if (groupChat) {
115 return "image://theme/contact-group"
116 } else if (delegateHelper.avatar !== "") {
117 return delegateHelper.avatar
118 } else {
119 return "image://theme/contact"
120 }
121 }
115 fallbackDisplayName: delegateHelper.alias122 fallbackDisplayName: delegateHelper.alias
116 showAvatarPicture: (delegateHelper.avatar !== "") || (initials.length === 0) || groupChat123 showAvatarPicture: groupChat || (delegateHelper.avatar !== "") || (initials.length === 0)
117 anchors {124 anchors {
118 left: parent.left125 left: parent.left
119 top: parent.top126 top: parent.top
@@ -127,24 +134,35 @@
127 id: contactName134 id: contactName
128 anchors {135 anchors {
129 top: avatar.top136 top: avatar.top
137 topMargin: units.gu(0.5)
130 left: avatar.right138 left: avatar.right
131 leftMargin: units.gu(1)139 leftMargin: units.gu(1)
132 }140 }
133 fontSize: "medium"
134 color: UbuntuColors.lightAubergine141 color: UbuntuColors.lightAubergine
135 text: groupChat ? groupChatLabel : unknownContact ? delegateHelper.phoneNumber : delegateHelper.alias142 text: groupChat ? groupChatLabel : unknownContact ? delegateHelper.phoneNumber : delegateHelper.alias
136 }143 }
137144
138 Label {145 Row {
139 id: time146 id: time
147
140 anchors {148 anchors {
141 verticalCenter: contactName.verticalCenter149 verticalCenter: contactName.verticalCenter
142 right: parent.right150 right: parent.right
143 }151 }
144 fontSize: "x-small"152 Label {
145 text: Qt.formatDateTime(eventTimestamp,"h:mm ap")153 fontSize: "x-small"
154 font.weight: Font.DemiBold
155 opacity: 0.70
156 text: Qt.formatDateTime(eventTimestamp,"h:mm")
157 }
158 Label {
159 fontSize: "x-small"
160 opacity: 0.70
161 text: Qt.formatDateTime(eventTimestamp," ap")
162 }
146 }163 }
147 164
165
148 UbuntuShape {166 UbuntuShape {
149 id: unreadCountIndicator167 id: unreadCountIndicator
150 height: units.gu(2)168 height: units.gu(2)
@@ -181,20 +199,18 @@
181199
182 Label {200 Label {
183 id: latestMessage201 id: latestMessage
184 height: units.gu(3)202
185 anchors {203 anchors {
186 top: contactName.bottom204 top: contactName.bottom
187 topMargin: units.gu(0.5)205 topMargin: units.gu(0.5)
188 left: contactName.left206 left: contactName.left
189 right: time.left207 right: time.left
190 rightMargin: units.gu(3)208 rightMargin: units.gu(3)
209 bottom: avatar.bottom
191 }210 }
192 elide: Text.ElideRight211 elide: Text.ElideRight
193 maximumLineCount: 2
194 fontSize: "x-small"212 fontSize: "x-small"
195 wrapMode: Text.WordWrap
196 text: textMessage213 text: textMessage
197 font.weight: Font.Light
198 }214 }
199215
200 Item {216 Item {
201217
=== modified file 'src/qml/assets/conversation_incoming@27.png'
202Binary 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 differ218Binary 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
=== modified file 'src/qml/messaging-app.qml'
--- src/qml/messaging-app.qml 2014-08-12 15:32:18 +0000
+++ src/qml/messaging-app.qml 2014-08-12 15:32:18 +0000
@@ -16,7 +16,7 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */17 */
1818
19import QtQuick 2.019import QtQuick 2.2
20import Qt.labs.settings 1.020import Qt.labs.settings 1.0
21import Ubuntu.Components 1.121import Ubuntu.Components 1.1
22import Ubuntu.Components.ListItems 0.1 as ListItem22import Ubuntu.Components.ListItems 0.1 as ListItem
@@ -54,7 +54,7 @@
54 Connections {54 Connections {
55 target: telepathyHelper55 target: telepathyHelper
56 onSetupReady: {56 onSetupReady: {
57 if (multipleAccounts && !telepathyHelper.defaultMessagingAccount && 57 if (multipleAccounts && !telepathyHelper.defaultMessagingAccount &&
58 settings.mainViewDontAskCount < 3 && mainStack.depth === 1) {58 settings.mainViewDontAskCount < 3 && mainStack.depth === 1) {
59 PopupUtils.open(Qt.createComponent("Dialogs/NoDefaultSIMCardDialog.qml").createObject(mainView))59 PopupUtils.open(Qt.createComponent("Dialogs/NoDefaultSIMCardDialog.qml").createObject(mainView))
60 }60 }
6161
=== modified file 'tests/autopilot/messaging_app/emulators.py'
--- tests/autopilot/messaging_app/emulators.py 2014-08-12 15:32:18 +0000
+++ tests/autopilot/messaging_app/emulators.py 2014-08-12 15:32:18 +0000
@@ -57,8 +57,8 @@
57 """57 """
5858
59 time.sleep(2) # message is not always found on slow emulator59 time.sleep(2) # message is not always found on slow emulator
60 for message in self.select_many(MessageDelegate):60 for message in self.select_many(MessageDelegateFactory):
61 for item in self.select_many('Label'):61 for item in message.select_many('Label'):
62 if "text" in item.get_properties():62 if "text" in item.get_properties():
63 if item.get_properties()['text'] == text:63 if item.get_properties()['text'] == text:
64 return message64 return message
@@ -280,7 +280,7 @@
280 def enable_messages_selection_mode(self):280 def enable_messages_selection_mode(self):
281 """Enable the selection mode on the messages page by pressing and281 """Enable the selection mode on the messages page by pressing and
282 holding the first item"""282 holding the first item"""
283 message = self.wait_select_single("MessageDelegate",283 message = self.wait_select_single("MessageDelegateFactory",
284 objectName="message0")284 objectName="message0")
285 self.long_press(message)285 self.long_press(message)
286286
@@ -475,8 +475,7 @@
475475
476 def _get_message_delegate(self, index):476 def _get_message_delegate(self, index):
477 return self.wait_select_single(477 return self.wait_select_single(
478 'MessageDelegate', objectName='message{}'.format(index),478 'MessageDelegateFactory', objectName='message{}'.format(index))
479 unread=False)
480479
481 def _long_press_to_select_message(self, message):480 def _long_press_to_select_message(self, message):
482 # XXX We used to leave the pointing device pressed for three seconds,481 # XXX We used to leave the pointing device pressed for three seconds,
@@ -539,5 +538,5 @@
539 """Autopilot helper for ThreadDelegate."""538 """Autopilot helper for ThreadDelegate."""
540539
541540
542class MessageDelegate(ListItemWithActions):541class MessageDelegateFactory(ListItemWithActions):
543 """Autopilot helper for the MessageDelegate."""542 """Autopilot helper for the MessageDelegateFactory."""
544543
=== modified file 'tests/qml/tst_MessageBubble.qml'
--- tests/qml/tst_MessageBubble.qml 2014-07-31 17:24:57 +0000
+++ tests/qml/tst_MessageBubble.qml 2014-08-12 15:32:18 +0000
@@ -34,7 +34,7 @@
3434
35 height: parent.height / 335 height: parent.height / 3
3636
37 incoming: true37 messageIncoming: true
38 }38 }
3939
40 MessageBubble {40 MessageBubble {
@@ -44,7 +44,7 @@
44 anchors.top: incomingMessageBubble.bottom44 anchors.top: incomingMessageBubble.bottom
45 height: parent.height / 345 height: parent.height / 3
4646
47 incoming: false47 messageIncoming: false
48 }48 }
4949
50 MessageBubble {50 MessageBubble {
@@ -54,7 +54,7 @@
54 anchors.top: outgoingMessageBubble.bottom54 anchors.top: outgoingMessageBubble.bottom
55 height: parent.height / 355 height: parent.height / 3
5656
57 incoming: true57 messageIncoming: true
58 }58 }
5959
60 UbuntuTestCase {60 UbuntuTestCase {
@@ -67,7 +67,7 @@
67 }67 }
6868
69 function cleanup() {69 function cleanup() {
70 changeIncomingMessageBubble.incoming = true;70 changeIncomingMessageBubble.messageIncoming = true;
71 }71 }
7272
73 function getFileName(filePath) {73 function getFileName(filePath) {
@@ -93,7 +93,7 @@
93 function test_changeIncomingMustUpdateSource() {93 function test_changeIncomingMustUpdateSource() {
94 var changeIncomingMessageBubble = findChild(94 var changeIncomingMessageBubble = findChild(
95 root, 'changeIncomingMessageBubble');95 root, 'changeIncomingMessageBubble');
96 changeIncomingMessageBubble.incoming = false;96 changeIncomingMessageBubble.messageIncoming = false;
97 compare(97 compare(
98 getFileName(changeIncomingMessageBubble.source),98 getFileName(changeIncomingMessageBubble.source),
99 'conversation_outgoing.sci');99 'conversation_outgoing.sci');

Subscribers

People subscribed via source and target branches