Merge lp:~renatofilho/messaging-app/rtm-fit-finish2 into lp:messaging-app
- rtm-fit-finish2
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~renatofilho/messaging-app/rtm-fit-finish2 |
Merge into: | lp:messaging-app |
Diff against target: |
2612 lines (+1261/-658) 34 files modified
debian/control (+2/-0) debian/messaging-app.install (+1/-0) src/main.cpp (+2/-0) src/qml/CMakeLists.txt (+1/-0) src/qml/Dialogs/CMakeLists.txt (+7/-0) src/qml/Dialogs/NoDefaultSIMCardDialog.qml (+91/-0) src/qml/Dialogs/NoSIMCardSelectedDialog.qml (+38/-0) src/qml/Dialogs/SetDefaultSIMCardDialog.qml (+73/-0) 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 (+34/-2) 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 (+109/-106) 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 (+29/-1) tests/autopilot/messaging_app/emulators.py (+8/-7) tests/qml/tst_MessageBubble.qml (+5/-5) |
To merge this branch: | bzr merge lp:~renatofilho/messaging-app/rtm-fit-finish2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+229089@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-08-12.
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
You need the new model to get this working: https:/
- 202. By Renato Araujo Oliveira Filho
-
Parent branch merged.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 203. By Renato Araujo Oliveira Filho
-
Fixed retry button alingment.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:202
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:203
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 204. By Renato Araujo Oliveira Filho
-
Fixed QML warnings.
- 205. By Renato Araujo Oliveira Filho
-
Parent merged.
- 206. By Renato Araujo Oliveira Filho
-
Parent merged.
- 207. By Renato Araujo Oliveira Filho
-
[Messages] Make the bottom panel invisible during a contact search.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:207
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 208. By Renato Araujo Oliveira Filho
-
[Message] Fix search list view animation to appear and disappear.
- 209. By Renato Araujo Oliveira Filho
-
Use empty title on selection mode.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:208
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 210. By Renato Araujo Oliveira Filho
-
Added "Retry" action on righSide actions.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:209
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 211. By Renato Araujo Oliveira Filho
-
Revert changes on test CMakeLists.txt
- 212. By Renato Araujo Oliveira Filho
-
Fix retry button alingment.
- 213. By Renato Araujo Oliveira Filho
-
Avoid go to preview mode during the selection mode.
- 214. By Renato Araujo Oliveira Filho
-
Better implementation of avoid clicking on attachment during the selection mode.
- 215. By Renato Araujo Oliveira Filho
-
Only shows the number of participants on messaging chat window.
- 216. By Renato Araujo Oliveira Filho
-
Show the group icon for group conversation thread
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:210
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 217. By Renato Araujo Oliveira Filho
-
Fixed TreadDelegate top margin.
- 218. By Renato Araujo Oliveira Filho
-
Updated the white bubble.
Updated ThreadDelegate visuals.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:218
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 219. By Renato Araujo Oliveira Filho
-
Updated contact vcard attachment visual.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:219
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 220. By Renato Araujo Oliveira Filho
-
Add timestamp in image bottom if the message does not contain text.
- 221. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 222. By Renato Araujo Oliveira Filho
-
Implemented conversation section for dates.
- 223. By Renato Araujo Oliveira Filho
-
display account label in the timestamp.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:221
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:223
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 224. By Renato Araujo Oliveira Filho
- 225. By Renato Araujo Oliveira Filho
-
Set the minimum version required for qtdeclarative5-
ubuntu- contacts0. 1 - 226. By Renato Araujo Oliveira Filho
-
Fixed multiple selection mode.
- 227. By Renato Araujo Oliveira Filho
-
Update autopilot tests.
- 228. By Renato Araujo Oliveira Filho
-
Update autopilot tests.
- 229. By Renato Araujo Oliveira Filho
-
Fixed bubble size.
Fixed bubble font color for incoming message.
Fixed account label on bubble. - 230. By Renato Araujo Oliveira Filho
-
Fixed MessageBubble width.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:225
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:230
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 231. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 232. By Renato Araujo Oliveira Filho
-
Updated unit test.
- 233. By Renato Araujo Oliveira Filho
-
Used section to show the dates.
- 234. By Renato Araujo Oliveira Filho
-
Implemented message info dialog and right action.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:234
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 235. By Renato Araujo Oliveira Filho
-
Use Manual created sections because of the verticalLayoutD
irection used by Messages list view.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:235
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
None: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 236. By Renato Araujo Oliveira Filho
-
Update message info dialog.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:236
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 237. By Renato Araujo Oliveira Filho
-
Show hardcoded status "Received" for received messages.
- 238. By Renato Araujo Oliveira Filho
-
Fixed selectionMode for ThreadDelegate.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:238
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 239. By Renato Araujo Oliveira Filho
-
Make sure that the timestamp and sim name get ellipsized correct.
- 240. By Renato Araujo Oliveira Filho
-
Fixed timestamp maximum width.
- 241. By Renato Araujo Oliveira Filho
-
Fixed select all messages to make sure that unselect all if all messages is already selected.
- 242. By Renato Araujo Oliveira Filho
-
Fixed item display for missing file.
In case of the MMS data file was deleted we need to be able to display the message with the remaning information.
- 243. By Renato Araujo Oliveira Filho
-
Fixed contact preview page to show "Unknown contact" when the contact name is empty.
- 244. By Renato Araujo Oliveira Filho
-
Manually set the dialog parent.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:241
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:244
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-08-06 15:11:02 +0000 |
3 | +++ debian/control 2014-08-12 15:31:06 +0000 |
4 | @@ -13,6 +13,7 @@ |
5 | qtbase5-dev (>= 5.0), |
6 | qtdeclarative5-dev (>= 5.0), |
7 | qtdeclarative5-dev-tools, |
8 | + qtdeclarative5-gsettings1.0, |
9 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
10 | qtdeclarative5-ubuntu-history0.1, |
11 | qtpim5-dev, |
12 | @@ -33,6 +34,7 @@ |
13 | qtdeclarative5-ubuntu-telephony0.1 | qtdeclarative5-ubuntu-telephony-plugin, |
14 | qtdeclarative5-ubuntu-contacts0.1 (>= 0.2+14.10.20140805), |
15 | qtdeclarative5-qtcontacts-plugin, |
16 | + qml-module-qt-labs-settings, |
17 | Recommends: unity8 (>= 7.81.0~), |
18 | Description: messaging application for Ubuntu |
19 | An application to send and receive messages. |
20 | |
21 | === modified file 'debian/messaging-app.install' |
22 | --- debian/messaging-app.install 2014-06-26 19:26:17 +0000 |
23 | +++ debian/messaging-app.install 2014-08-12 15:31:06 +0000 |
24 | @@ -7,4 +7,5 @@ |
25 | usr/share/messaging-app/assets |
26 | usr/share/messaging-app/3rd_party |
27 | usr/share/messaging-app/MMS/*.qml |
28 | +usr/share/messaging-app/Dialogs/*.qml |
29 | usr/bin/*messaging-app* |
30 | |
31 | === modified file 'src/main.cpp' |
32 | --- src/main.cpp 2013-07-15 20:33:33 +0000 |
33 | +++ src/main.cpp 2014-08-12 15:31:06 +0000 |
34 | @@ -39,6 +39,8 @@ |
35 | int main(int argc, char** argv) |
36 | { |
37 | QGuiApplication::setApplicationName("Messaging App"); |
38 | + QGuiApplication::setOrganizationName("com.ubuntu.messaging-app"); |
39 | + |
40 | MessagingApplication application(argc, argv); |
41 | |
42 | if (!application.setup()) { |
43 | |
44 | === modified file 'src/qml/CMakeLists.txt' |
45 | --- src/qml/CMakeLists.txt 2014-07-31 13:29:54 +0000 |
46 | +++ src/qml/CMakeLists.txt 2014-08-12 15:31:06 +0000 |
47 | @@ -16,3 +16,4 @@ |
48 | install(DIRECTORY ${3RD_PARTY_DIR} DESTINATION ${MESSAGING_APP_DIR}) |
49 | |
50 | add_subdirectory(MMS) |
51 | +add_subdirectory(Dialogs) |
52 | |
53 | === added directory 'src/qml/Dialogs' |
54 | === added file 'src/qml/Dialogs/CMakeLists.txt' |
55 | --- src/qml/Dialogs/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
56 | +++ src/qml/Dialogs/CMakeLists.txt 2014-08-12 15:31:06 +0000 |
57 | @@ -0,0 +1,7 @@ |
58 | +file(GLOB DIALOGS_QML_JS_FILES *.qml *.js) |
59 | + |
60 | +# make the files visible on qtcreator |
61 | +add_custom_target(messaging_dialogs_QMlFiles ALL SOURCES ${DIALOGS_QML_JS_FILES}) |
62 | + |
63 | +install(FILES ${DIALOGS_QML_JS_FILES} DESTINATION ${MESSAGING_APP_DIR}/Dialogs) |
64 | + |
65 | |
66 | === added file 'src/qml/Dialogs/NoDefaultSIMCardDialog.qml' |
67 | --- src/qml/Dialogs/NoDefaultSIMCardDialog.qml 1970-01-01 00:00:00 +0000 |
68 | +++ src/qml/Dialogs/NoDefaultSIMCardDialog.qml 2014-08-12 15:31:06 +0000 |
69 | @@ -0,0 +1,91 @@ |
70 | +/* |
71 | + * Copyright 2012-2013 Canonical Ltd. |
72 | + * |
73 | + * This file is part of messaging-app. |
74 | + * |
75 | + * messaging-app is free software; you can redistribute it and/or modify |
76 | + * it under the terms of the GNU General Public License as published by |
77 | + * the Free Software Foundation; version 3. |
78 | + * |
79 | + * messaging-app is distributed in the hope that it will be useful, |
80 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
81 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
82 | + * GNU General Public License for more details. |
83 | + * |
84 | + * You should have received a copy of the GNU General Public License |
85 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
86 | + */ |
87 | + |
88 | +import QtQuick 2.0 |
89 | +import Ubuntu.Components 1.1 |
90 | +import Ubuntu.Components.Popups 0.1 |
91 | +import Ubuntu.Telephony 0.1 |
92 | + |
93 | +Component { |
94 | + Dialog { |
95 | + id: dialogue |
96 | + title: i18n.tr("Switch to default SIM:") |
97 | + Column { |
98 | + anchors.left: parent.left |
99 | + anchors.right: parent.right |
100 | + spacing: units.gu(2) |
101 | + |
102 | + Row { |
103 | + spacing: units.gu(4) |
104 | + anchors.horizontalCenter: parent.horizontalCenter |
105 | + height: paintedHeight + units.gu(3) |
106 | + Repeater { |
107 | + model: telepathyHelper.accounts |
108 | + delegate: Label { |
109 | + text: modelData.displayName |
110 | + color: UbuntuColors.orange |
111 | + MouseArea { |
112 | + anchors.fill: parent |
113 | + onClicked: { |
114 | + PopupUtils.close(dialogue) |
115 | + telepathyHelper.setDefaultAccount(TelepathyHelper.Messaging, modelData) |
116 | + } |
117 | + } |
118 | + } |
119 | + } |
120 | + } |
121 | + |
122 | + Label { |
123 | + anchors.left: parent.left |
124 | + anchors.right: parent.right |
125 | + height: paintedHeight + units.gu(6) |
126 | + verticalAlignment: Text.AlignVCenter |
127 | + text: i18n.tr("Select a default SIM for all outgoing messages. You can always alter your choice in <a href=\"system_settings\">System Settings</a>.") |
128 | + wrapMode: Text.WordWrap |
129 | + onLinkActivated: { |
130 | + PopupUtils.close(dialogue) |
131 | + Qt.openUrlExternally("settings:///system/cellular") |
132 | + } |
133 | + } |
134 | + Row { |
135 | + spacing: units.gu(4) |
136 | + anchors.horizontalCenter: parent.horizontalCenter |
137 | + Button { |
138 | + objectName: "noNoSimCardDefaultDialog" |
139 | + text: i18n.tr("No") |
140 | + color: UbuntuColors.orange |
141 | + onClicked: { |
142 | + settings.mainViewDontAskCount = 3 |
143 | + PopupUtils.close(dialogue) |
144 | + Qt.inputMethod.hide() |
145 | + } |
146 | + } |
147 | + Button { |
148 | + objectName: "laterNoSimCardDefaultDialog" |
149 | + text: i18n.tr("Later") |
150 | + color: UbuntuColors.orange |
151 | + onClicked: { |
152 | + PopupUtils.close(dialogue) |
153 | + settings.mainViewDontAskCount++ |
154 | + Qt.inputMethod.hide() |
155 | + } |
156 | + } |
157 | + } |
158 | + } |
159 | + } |
160 | +} |
161 | |
162 | === added file 'src/qml/Dialogs/NoSIMCardSelectedDialog.qml' |
163 | --- src/qml/Dialogs/NoSIMCardSelectedDialog.qml 1970-01-01 00:00:00 +0000 |
164 | +++ src/qml/Dialogs/NoSIMCardSelectedDialog.qml 2014-08-12 15:31:06 +0000 |
165 | @@ -0,0 +1,38 @@ |
166 | +/* |
167 | + * Copyright 2012-2013 Canonical Ltd. |
168 | + * |
169 | + * This file is part of messaging-app. |
170 | + * |
171 | + * messaging-app is free software; you can redistribute it and/or modify |
172 | + * it under the terms of the GNU General Public License as published by |
173 | + * the Free Software Foundation; version 3. |
174 | + * |
175 | + * messaging-app is distributed in the hope that it will be useful, |
176 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
177 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
178 | + * GNU General Public License for more details. |
179 | + * |
180 | + * You should have received a copy of the GNU General Public License |
181 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
182 | + */ |
183 | + |
184 | +import QtQuick 2.0 |
185 | +import Ubuntu.Components 1.1 |
186 | +import Ubuntu.Components.Popups 0.1 |
187 | + |
188 | +Component { |
189 | + Dialog { |
190 | + id: dialogue |
191 | + title: i18n.tr("No SIM card selected") |
192 | + text: i18n.tr("You need to select a SIM card") |
193 | + Button { |
194 | + objectName: "closeNoSimCardSelectedDialog" |
195 | + text: i18n.tr("Close") |
196 | + color: UbuntuColors.orange |
197 | + onClicked: { |
198 | + PopupUtils.close(dialogue) |
199 | + Qt.inputMethod.hide() |
200 | + } |
201 | + } |
202 | + } |
203 | +} |
204 | |
205 | === added file 'src/qml/Dialogs/SetDefaultSIMCardDialog.qml' |
206 | --- src/qml/Dialogs/SetDefaultSIMCardDialog.qml 1970-01-01 00:00:00 +0000 |
207 | +++ src/qml/Dialogs/SetDefaultSIMCardDialog.qml 2014-08-12 15:31:06 +0000 |
208 | @@ -0,0 +1,73 @@ |
209 | +/* |
210 | + * Copyright 2012-2013 Canonical Ltd. |
211 | + * |
212 | + * This file is part of messaging-app. |
213 | + * |
214 | + * messaging-app is free software; you can redistribute it and/or modify |
215 | + * it under the terms of the GNU General Public License as published by |
216 | + * the Free Software Foundation; version 3. |
217 | + * |
218 | + * messaging-app is distributed in the hope that it will be useful, |
219 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
220 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
221 | + * GNU General Public License for more details. |
222 | + * |
223 | + * You should have received a copy of the GNU General Public License |
224 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
225 | + */ |
226 | + |
227 | +import QtQuick 2.0 |
228 | +import Ubuntu.Components 1.1 |
229 | +import Ubuntu.Components.Popups 0.1 |
230 | +import Ubuntu.Telephony 0.1 |
231 | + |
232 | +Component { |
233 | + id: setDefaultSimCardDialog |
234 | + Dialog { |
235 | + id: dialogue |
236 | + text: i18n.tr("Change all Messaging associations to " + messages.account.displayName +"?") |
237 | + Column { |
238 | + anchors.left: parent.left |
239 | + anchors.right: parent.right |
240 | + spacing: units.gu(2) |
241 | + Row { |
242 | + anchors.horizontalCenter: parent.horizontalCenter |
243 | + spacing: units.gu(4) |
244 | + Button { |
245 | + objectName: "setDefaultSimCardDialogNo" |
246 | + text: i18n.tr("No") |
247 | + color: UbuntuColors.orange |
248 | + onClicked: { |
249 | + PopupUtils.close(dialogue) |
250 | + Qt.inputMethod.hide() |
251 | + } |
252 | + } |
253 | + Button { |
254 | + objectName: "setDefaultSimCardDialogYes" |
255 | + text: i18n.tr("Yes") |
256 | + color: UbuntuColors.orange |
257 | + onClicked: { |
258 | + telepathyHelper.setDefaultAccount(TelepathyHelper.Messaging, messages.account) |
259 | + PopupUtils.close(dialogue) |
260 | + Qt.inputMethod.hide() |
261 | + } |
262 | + } |
263 | + } |
264 | + Row { |
265 | + CheckBox { |
266 | + id: dontAskAgainCheckbox |
267 | + checked: false |
268 | + onCheckedChanged: settings.messagesDontAsk = checked |
269 | + } |
270 | + Label { |
271 | + text: i18n.tr("Don't ask again") |
272 | + anchors.verticalCenter: dontAskAgainCheckbox.verticalCenter |
273 | + MouseArea { |
274 | + anchors.fill: parent |
275 | + onClicked: dontAskAgainCheckbox.checked = !dontAskAgainCheckbox.checked |
276 | + } |
277 | + } |
278 | + } |
279 | + } |
280 | + } |
281 | +} |
282 | |
283 | === modified file 'src/qml/KeyboardRectangle.qml' |
284 | --- src/qml/KeyboardRectangle.qml 2014-07-25 16:22:54 +0000 |
285 | +++ src/qml/KeyboardRectangle.qml 2014-08-12 15:31:06 +0000 |
286 | @@ -16,7 +16,7 @@ |
287 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
288 | */ |
289 | |
290 | -import QtQuick 2.0 |
291 | +import QtQuick 2.2 |
292 | |
293 | Item { |
294 | id: keyboardRect |
295 | |
296 | === modified file 'src/qml/MMS/MMSBase.qml' |
297 | --- src/qml/MMS/MMSBase.qml 2014-07-31 19:58:34 +0000 |
298 | +++ src/qml/MMS/MMSBase.qml 2014-08-12 15:31:06 +0000 |
299 | @@ -16,82 +16,13 @@ |
300 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
301 | */ |
302 | import QtQuick 2.2 |
303 | -import Ubuntu.Components 1.1 |
304 | -import Ubuntu.Contacts 0.1 |
305 | |
306 | -ListItemWithActions { |
307 | +Item { |
308 | id: baseDelegate |
309 | |
310 | property var attachment |
311 | - property bool parentSelected: false |
312 | - property bool incoming |
313 | - property bool showInfo: false |
314 | - |
315 | - signal itemRemoved() |
316 | - signal attachmentClicked() |
317 | - |
318 | - function checkClick(bubble, mouse) { |
319 | - var itemX1 = bubble.x |
320 | - var itemX2 = itemX1+bubble.width |
321 | - var itemY1 = bubble.y |
322 | - var itemY2 = itemY1+bubble.height |
323 | - if (mouse.x >= itemX1 && mouse.x <= itemX2 && |
324 | - mouse.y >= itemY1 && mouse.y <= itemY2) { |
325 | - return true |
326 | - } |
327 | - return false |
328 | - } |
329 | - |
330 | - Component.onCompleted: { |
331 | - visibleAttachments++ |
332 | - } |
333 | - Component.onDestruction: { |
334 | - visibleAttachments-- |
335 | - } |
336 | - |
337 | - leftSideAction: Action { |
338 | - iconName: "delete" |
339 | - text: i18n.tr("Delete") |
340 | - onTriggered: baseDelegate.itemRemoved() |
341 | - } |
342 | - |
343 | - internalAnchors { |
344 | - topMargin: 0 |
345 | - bottomMargin: 0 |
346 | - } |
347 | - |
348 | - color: parentSelected ? selectedColor : Theme.palette.normal.background |
349 | - states: [ |
350 | - State { |
351 | - when: incoming |
352 | - name: "incoming" |
353 | - AnchorChanges { |
354 | - target: bubble |
355 | - anchors.left: parent.left |
356 | - anchors.right: undefined |
357 | - } |
358 | - PropertyChanges { |
359 | - target: bubble |
360 | - anchors.leftMargin: units.gu(1) |
361 | - anchors.rightMargin: 0 |
362 | - } |
363 | - }, |
364 | - State { |
365 | - when: !incoming |
366 | - name: "outgoing" |
367 | - AnchorChanges { |
368 | - target: bubble |
369 | - anchors.left: undefined |
370 | - anchors.right: parent.right |
371 | - } |
372 | - PropertyChanges { |
373 | - target: bubble |
374 | - anchors.leftMargin: 0 |
375 | - anchors.rightMargin: units.gu(1) |
376 | - } |
377 | - } |
378 | - ] |
379 | - |
380 | - onSwippingChanged: messageList.updateSwippedItem(baseDelegate) |
381 | - onSwipeStateChanged: messageList.updateSwippedItem(baseDelegate) |
382 | + property string previewer |
383 | + property bool incoming: false |
384 | + property bool lastItem: false |
385 | + property string timestamp |
386 | } |
387 | |
388 | === modified file 'src/qml/MMS/MMSContact.qml' |
389 | --- src/qml/MMS/MMSContact.qml 2014-07-31 19:01:23 +0000 |
390 | +++ src/qml/MMS/MMSContact.qml 2014-08-12 15:31:06 +0000 |
391 | @@ -16,93 +16,73 @@ |
392 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
393 | */ |
394 | |
395 | -import QtQuick 2.0 |
396 | -import Ubuntu.Components 0.1 |
397 | +import QtQuick 2.2 |
398 | +import Ubuntu.Components 1.1 |
399 | import Ubuntu.Contacts 0.1 |
400 | -import ".." |
401 | +import Ubuntu.History 0.1 |
402 | |
403 | MMSBase { |
404 | id: vcardDelegate |
405 | - property string previewer: "MMS/PreviewerContact.qml" |
406 | - onItemClicked: { |
407 | - if (checkClick(bubble, mouse)) { |
408 | - attachmentClicked() |
409 | - } |
410 | - } |
411 | - states: [ |
412 | - State { |
413 | - name: "incoming" |
414 | - AnchorChanges { |
415 | - target: bubble |
416 | - anchors.left: parent.left |
417 | - anchors.right: undefined |
418 | - } |
419 | - PropertyChanges { |
420 | - target: bubble |
421 | - anchors.leftMargin: units.gu(1) |
422 | - anchors.rightMargin: units.gu(1) |
423 | - } |
424 | - AnchorChanges { |
425 | - target: contactName |
426 | - anchors.left: bubble.right |
427 | - anchors.right: undefined |
428 | - } |
429 | - PropertyChanges { |
430 | - target: contactName |
431 | - anchors.leftMargin: units.gu(2) |
432 | - anchors.rightMargin: units.gu(2) |
433 | - } |
434 | - }, |
435 | - State { |
436 | - name: "outgoing" |
437 | - AnchorChanges { |
438 | - target: bubble |
439 | - anchors.left: undefined |
440 | - anchors.right: parent.right |
441 | - } |
442 | - PropertyChanges { |
443 | - target: bubble |
444 | - anchors.leftMargin: units.gu(1) |
445 | - anchors.rightMargin: units.gu(1) |
446 | - } |
447 | - AnchorChanges { |
448 | - target: contactName |
449 | - anchors.left: undefined |
450 | - anchors.right: bubble.left |
451 | - } |
452 | - PropertyChanges { |
453 | - target: contactName |
454 | - anchors.leftMargin: units.gu(2) |
455 | - anchors.rightMargin: units.gu(2) |
456 | - } |
457 | - } |
458 | - ] |
459 | - height: bubble.height + units.gu(2) |
460 | - Item { |
461 | + |
462 | + readonly property bool error: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) |
463 | + readonly property bool sending: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown || |
464 | + textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming |
465 | + |
466 | + previewer: "MMS/PreviewerContact.qml" |
467 | + height: units.gu(8) |
468 | + width: units.gu(27) |
469 | + |
470 | + Rectangle { |
471 | id: bubble |
472 | - anchors.top: parent.top |
473 | - width: avatar.width |
474 | - height: avatar.height |
475 | + |
476 | + anchors.fill: parent |
477 | + color: { |
478 | + if (error) { |
479 | + return "#fc4949" |
480 | + } else if (sending) { |
481 | + return "#b2b2b2" |
482 | + } else if (incoming) { |
483 | + return "#ffffff" |
484 | + } else { |
485 | + return "#3fb24f" |
486 | + } |
487 | + } |
488 | + radius: height * 0.1 |
489 | + |
490 | ContactAvatar { |
491 | id: avatar |
492 | |
493 | + anchors { |
494 | + top: parent.top |
495 | + topMargin: units.gu(1) |
496 | + bottom: parent.bottom |
497 | + bottomMargin: units.gu(1) |
498 | + left: parent.left |
499 | + leftMargin: units.gu(1) |
500 | + } |
501 | fallbackAvatarUrl: "image://theme/contact" |
502 | fallbackDisplayName: contactName.name |
503 | - anchors.centerIn: parent |
504 | - height: units.gu(6) |
505 | - width: units.gu(6) |
506 | - } |
507 | - } |
508 | - Label { |
509 | - id: contactName |
510 | - property string name: application.contactNameFromVCard(attachment.filePath) |
511 | - anchors.bottom: bubble.bottom |
512 | - anchors.left: incoming ? bubble.right : undefined |
513 | - anchors.right: !incoming ? bubble.left : undefined |
514 | - anchors.rightMargin: !incoming ? units.gu(1) : undefined |
515 | - anchors.leftMargin: incoming ? units.gu(1) : undefined |
516 | - text: name !== "" ? name : i18n.tr("Unknown contact") |
517 | - height: paintedHeight |
518 | - width: paintedWidth |
519 | + width: height |
520 | + } |
521 | + |
522 | + Label { |
523 | + id: contactName |
524 | + |
525 | + property string name: application.contactNameFromVCard(attachment.filePath) |
526 | + |
527 | + anchors { |
528 | + left: avatar.right |
529 | + leftMargin: units.gu(1) |
530 | + top: avatar.top |
531 | + bottom: avatar.bottom |
532 | + right: parent.right |
533 | + rightMargin: units.gu(1) |
534 | + } |
535 | + |
536 | + verticalAlignment: Text.AlignVCenter |
537 | + text: name !== "" ? name : i18n.tr("Unknown contact") |
538 | + elide: Text.ElideRight |
539 | + color: vcardDelegate.incoming ? UbuntuColors.darkGrey : "#ffffff" |
540 | + } |
541 | } |
542 | } |
543 | |
544 | === modified file 'src/qml/MMS/MMSDefault.qml' |
545 | --- src/qml/MMS/MMSDefault.qml 2014-07-31 19:01:23 +0000 |
546 | +++ src/qml/MMS/MMSDefault.qml 2014-08-12 15:31:06 +0000 |
547 | @@ -16,54 +16,16 @@ |
548 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
549 | */ |
550 | |
551 | -import QtQuick 2.0 |
552 | -import Ubuntu.Components 0.1 |
553 | +import QtQuick 2.2 |
554 | +import Ubuntu.Components 1.1 |
555 | import ".." |
556 | |
557 | MMSBase { |
558 | id: defaultDelegate |
559 | - property var attachment |
560 | - property bool incoming |
561 | - property string previewer: "" |
562 | - property string textColor: incoming ? "#333333" : "#ffffff" |
563 | + |
564 | anchors.left: parent.left |
565 | anchors.right: parent.right |
566 | - onItemClicked: { |
567 | - if (checkClick(bubble, mouse)) { |
568 | - attachmentClicked() |
569 | - } |
570 | - } |
571 | - state: incoming ? "incoming" : "outgoing" |
572 | - states: [ |
573 | - State { |
574 | - name: "incoming" |
575 | - AnchorChanges { |
576 | - target: bubble |
577 | - anchors.left: parent.left |
578 | - anchors.right: undefined |
579 | - } |
580 | - PropertyChanges { |
581 | - target: bubble |
582 | - anchors.leftMargin: units.gu(1) |
583 | - anchors.rightMargin: units.gu(1) |
584 | - } |
585 | - }, |
586 | - State { |
587 | - name: "outgoing" |
588 | - AnchorChanges { |
589 | - target: bubble |
590 | - anchors.left: undefined |
591 | - anchors.right: parent.right |
592 | - } |
593 | - PropertyChanges { |
594 | - target: bubble |
595 | - anchors.leftMargin: units.gu(1) |
596 | - anchors.rightMargin: units.gu(1) |
597 | - } |
598 | - } |
599 | - ] |
600 | height: bubble.height + units.gu(1) |
601 | - clip: true |
602 | Item { |
603 | id: bubble |
604 | anchors.top: parent.top |
605 | |
606 | === modified file 'src/qml/MMS/MMSImage.qml' |
607 | --- src/qml/MMS/MMSImage.qml 2014-07-31 19:01:23 +0000 |
608 | +++ src/qml/MMS/MMSImage.qml 2014-08-12 15:31:06 +0000 |
609 | @@ -16,27 +16,19 @@ |
610 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
611 | */ |
612 | |
613 | -import QtQuick 2.0 |
614 | +import QtQuick 2.2 |
615 | import Ubuntu.Components 1.1 |
616 | -import Ubuntu.Contacts 0.1 |
617 | -import ".." |
618 | |
619 | MMSBase { |
620 | id: imageDelegate |
621 | - property string previewer: "MMS/PreviewerImage.qml" |
622 | - onItemClicked: { |
623 | - if (checkClick(bubble, mouse)) { |
624 | - attachmentClicked() |
625 | - } |
626 | - } |
627 | |
628 | + previewer: "MMS/PreviewerImage.qml" |
629 | height: imageAttachment.height |
630 | + width: imageAttachment.width |
631 | + |
632 | UbuntuShape { |
633 | id: bubble |
634 | - anchors { |
635 | - top: parent.top |
636 | - bottom: parent.bottom |
637 | - } |
638 | + anchors.top: parent.top |
639 | width: image.width |
640 | height: image.height |
641 | |
642 | @@ -49,16 +41,42 @@ |
643 | smooth: true |
644 | source: attachment.filePath |
645 | visible: false |
646 | - } |
647 | - } |
648 | - |
649 | - Loader { |
650 | - active: (index == visibleAttachments-1) && !incoming && mmsText == "" && (inProgress || failed) |
651 | - visible: active |
652 | - height: active ? item.height : 0 |
653 | - sourceComponent: statusIcon |
654 | - anchors.right: bubble.left |
655 | - anchors.rightMargin: units.gu(1) |
656 | - anchors.verticalCenter: bubble.verticalCenter |
657 | + asynchronous: true |
658 | + |
659 | + onStatusChanged: { |
660 | + if (status === Image.Error) { |
661 | + source = "image://theme/image-missing" |
662 | + width = 128 |
663 | + height = 128 |
664 | + } |
665 | + } |
666 | + } |
667 | + |
668 | + Rectangle { |
669 | + visible: imageDelegate.lastItem |
670 | + gradient: Gradient { |
671 | + GradientStop { position: 0.0; color: "transparent" } |
672 | + GradientStop { position: 1.0; color: "gray" } |
673 | + } |
674 | + |
675 | + anchors { |
676 | + bottom: parent.bottom |
677 | + left: parent.left |
678 | + right: parent.right |
679 | + } |
680 | + height: units.gu(2) |
681 | + radius: bubble.height * 0.1 |
682 | + Label { |
683 | + anchors{ |
684 | + left: parent.left |
685 | + bottom: parent.bottom |
686 | + leftMargin: incoming ? units.gu(2) : units.gu(1) |
687 | + bottomMargin: units.gu(0.5) |
688 | + } |
689 | + fontSize: "xx-small" |
690 | + text: Qt.formatDateTime(timestamp, "hh:mm AP") |
691 | + color: "white" |
692 | + } |
693 | + } |
694 | } |
695 | } |
696 | |
697 | === modified file 'src/qml/MMS/MMSVideo.qml' |
698 | --- src/qml/MMS/MMSVideo.qml 2014-07-31 19:01:23 +0000 |
699 | +++ src/qml/MMS/MMSVideo.qml 2014-08-12 15:31:06 +0000 |
700 | @@ -16,54 +16,19 @@ |
701 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
702 | */ |
703 | |
704 | -import QtQuick 2.0 |
705 | -import Ubuntu.Components 0.1 |
706 | +import QtQuick 2.2 |
707 | +import Ubuntu.Components 1.1 |
708 | import QtMultimedia 5.0 |
709 | import ".." |
710 | |
711 | MMSBase { |
712 | id: videoDelegate |
713 | - property var attachment |
714 | - property bool incoming |
715 | - property string previewer: "MMS/PreviewerVideo.qml" |
716 | + |
717 | + previewer: "MMS/PreviewerVideo.qml" |
718 | anchors.left: parent.left |
719 | anchors.right: parent.right |
720 | - onItemClicked: { |
721 | - if (checkClick(bubble, mouse)) { |
722 | - attachmentClicked() |
723 | - } |
724 | - } |
725 | - state: incoming ? "incoming" : "outgoing" |
726 | - states: [ |
727 | - State { |
728 | - name: "incoming" |
729 | - AnchorChanges { |
730 | - target: bubble |
731 | - anchors.left: parent.left |
732 | - anchors.right: undefined |
733 | - } |
734 | - PropertyChanges { |
735 | - target: bubble |
736 | - anchors.leftMargin: units.gu(1) |
737 | - anchors.rightMargin: units.gu(1) |
738 | - } |
739 | - }, |
740 | - State { |
741 | - name: "outgoing" |
742 | - AnchorChanges { |
743 | - target: bubble |
744 | - anchors.left: undefined |
745 | - anchors.right: parent.right |
746 | - } |
747 | - PropertyChanges { |
748 | - target: bubble |
749 | - anchors.leftMargin: units.gu(1) |
750 | - anchors.rightMargin: units.gu(1) |
751 | - } |
752 | - } |
753 | - ] |
754 | height: bubble.height + units.gu(1) |
755 | - clip: true |
756 | + |
757 | Item { |
758 | id: bubble |
759 | anchors.top: parent.top |
760 | |
761 | === modified file 'src/qml/MMS/Previewer.qml' |
762 | --- src/qml/MMS/Previewer.qml 2014-06-13 19:39:49 +0000 |
763 | +++ src/qml/MMS/Previewer.qml 2014-08-12 15:31:06 +0000 |
764 | @@ -16,8 +16,8 @@ |
765 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
766 | */ |
767 | |
768 | -import QtQuick 2.0 |
769 | -import Ubuntu.Components 0.1 |
770 | +import QtQuick 2.2 |
771 | +import Ubuntu.Components 1.1 |
772 | import Ubuntu.Content 0.1 |
773 | import ".." |
774 | |
775 | |
776 | === modified file 'src/qml/MMS/PreviewerContact.qml' |
777 | --- src/qml/MMS/PreviewerContact.qml 2014-07-30 18:23:16 +0000 |
778 | +++ src/qml/MMS/PreviewerContact.qml 2014-08-12 15:31:06 +0000 |
779 | @@ -16,12 +16,14 @@ |
780 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
781 | */ |
782 | |
783 | -import QtQuick 2.0 |
784 | -import Ubuntu.Components 0.1 |
785 | +import QtQuick 2.2 |
786 | +import Ubuntu.Components 1.1 |
787 | import Ubuntu.Content 0.1 |
788 | import ".." |
789 | |
790 | Previewer { |
791 | - title: application.contactNameFromVCard(attachment.filePath) |
792 | + property string contactName: application.contactNameFromVCard(attachment.filePath) |
793 | + |
794 | + title: contactName !== "" ? contactName : i18n.tr("Unknown contact") |
795 | clip: true |
796 | } |
797 | |
798 | === modified file 'src/qml/MMS/PreviewerImage.qml' |
799 | --- src/qml/MMS/PreviewerImage.qml 2014-06-13 19:39:49 +0000 |
800 | +++ src/qml/MMS/PreviewerImage.qml 2014-08-12 15:31:06 +0000 |
801 | @@ -16,8 +16,8 @@ |
802 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
803 | */ |
804 | |
805 | -import QtQuick 2.0 |
806 | -import Ubuntu.Components 0.1 |
807 | +import QtQuick 2.2 |
808 | +import Ubuntu.Components 1.1 |
809 | import Ubuntu.Content 0.1 |
810 | import ".." |
811 | |
812 | |
813 | === modified file 'src/qml/MMS/PreviewerVideo.qml' |
814 | --- src/qml/MMS/PreviewerVideo.qml 2014-05-30 21:16:51 +0000 |
815 | +++ src/qml/MMS/PreviewerVideo.qml 2014-08-12 15:31:06 +0000 |
816 | @@ -16,8 +16,8 @@ |
817 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
818 | */ |
819 | |
820 | -import QtQuick 2.0 |
821 | -import Ubuntu.Components 0.1 |
822 | +import QtQuick 2.2 |
823 | +import Ubuntu.Components 1.1 |
824 | import QtMultimedia 5.0 |
825 | import ".." |
826 | |
827 | |
828 | === added file 'src/qml/MMSDelegate.qml' |
829 | --- src/qml/MMSDelegate.qml 1970-01-01 00:00:00 +0000 |
830 | +++ src/qml/MMSDelegate.qml 2014-08-12 15:31:06 +0000 |
831 | @@ -0,0 +1,198 @@ |
832 | +/* |
833 | + * Copyright 2012, 2013, 2014 Canonical Ltd. |
834 | + * |
835 | + * This file is part of messaging-app. |
836 | + * |
837 | + * messaging-app is free software; you can redistribute it and/or modify |
838 | + * it under the terms of the GNU General Public License as published by |
839 | + * the Free Software Foundation; version 3. |
840 | + * |
841 | + * messaging-app is distributed in the hope that it will be useful, |
842 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
843 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
844 | + * GNU General Public License for more details. |
845 | + * |
846 | + * You should have received a copy of the GNU General Public License |
847 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
848 | + */ |
849 | + |
850 | +import QtQuick 2.2 |
851 | +import Ubuntu.Components 1.1 |
852 | + |
853 | +MessageDelegate { |
854 | + id: root |
855 | + |
856 | + property var dataAttachments: [] |
857 | + property var textAttachements: [] |
858 | + |
859 | + function clicked(mouse) |
860 | + { |
861 | + var childPoint = root.mapToItem(attachmentsView, mouse.x, mouse.y) |
862 | + var attachment = attachmentsView.childAt(childPoint.x, childPoint.y) |
863 | + if (attachment && attachment.item && attachment.item.previewer) { |
864 | + var properties = {} |
865 | + properties["attachment"] = attachment.item.attachment |
866 | + mainStack.push(Qt.resolvedUrl(attachment.item.previewer), properties) |
867 | + } |
868 | + } |
869 | + |
870 | + function deleteMessage() |
871 | + { |
872 | + eventModel.removeEvent(accountId, threadId, eventId, type) |
873 | + } |
874 | + |
875 | + function resendMessage() |
876 | + { |
877 | + var newAttachments = [] |
878 | + for (var i = 0; i < attachments.length; i++) { |
879 | + var attachment = [] |
880 | + var item = textMessageAttachments[i] |
881 | + // we dont include smil files. they will be auto generated |
882 | + if (item.contentType.toLowerCase() === "application/smil") { |
883 | + continue |
884 | + } |
885 | + attachment.push(item.attachmentId) |
886 | + attachment.push(item.contentType) |
887 | + attachment.push(item.filePath) |
888 | + newAttachments.push(attachment) |
889 | + } |
890 | + eventModel.removeEvent(accountId, threadId, eventId, type) |
891 | + chatManager.sendMMS(participants, textMessage, newAttachments, messages.accountId) |
892 | + } |
893 | + |
894 | + function copyMessage() |
895 | + { |
896 | + if (bubble.visible) { |
897 | + Clipboard.push(bubble.messageText) |
898 | + } |
899 | + } |
900 | + |
901 | + onAttachmentsChanged: { |
902 | + dataAttachments = [] |
903 | + textAttachements = [] |
904 | + for (var i=0; i < attachments.length; i++) { |
905 | + var attachment = attachments[i] |
906 | + if (startsWith(attachment.contentType, "text/plain") ) { |
907 | + textAttachements.push(attachment) |
908 | + } else if (startsWith(attachment.contentType, "image/")) { |
909 | + dataAttachments.push({"type": "image", |
910 | + "data": attachment, |
911 | + "delegateSource": "MMS/MMSImage.qml", |
912 | + }) |
913 | + } else if (startsWith(attachment.contentType, "video/")) { |
914 | + // TODO: implement proper video attachment support |
915 | + // dataAttachments.push({type: "video", |
916 | + // data: attachment, |
917 | + // delegateSource: "MMS/MMSVideo.qml", |
918 | + // }) |
919 | + } else if (startsWith(attachment.contentType, "application/smil") || |
920 | + startsWith(attachment.contentType, "application/x-smil")) { |
921 | + // TODO: implement support for this kind of attachment |
922 | + // dataAttachments.push({type: "application", |
923 | + // data: attachment, |
924 | + // delegateSource: "", |
925 | + // }) |
926 | + } else if (startsWith(attachment.contentType, "text/vcard") || |
927 | + startsWith(attachment.contentType, "text/x-vcard")) { |
928 | + dataAttachments.push({"type": "vcard", |
929 | + "data": attachment, |
930 | + "delegateSource": "MMS/MMSContact.qml" |
931 | + }) |
932 | + } else { |
933 | + console.log("No MMS render for " + attachment.contentType) |
934 | + } |
935 | + } |
936 | + } |
937 | + height: attachmentsView.height |
938 | + _lastItem: bubble.visible ? bubble : attachmentsRepeater.itemAt(attachmentsRepeater - 1) |
939 | + Column { |
940 | + id: attachmentsView |
941 | + |
942 | + anchors { |
943 | + top: parent.top |
944 | + left: parent.left |
945 | + right: parent.right |
946 | + } |
947 | + height: childrenRect.height |
948 | + |
949 | + Repeater { |
950 | + id: attachmentsRepeater |
951 | + model: dataAttachments |
952 | + |
953 | + Loader { |
954 | + id: attachmentLoader |
955 | + asynchronous: true |
956 | + states: [ |
957 | + State { |
958 | + when: root.incoming |
959 | + name: "incoming" |
960 | + AnchorChanges { |
961 | + target: attachmentLoader |
962 | + anchors.left: parent.left |
963 | + } |
964 | + PropertyChanges { |
965 | + target: attachmentLoader |
966 | + anchors.leftMargin: units.gu(1) |
967 | + anchors.rightMargin: 0 |
968 | + } |
969 | + }, |
970 | + State { |
971 | + when: !root.incoming |
972 | + name: "outgoing" |
973 | + AnchorChanges { |
974 | + target: attachmentLoader |
975 | + anchors.right: parent.right |
976 | + } |
977 | + PropertyChanges { |
978 | + target: attachmentLoader |
979 | + anchors.leftMargin: 0 |
980 | + anchors.rightMargin: units.gu(1) |
981 | + } |
982 | + } |
983 | + ] |
984 | + |
985 | + Component.onCompleted: { |
986 | + var initialProperties = { |
987 | + "incoming": root.incoming, |
988 | + "attachment": modelData.data, |
989 | + "timestamp": timestamp, |
990 | + "lastItem": (index === (attachmentsRepeater.count - 1)) && (textAttachements.length === 0) |
991 | + } |
992 | + setSource(modelData.delegateSource, initialProperties) |
993 | + } |
994 | + } |
995 | + } |
996 | + |
997 | + // TODO: is possible to have more than one text ??? |
998 | + MessageBubble { |
999 | + id: bubble |
1000 | + |
1001 | + property string textData: application.readTextFile(root.textAttachements[0].filePath) |
1002 | + |
1003 | + states: [ |
1004 | + State { |
1005 | + when: root.incoming |
1006 | + name: "incoming" |
1007 | + AnchorChanges { |
1008 | + target: bubble |
1009 | + anchors.left: parent.left |
1010 | + } |
1011 | + }, |
1012 | + State { |
1013 | + name: "outgoing" |
1014 | + when: !root.incoming |
1015 | + AnchorChanges { |
1016 | + target: bubble |
1017 | + anchors.right: parent.right |
1018 | + } |
1019 | + } |
1020 | + ] |
1021 | + visible: (root.textAttachements.length > 0) |
1022 | + messageText: textData.length > 0 ? textData : i18n.tr("Missing message data") |
1023 | + messageTimeStamp: root.timestamp |
1024 | + messageStatus: textMessageStatus |
1025 | + messageIncoming: root.incoming |
1026 | + accountName: root.accountLabel |
1027 | + } |
1028 | + } |
1029 | +} |
1030 | |
1031 | === modified file 'src/qml/MainPage.qml' |
1032 | --- src/qml/MainPage.qml 2014-07-31 19:16:57 +0000 |
1033 | +++ src/qml/MainPage.qml 2014-08-12 15:31:06 +0000 |
1034 | @@ -16,7 +16,7 @@ |
1035 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1036 | */ |
1037 | |
1038 | -import QtQuick 2.0 |
1039 | +import QtQuick 2.2 |
1040 | import Ubuntu.Components 1.1 |
1041 | import Ubuntu.Components.ListItems 0.1 as ListItem |
1042 | import Ubuntu.History 0.1 |
1043 | @@ -40,7 +40,7 @@ |
1044 | bottomEdgePageComponent: Messages { |
1045 | active: false |
1046 | } |
1047 | - bottomEdgeTitle: i18n.tr("New Chat") |
1048 | + bottomEdgeTitle: i18n.tr("Create new") |
1049 | |
1050 | TextField { |
1051 | id: searchField |
1052 | @@ -114,6 +114,38 @@ |
1053 | } |
1054 | ] |
1055 | |
1056 | + Item { |
1057 | + id: emptyStateScreen |
1058 | + anchors.left: parent.left |
1059 | + anchors.leftMargin: units.gu(6) |
1060 | + anchors.right: parent.right |
1061 | + anchors.rightMargin: units.gu(6) |
1062 | + height: childrenRect.height |
1063 | + anchors.verticalCenter: parent.verticalCenter |
1064 | + visible: threadCount == 0 && !threadModel.canFetchMore |
1065 | + Icon { |
1066 | + id: emptyStateIcon |
1067 | + anchors.top: emptyStateScreen.top |
1068 | + anchors.horizontalCenter: parent.horizontalCenter |
1069 | + height: units.gu(5) |
1070 | + width: height |
1071 | + opacity: 0.3 |
1072 | + name: "message" |
1073 | + } |
1074 | + Label { |
1075 | + id: emptyStateLabel |
1076 | + anchors.top: emptyStateIcon.bottom |
1077 | + anchors.topMargin: units.gu(2) |
1078 | + anchors.left: parent.left |
1079 | + anchors.right: parent.right |
1080 | + text: i18n.tr("Compose a new message by swiping up from the bottom of the screen.") |
1081 | + color: "#5d5d5d" |
1082 | + fontSize: "x-large" |
1083 | + wrapMode: Text.WordWrap |
1084 | + horizontalAlignment: Text.AlignHCenter |
1085 | + } |
1086 | + } |
1087 | + |
1088 | HistoryThreadGroupingProxyModel { |
1089 | id: sortProxy |
1090 | sortRole: HistoryThreadModel.LastEventTimestampRole |
1091 | |
1092 | === modified file 'src/qml/MessageBubble.qml' |
1093 | --- src/qml/MessageBubble.qml 2014-08-01 02:36:29 +0000 |
1094 | +++ src/qml/MessageBubble.qml 2014-08-12 15:31:06 +0000 |
1095 | @@ -27,15 +27,16 @@ |
1096 | id: root |
1097 | |
1098 | property int messageStatus: -1 |
1099 | - property bool incoming: false |
1100 | + property bool messageIncoming: false |
1101 | property alias sender: senderName.text |
1102 | property string messageText |
1103 | property var messageTimeStamp |
1104 | - property int maxDelegateWidth: units.gu(30) |
1105 | + property int maxDelegateWidth: units.gu(27) |
1106 | + property string accountName |
1107 | |
1108 | readonly property bool error: (messageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) |
1109 | readonly property bool sending: (messageStatus === HistoryThreadModel.MessageStatusUnknown || |
1110 | - messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !incoming |
1111 | + messageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) && !messageIncoming |
1112 | |
1113 | function selectBubble() { |
1114 | var fileName = "assets/conversation_"; |
1115 | @@ -43,7 +44,7 @@ |
1116 | fileName += "error.sci" |
1117 | } else if (sending) { |
1118 | fileName += "pending.sci" |
1119 | - } else if (incoming) { |
1120 | + } else if (messageIncoming) { |
1121 | fileName += "incoming.sci"; |
1122 | } else { |
1123 | fileName += "outgoing.sci"; |
1124 | @@ -63,11 +64,11 @@ |
1125 | return text.replace(phoneExp, '<a href="tel:///$1">$1</a>'); |
1126 | } |
1127 | |
1128 | - onIncomingChanged: source = selectBubble() |
1129 | + onMessageIncomingChanged: source = selectBubble() |
1130 | source: selectBubble() |
1131 | - height: childrenRect.height + units.gu(2) |
1132 | + height: senderName.height + textLabel.height + textTimestamp.height + units.gu(3) |
1133 | width: Math.min(units.gu(27), |
1134 | - Math.max(textLabel.text.length, textTimestamp.text.length) * units.gu(1)) |
1135 | + Math.max(textLabel.contentWidth, textTimestamp.contentWidth)) |
1136 | + border.left + border.right |
1137 | Label { |
1138 | id: senderName |
1139 | @@ -76,7 +77,7 @@ |
1140 | top: parent.top |
1141 | topMargin: units.gu(1) |
1142 | left: parent.left |
1143 | - leftMargin: incoming ? units.gu(2) : units.gu(1) |
1144 | + leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1) |
1145 | } |
1146 | height: text === "" ? 0 : paintedHeight |
1147 | fontSize: "large" |
1148 | @@ -91,17 +92,15 @@ |
1149 | top: sender == "" ? parent.top : senderName.bottom |
1150 | topMargin: units.gu(1) |
1151 | left: parent.left |
1152 | - leftMargin: incoming ? units.gu(2) : units.gu(1) |
1153 | - right: parent.right |
1154 | - rightMargin: incoming ? units.gu(1) : units.gu(1) |
1155 | + leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1) |
1156 | } |
1157 | width: maxDelegateWidth |
1158 | fontSize: "medium" |
1159 | - height: text === "" ? 0 : paintedHeight |
1160 | + height: contentHeight |
1161 | onLinkActivated: Qt.openUrlExternally(link) |
1162 | text: root.parseText(messageText) |
1163 | wrapMode: Text.Wrap |
1164 | - color: root.incoming ? UbuntuColors.darkGrey : "white" |
1165 | + color: root.messageIncoming ? UbuntuColors.darkGrey : "white" |
1166 | } |
1167 | |
1168 | Label { |
1169 | @@ -110,16 +109,25 @@ |
1170 | |
1171 | anchors{ |
1172 | top: textLabel.bottom |
1173 | - topMargin: units.gu(0.5) |
1174 | + topMargin: units.gu(1) |
1175 | left: parent.left |
1176 | - leftMargin: incoming ? units.gu(2) : units.gu(1) |
1177 | + leftMargin: root.messageIncoming ? units.gu(2) : units.gu(1) |
1178 | } |
1179 | |
1180 | visible: !root.sending |
1181 | - height: visible ? paintedHeight : 0 |
1182 | + height: units.gu(2) |
1183 | + width: visible ? maxDelegateWidth : 0 |
1184 | fontSize: "xx-small" |
1185 | - color: root.incoming ? UbuntuColors.lightGrey : "white" |
1186 | - opacity: root.incoming ? 1.0 : 0.8 |
1187 | - text: Qt.formatDateTime(messageTimeStamp, "hh:mm AP") |
1188 | + color: root.messageIncoming ? UbuntuColors.lightGrey : "white" |
1189 | + opacity: root.messageIncoming ? 1.0 : 0.8 |
1190 | + elide: Text.ElideRight |
1191 | + text: { |
1192 | + var str = Qt.formatDateTime(messageTimeStamp, "hh:mm AP") |
1193 | + if (root.accountName.length === 0) { |
1194 | + return str |
1195 | + } |
1196 | + str += " @ %1".arg(root.accountName) |
1197 | + return str |
1198 | + } |
1199 | } |
1200 | } |
1201 | |
1202 | === added file 'src/qml/MessageDateSection.qml' |
1203 | --- src/qml/MessageDateSection.qml 1970-01-01 00:00:00 +0000 |
1204 | +++ src/qml/MessageDateSection.qml 2014-08-12 15:31:06 +0000 |
1205 | @@ -0,0 +1,38 @@ |
1206 | +/* |
1207 | + * Copyright 2012, 2013, 2014 Canonical Ltd. |
1208 | + * |
1209 | + * This file is part of messaging-app. |
1210 | + * |
1211 | + * messaging-app is free software; you can redistribute it and/or modify |
1212 | + * it under the terms of the GNU General Public License as published by |
1213 | + * the Free Software Foundation; version 3. |
1214 | + * |
1215 | + * messaging-app is distributed in the hope that it will be useful, |
1216 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1217 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1218 | + * GNU General Public License for more details. |
1219 | + * |
1220 | + * You should have received a copy of the GNU General Public License |
1221 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1222 | + */ |
1223 | + |
1224 | +import QtQuick 2.2 |
1225 | +import Ubuntu.Components 1.1 |
1226 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
1227 | + |
1228 | +Item { |
1229 | + property alias text: label.text |
1230 | + |
1231 | + height: units.gu(3) |
1232 | + Label { |
1233 | + id: label |
1234 | + |
1235 | + anchors.fill: parent |
1236 | + elide: Text.ElideRight |
1237 | + verticalAlignment: Text.AlignVCenter |
1238 | + fontSize: "small" |
1239 | + } |
1240 | + ListItem.ThinDivider { |
1241 | + anchors.bottom: parent.bottom |
1242 | + } |
1243 | +} |
1244 | |
1245 | === modified file 'src/qml/MessageDelegate.qml' |
1246 | --- src/qml/MessageDelegate.qml 2014-07-31 19:58:54 +0000 |
1247 | +++ src/qml/MessageDelegate.qml 2014-08-12 15:31:06 +0000 |
1248 | @@ -16,242 +16,46 @@ |
1249 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1250 | */ |
1251 | |
1252 | -import QtQuick 2.0 |
1253 | -import Ubuntu.Components 1.1 |
1254 | -import Ubuntu.Components.Popups 0.1 |
1255 | -import Ubuntu.History 0.1 |
1256 | -import Ubuntu.Telephony 0.1 |
1257 | -import Ubuntu.Content 0.1 |
1258 | -import Ubuntu.Contacts 0.1 |
1259 | - |
1260 | -import "dateUtils.js" as DateUtils |
1261 | +import QtQuick 2.2 |
1262 | |
1263 | Item { |
1264 | id: messageDelegate |
1265 | - |
1266 | - property alias incoming: bubble.incoming |
1267 | - property string textColor: incoming ? "#333333" : "white" |
1268 | - property bool unread: false |
1269 | - property variant activeAttachment |
1270 | - property string mmsText: "" |
1271 | - property string mmsTextId: "" |
1272 | - property string accountLabel: "" |
1273 | - property bool selectionMode: false |
1274 | - property bool selected: false |
1275 | - property bool inProgress: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown || |
1276 | - textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) |
1277 | - property bool failed: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) |
1278 | - property int visibleAttachments: 0 |
1279 | - |
1280 | - signal resend() |
1281 | - signal itemPressAndHold(QtObject obj) |
1282 | - signal itemClicked(QtObject obj) |
1283 | - |
1284 | - anchors { |
1285 | - left: parent ? parent.left : undefined |
1286 | - right: parent ? parent.right: undefined |
1287 | - } |
1288 | - height: attachments.height + bubbleItem.height |
1289 | - |
1290 | - Component { |
1291 | - id: statusIcon |
1292 | - Item { |
1293 | - height: units.gu(4) |
1294 | - width: units.gu(4) |
1295 | - visible: !incoming && !messageDelegate.selectionMode |
1296 | - ActivityIndicator { |
1297 | - id: indicator |
1298 | - |
1299 | - anchors.centerIn: parent |
1300 | - height: units.gu(2) |
1301 | - width: units.gu(2) |
1302 | - visible: running && !selectionMode |
1303 | - // if temporarily failed or unknown status, then show the spinner |
1304 | - running: inProgress |
1305 | - } |
1306 | - |
1307 | - Item { |
1308 | - id: retrybutton |
1309 | - |
1310 | - anchors.fill: parent |
1311 | - Icon { |
1312 | - id: icon |
1313 | - |
1314 | - name: "reload" |
1315 | - color: "red" |
1316 | - height: units.gu(2) |
1317 | - width: units.gu(2) |
1318 | - anchors { |
1319 | - centerIn: parent |
1320 | - verticalCenterOffset: units.gu(-1) |
1321 | - } |
1322 | - } |
1323 | - |
1324 | - Label { |
1325 | - text: i18n.tr("Failed!") |
1326 | - fontSize: "small" |
1327 | - color: "red" |
1328 | - anchors { |
1329 | - horizontalCenter: retrybutton.horizontalCenter |
1330 | - top: icon.bottom |
1331 | - } |
1332 | - } |
1333 | - visible: failed |
1334 | - MouseArea { |
1335 | - id: retrybuttonMouseArea |
1336 | - |
1337 | - anchors.fill: parent |
1338 | - onClicked: messageDelegate.resend() |
1339 | - } |
1340 | - } |
1341 | - } |
1342 | - } |
1343 | - |
1344 | - Column { |
1345 | - id: attachments |
1346 | - anchors { |
1347 | - top: parent.top |
1348 | - left: parent.left |
1349 | - right: parent.right |
1350 | - } |
1351 | - height: childrenRect.height |
1352 | - Repeater { |
1353 | - id: attachmentsRepeater |
1354 | - |
1355 | - model: textMessageAttachments |
1356 | - Loader { |
1357 | - anchors { |
1358 | - left: parent ? parent.left : undefined |
1359 | - right: parent ? parent.right : undefined |
1360 | - } |
1361 | - height: item ? item.height : 0 |
1362 | - source: { |
1363 | - if (startsWith(modelData.contentType, "image/")) { |
1364 | - return "MMS/MMSImage.qml" |
1365 | - } else if (startsWith(modelData.contentType, "video/")) { |
1366 | - return "MMS/MMSVideo.qml" |
1367 | - } else if (startsWith(modelData.contentType, "application/smil") || |
1368 | - startsWith(modelData.contentType, "application/x-smil")) { |
1369 | - return "" |
1370 | - } else if (startsWith(modelData.contentType, "text/plain") ) { |
1371 | - mmsText = application.readTextFile(modelData.filePath) |
1372 | - mmsTextId = modelData.attachmentId |
1373 | - return "" |
1374 | - } else if (startsWith(modelData.contentType, "text/vcard") || |
1375 | - startsWith(modelData.contentType, "text/x-vcard")) { |
1376 | - return "MMS/MMSContact.qml" |
1377 | - } else { |
1378 | - console.log("No MMS render for " + modelData.contentType) |
1379 | - return "MMS/MMSDefault.qml" |
1380 | - } |
1381 | - } |
1382 | - onStatusChanged: { |
1383 | - if (status == Loader.Ready) { |
1384 | - item.attachment = modelData |
1385 | - item.incoming = incoming |
1386 | - } |
1387 | - } |
1388 | - Connections { |
1389 | - target: item |
1390 | - onItemRemoved: { |
1391 | - eventModel.removeEventAttachment(accountId, threadId, eventId, type, modelData.attachmentId) |
1392 | - if (visibleAttachments == 1 && mmsText === "") { |
1393 | - // this is the last attachment. remove the whole event |
1394 | - eventModel.removeEvent(accountId, threadId, eventId, type) |
1395 | - return |
1396 | - } |
1397 | - } |
1398 | - } |
1399 | - Connections { |
1400 | - target: item |
1401 | - onItemPressAndHold: itemPressAndHold(bubbleItem) |
1402 | - } |
1403 | - Binding { |
1404 | - target: item |
1405 | - property: "parentSelected" |
1406 | - value: messageDelegate.selected |
1407 | - } |
1408 | - Connections { |
1409 | - target: item |
1410 | - onAttachmentClicked: { |
1411 | - if (item.previewer === "") { |
1412 | - activeAttachment = modelData |
1413 | - PopupUtils.open(popoverSaveAttachmentComponent, item) |
1414 | - return |
1415 | - } |
1416 | - |
1417 | - var properties = {} |
1418 | - properties["attachment"] = item.attachment |
1419 | - mainStack.push(Qt.resolvedUrl(item.previewer), properties) |
1420 | - } |
1421 | - } |
1422 | - } |
1423 | - } |
1424 | - } |
1425 | - |
1426 | - ListItemWithActions { |
1427 | - id: bubbleItem |
1428 | - |
1429 | - anchors { |
1430 | - top: attachments.bottom |
1431 | - left: parent.left |
1432 | - right: parent.right |
1433 | - } |
1434 | - internalAnchors { |
1435 | - topMargin: 0 |
1436 | - bottomMargin: 0 |
1437 | - } |
1438 | - |
1439 | - height: bubble.visible ? bubble.height : 0 |
1440 | - leftSideAction: Action { |
1441 | - iconName: "delete" |
1442 | - text: i18n.tr("Delete") |
1443 | - onTriggered: { |
1444 | - // if there are no attachments, remove the whole message |
1445 | - if (visibleAttachments == 0) { |
1446 | - eventModel.removeEvent(accountId, threadId, eventId, type) |
1447 | - return |
1448 | - } |
1449 | - // check if this is an mms text and we have more attachments |
1450 | - if (mmsText !== "" && visibleAttachments > 1) { |
1451 | - // remove only the text attachment if we have more attachments |
1452 | - eventModel.removeEventAttachment(accountId, threadId, eventId, type, mmsTextId) |
1453 | - mmsText = "" |
1454 | - mmsTextId = "" |
1455 | - return |
1456 | - } |
1457 | - } |
1458 | - } |
1459 | - |
1460 | - selected: messageDelegate.selected |
1461 | - selectionMode: messageDelegate.selectionMode |
1462 | - onItemPressAndHold: messageDelegate.itemPressAndHold(bubbleItem) |
1463 | - onItemClicked: messageDelegate.itemClicked(bubbleItem) |
1464 | - onSwippingChanged: messageList.updateSwippedItem(bubbleItem) |
1465 | - onSwipeStateChanged: messageList.updateSwippedItem(bubbleItem) |
1466 | - |
1467 | - MessageBubble { |
1468 | - id: bubble |
1469 | - |
1470 | - anchors { |
1471 | - top: parent.top |
1472 | - left: incoming ? parent.left : undefined |
1473 | - right: incoming ? undefined : parent.right |
1474 | - } |
1475 | - visible: (messageText !== "") |
1476 | - messageText: textMessage !== "" ? textMessage : mmsText |
1477 | - messageTimeStamp: timestamp |
1478 | - messageStatus: textMessageStatus |
1479 | - } |
1480 | - |
1481 | - Loader { |
1482 | - id: statusIconLoader |
1483 | - active: !incoming && !messageDelegate.selectionMode && bubble.visible && (inProgress || failed) |
1484 | - sourceComponent: statusIcon |
1485 | - anchors.right: bubble.left |
1486 | - anchors.rightMargin: units.gu(1) |
1487 | - anchors.verticalCenter: bubble.verticalCenter |
1488 | - } |
1489 | - } |
1490 | - |
1491 | + objectName: "messageDelegate" |
1492 | + |
1493 | + property bool incoming |
1494 | + property var attachments |
1495 | + property string accountId |
1496 | + property var threadId |
1497 | + property var eventId |
1498 | + property var type |
1499 | + property string text |
1500 | + property var timestamp |
1501 | + property string accountLabel |
1502 | + property var _lastItem: messageDelegate |
1503 | + |
1504 | + |
1505 | + function deleteMessage() |
1506 | + { |
1507 | + //virtual implemented by each Message type |
1508 | + } |
1509 | + |
1510 | + function copyMessage() |
1511 | + { |
1512 | + //virtual implemented by each Message type |
1513 | + } |
1514 | + |
1515 | + function resendMessage() |
1516 | + { |
1517 | + //virtual implemented by each Message type |
1518 | + } |
1519 | + |
1520 | + function showMessageDetails(mouse) |
1521 | + { |
1522 | + //virtual implemented by each Message type |
1523 | + } |
1524 | + |
1525 | + function clicked(mouse) |
1526 | + { |
1527 | + //virtual implemented by each Message type |
1528 | + } |
1529 | } |
1530 | |
1531 | === added file 'src/qml/MessageDelegateFactory.qml' |
1532 | --- src/qml/MessageDelegateFactory.qml 1970-01-01 00:00:00 +0000 |
1533 | +++ src/qml/MessageDelegateFactory.qml 2014-08-12 15:31:06 +0000 |
1534 | @@ -0,0 +1,203 @@ |
1535 | +/* |
1536 | + * Copyright 2012, 2013, 2014 Canonical Ltd. |
1537 | + * |
1538 | + * This file is part of messaging-app. |
1539 | + * |
1540 | + * messaging-app is free software; you can redistribute it and/or modify |
1541 | + * it under the terms of the GNU General Public License as published by |
1542 | + * the Free Software Foundation; version 3. |
1543 | + * |
1544 | + * messaging-app is distributed in the hope that it will be useful, |
1545 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1546 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1547 | + * GNU General Public License for more details. |
1548 | + * |
1549 | + * You should have received a copy of the GNU General Public License |
1550 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1551 | + */ |
1552 | + |
1553 | +import QtQuick 2.2 |
1554 | +import Ubuntu.Components 1.1 |
1555 | +import Ubuntu.Contacts 0.1 |
1556 | +import Ubuntu.History 0.1 |
1557 | + |
1558 | +ListItemWithActions { |
1559 | + id: root |
1560 | + |
1561 | + property bool incoming: false |
1562 | + property var _lastItem: loader.status === Loader.Ready ? loader.item._lastItem : null |
1563 | + property list<Action> _availableActions |
1564 | + property string accountLabel |
1565 | + |
1566 | + signal deleteMessage() |
1567 | + signal resendMessage() |
1568 | + signal copyMessage() |
1569 | + signal showMessageDetails() |
1570 | + |
1571 | + triggerActionOnMouseRelease: true |
1572 | + width: messageList.width |
1573 | + leftSideAction: Action { |
1574 | + iconName: "delete" |
1575 | + text: i18n.tr("Delete") |
1576 | + onTriggered: deleteMessage() |
1577 | + } |
1578 | + |
1579 | + // WORKAROUND: to filter actions on rightSideActions property based on message status |
1580 | + _availableActions: [ |
1581 | + Action { |
1582 | + id: reloadAction |
1583 | + |
1584 | + iconName: "reload" |
1585 | + text: i18n.tr("Retry") |
1586 | + onTriggered: resendMessage() |
1587 | + }, |
1588 | + Action { |
1589 | + id: copyAction |
1590 | + |
1591 | + iconName: "edit-copy" |
1592 | + text: i18n.tr("Copy") |
1593 | + onTriggered: copyMessage() |
1594 | + }, |
1595 | + Action { |
1596 | + id: infoAction |
1597 | + |
1598 | + iconName: "info" |
1599 | + text: i18n.tr("Info") |
1600 | + onTriggered: { |
1601 | + // FIXME: Is that the corect way to do that? |
1602 | + var messageType = textMessageAttachments.length > 0 ? i18n.tr("MMS") : i18n.tr("SMS") |
1603 | + var messageInfo = {"type": messageType, |
1604 | + "senderId": senderId, |
1605 | + "timestamp": timestamp, |
1606 | + "textReadTimestamp": textReadTimestamp, |
1607 | + "status": textMessageStatus} |
1608 | + messageInfoDialog.showMessageInfo(messageInfo) |
1609 | + } |
1610 | + } |
1611 | + ] |
1612 | + |
1613 | + rightSideActions: { |
1614 | + var actions = [] |
1615 | + if (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) { |
1616 | + actions.push(reloadAction) |
1617 | + } |
1618 | + actions.push(copyAction) |
1619 | + actions.push(infoAction) |
1620 | + return actions |
1621 | + } |
1622 | + |
1623 | + height: loader.height + units.gu(1) |
1624 | + internalAnchors { |
1625 | + topMargin: units.gu(0.5) |
1626 | + bottomMargin: units.gu(0.5) |
1627 | + } |
1628 | + |
1629 | + onItemClicked: { |
1630 | + if (!selectionMode && (loader.status === Loader.Ready)) { |
1631 | + loader.item.clicked(mouse) |
1632 | + } |
1633 | + } |
1634 | + |
1635 | + Loader { |
1636 | + id: loader |
1637 | + |
1638 | + onStatusChanged: { |
1639 | + if (status === Loader.Ready) { |
1640 | + //signals |
1641 | + root.resendMessage.connect(item.resendMessage) |
1642 | + root.deleteMessage.connect(item.deleteMessage) |
1643 | + root.copyMessage.connect(item.copyMessage) |
1644 | + root.showMessageDetails(item.showMessageDetails) |
1645 | + } |
1646 | + } |
1647 | + anchors { |
1648 | + left: parent.left |
1649 | + right: parent.right |
1650 | + } |
1651 | + height: status == Loader.Ready ? item.height : 0 |
1652 | + Component.onCompleted: { |
1653 | + var initialProperties = { |
1654 | + "incoming": root.incoming, |
1655 | + "accountLabel": accountLabel, |
1656 | + "attachments": textMessageAttachments, |
1657 | + "accountId": accountId, |
1658 | + "threadId": threadId, |
1659 | + "eventId": eventId, |
1660 | + "type": type, |
1661 | + "text": textMessage, |
1662 | + "timestamp": timestamp |
1663 | + } |
1664 | + if (textMessageAttachments.length > 0) { |
1665 | + setSource(Qt.resolvedUrl("MMSDelegate.qml"), initialProperties) |
1666 | + } else { |
1667 | + setSource(Qt.resolvedUrl("SMSDelegate.qml"), initialProperties) |
1668 | + } |
1669 | + } |
1670 | + } |
1671 | + |
1672 | + Item { |
1673 | + id: statusIcon |
1674 | + |
1675 | + height: units.gu(4) |
1676 | + width: units.gu(4) |
1677 | + parent: _lastItem |
1678 | + anchors { |
1679 | + verticalCenter: parent ? parent.verticalCenter : undefined |
1680 | + right: parent ? parent.left : undefined |
1681 | + rightMargin: units.gu(2) |
1682 | + } |
1683 | + |
1684 | + visible: !incoming && !selectionMode |
1685 | + ActivityIndicator { |
1686 | + id: indicator |
1687 | + |
1688 | + anchors.centerIn: parent |
1689 | + height: units.gu(2) |
1690 | + width: units.gu(2) |
1691 | + visible: running && !selectionMode |
1692 | + // if temporarily failed or unknown status, then show the spinner |
1693 | + running: (textMessageStatus === HistoryThreadModel.MessageStatusUnknown || |
1694 | + textMessageStatus === HistoryThreadModel.MessageStatusTemporarilyFailed) |
1695 | + } |
1696 | + |
1697 | + Item { |
1698 | + id: retrybutton |
1699 | + |
1700 | + anchors.fill: parent |
1701 | + Icon { |
1702 | + id: icon |
1703 | + |
1704 | + name: "reload" |
1705 | + color: "red" |
1706 | + height: units.gu(2) |
1707 | + width: units.gu(2) |
1708 | + anchors { |
1709 | + centerIn: parent |
1710 | + verticalCenterOffset: units.gu(-1) |
1711 | + } |
1712 | + } |
1713 | + |
1714 | + Label { |
1715 | + text: i18n.tr("Failed!") |
1716 | + fontSize: "small" |
1717 | + color: "red" |
1718 | + anchors { |
1719 | + horizontalCenter: retrybutton.horizontalCenter |
1720 | + top: icon.bottom |
1721 | + } |
1722 | + } |
1723 | + visible: (textMessageStatus === HistoryThreadModel.MessageStatusPermanentlyFailed) |
1724 | + MouseArea { |
1725 | + id: retrybuttonMouseArea |
1726 | + |
1727 | + anchors.fill: parent |
1728 | + onClicked: root.resendMessage() |
1729 | + } |
1730 | + } |
1731 | + |
1732 | + |
1733 | + MessageInfoDialog { |
1734 | + id: messageInfoDialog |
1735 | + } |
1736 | + } |
1737 | +} |
1738 | |
1739 | === added file 'src/qml/MessageInfoDialog.qml' |
1740 | --- src/qml/MessageInfoDialog.qml 1970-01-01 00:00:00 +0000 |
1741 | +++ src/qml/MessageInfoDialog.qml 2014-08-12 15:31:06 +0000 |
1742 | @@ -0,0 +1,124 @@ |
1743 | +/* |
1744 | + * Copyright 2012, 2013, 2014 Canonical Ltd. |
1745 | + * |
1746 | + * This file is part of messaging-app. |
1747 | + * |
1748 | + * messaging-app is free software; you can redistribute it and/or modify |
1749 | + * it under the terms of the GNU General Public License as published by |
1750 | + * the Free Software Foundation; version 3. |
1751 | + * |
1752 | + * messaging-app is distributed in the hope that it will be useful, |
1753 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1754 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1755 | + * GNU General Public License for more details. |
1756 | + * |
1757 | + * You should have received a copy of the GNU General Public License |
1758 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1759 | + */ |
1760 | + |
1761 | +import QtQuick 2.2 |
1762 | +import Ubuntu.Components 1.1 |
1763 | +import Ubuntu.Components.Popups 0.1 |
1764 | +import Ubuntu.History 0.1 |
1765 | + |
1766 | + |
1767 | +Item { |
1768 | + id: root |
1769 | + |
1770 | + property QtObject activeDialog: null |
1771 | + property var activeMessage: null |
1772 | + |
1773 | + function showMessageInfo(message) |
1774 | + { |
1775 | + if (!activeDialog) { |
1776 | + activeMessage = message |
1777 | + activeDialog = PopupUtils.open(messageInfoDialog, messages) |
1778 | + } |
1779 | + } |
1780 | + |
1781 | + Component { |
1782 | + id: messageInfoDialog |
1783 | + |
1784 | + Dialog { |
1785 | + id: dialogue |
1786 | + |
1787 | + parent: messages |
1788 | + |
1789 | + function statusToString(status) |
1790 | + { |
1791 | + switch(status) |
1792 | + { |
1793 | + case HistoryThreadModel.MessageStatusDelivered: |
1794 | + return i18n.tr("Delivered") |
1795 | + case HistoryThreadModel.MessageStatusTemporarilyFailed: |
1796 | + return i18n.tr("Temporarily Failed") |
1797 | + case HistoryThreadModel.MessageStatusPermanentlyFailed: |
1798 | + return i18n.tr("Failed") |
1799 | + case HistoryThreadModel.MessageStatusAccepted: |
1800 | + return i18n.tr("Accepted") |
1801 | + case HistoryThreadModel.MessageStatusRead: |
1802 | + return i18n.tr("Read") |
1803 | + case HistoryThreadModel.MessageStatusDeleted: |
1804 | + return i18n.tr("Deleted") |
1805 | + case HistoryThreadModel.MessageStatusPending: |
1806 | + return i18n.tr("Pending") |
1807 | + case HistoryThreadModel.MessageStatusUnknown: |
1808 | + //FIXME: Received messages has Unknown status is that correct?? |
1809 | + if (root.activeMessage.senderId !== "self") { |
1810 | + return i18n.tr("Received") |
1811 | + } else { |
1812 | + return i18n.tr("Unknown") |
1813 | + } |
1814 | + default: |
1815 | + return i18n.tr("Unknown") |
1816 | + } |
1817 | + } |
1818 | + |
1819 | + |
1820 | + title: i18n.tr("Message info") |
1821 | + |
1822 | + anchors.centerIn: parent |
1823 | + height: childrenRect.height |
1824 | + width: childrenRect.width |
1825 | + |
1826 | + Label { |
1827 | + text: "<b>%1:</b> %2".arg(i18n.tr("Type")).arg(root.activeMessage.type) |
1828 | + } |
1829 | + |
1830 | + Label { |
1831 | + text: "<b>%1:</b> %2".arg(i18n.tr("From")).arg(root.activeMessage.senderId !== "self" ? root.activeMessage.senderId : i18n.tr("Myself")) |
1832 | + } |
1833 | + |
1834 | + Label { |
1835 | + text: "<b>%1:</b> %2".arg(i18n.tr("Sent")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate)) |
1836 | + visible: (root.activeMessage.senderId === "self") |
1837 | + } |
1838 | + |
1839 | + Label { |
1840 | + text: "<b>%1:</b> %2".arg(i18n.tr("Received")).arg(Qt.formatDateTime(root.activeMessage.timestamp, Qt.DefaultLocaleShortDate)) |
1841 | + visible: (root.activeMessage.senderId !== "self") |
1842 | + } |
1843 | + |
1844 | + Label { |
1845 | + text: "<b>%1:</b> %2".arg(i18n.tr("Read")).arg(Qt.formatDateTime(root.activeMessage.textReadTimestamp, Qt.DefaultLocaleShortDate)) |
1846 | + visible: (root.activeMessage.senderId !== "self") && (root.activeMessage.textReadTimestamp > 0) |
1847 | + } |
1848 | + |
1849 | + Label { |
1850 | + text: "<b>%1:</b> %2".arg(i18n.tr("Status")).arg(statusToString(root.activeMessage.status)) |
1851 | + } |
1852 | + |
1853 | + Button { |
1854 | + text: i18n.tr("Close") |
1855 | + onClicked: { |
1856 | + PopupUtils.close(root.activeDialog) |
1857 | + } |
1858 | + } |
1859 | + |
1860 | + Component.onDestruction: { |
1861 | + root.activeDialog = null |
1862 | + root.activeMessage = null |
1863 | + } |
1864 | + } |
1865 | + } |
1866 | +} |
1867 | |
1868 | === modified file 'src/qml/Messages.qml' |
1869 | --- src/qml/Messages.qml 2014-07-31 20:21:52 +0000 |
1870 | +++ src/qml/Messages.qml 2014-08-12 15:31:06 +0000 |
1871 | @@ -16,7 +16,7 @@ |
1872 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1873 | */ |
1874 | |
1875 | -import QtQuick 2.0 |
1876 | +import QtQuick 2.2 |
1877 | import QtQuick.Window 2.0 |
1878 | import QtContacts 5.0 |
1879 | import Ubuntu.Components 1.1 |
1880 | @@ -28,11 +28,16 @@ |
1881 | import Ubuntu.Contacts 0.1 |
1882 | import QtContacts 5.0 |
1883 | |
1884 | +import "dateUtils.js" as DateUtils |
1885 | + |
1886 | Page { |
1887 | id: messages |
1888 | objectName: "messagesPage" |
1889 | - property QtObject account: telepathyHelper.accounts[0] |
1890 | - property bool multipleAccounts: telepathyHelper.accounts.length > 1 |
1891 | + |
1892 | + // this property can be overriden by the user using the account switcher, |
1893 | + // in the suru divider |
1894 | + property QtObject account: mainView.defaultAccount |
1895 | + |
1896 | property variant participants: [] |
1897 | property bool groupChat: participants.length > 1 |
1898 | property bool keyboardFocus: true |
1899 | @@ -40,7 +45,6 @@ |
1900 | // FIXME: MainView should provide if the view is in portait or landscape |
1901 | property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) |
1902 | property bool landscape: orientationAngle == 90 || orientationAngle == 270 |
1903 | - property bool pendingMessage: false |
1904 | property var activeTransfer: null |
1905 | property int activeAttachmentIndex: -1 |
1906 | property var sharedAttachmentsTransfer: [] |
1907 | @@ -72,6 +76,13 @@ |
1908 | return messages.account.connected; |
1909 | } |
1910 | |
1911 | + // this is necessary to automatically update the view when the |
1912 | + // default account changes in system settings |
1913 | + Connections { |
1914 | + target: mainView |
1915 | + onDefaultAccountChanged: account = mainView.defaultAccount |
1916 | + } |
1917 | + |
1918 | ListModel { |
1919 | id: attachments |
1920 | } |
1921 | @@ -103,7 +114,7 @@ |
1922 | |
1923 | title: { |
1924 | if (selectionMode) { |
1925 | - return i18n.tr("Edit") |
1926 | + return i18n.tr(" ") |
1927 | } |
1928 | |
1929 | if (landscape) { |
1930 | @@ -119,7 +130,7 @@ |
1931 | if (participants.length == 1) { |
1932 | return firstRecipient |
1933 | } else { |
1934 | - return i18n.tr("Group (%1 members)").arg(participants.length) |
1935 | + return i18n.tr("Group (%1)").arg(participants.length) |
1936 | } |
1937 | } |
1938 | return i18n.tr("New Message") |
1939 | @@ -256,12 +267,20 @@ |
1940 | } |
1941 | return accountNames |
1942 | } |
1943 | - head.sections.selectedIndex: Math.max(0, telepathyHelper.accounts.indexOf(messages.account)) |
1944 | + head.sections.selectedIndex: { |
1945 | + if (!messages.account) { |
1946 | + return -1 |
1947 | + } |
1948 | + for (var i in telepathyHelper.accounts) { |
1949 | + if (telepathyHelper.accounts[i].accountId === messages.account.accountId) { |
1950 | + return i |
1951 | + } |
1952 | + } |
1953 | + return -1 |
1954 | + } |
1955 | Connections { |
1956 | target: messages.head.sections |
1957 | - onSelectedIndexChanged: { |
1958 | - messages.account = telepathyHelper.accounts[head.sections.selectedIndex] |
1959 | - } |
1960 | + onSelectedIndexChanged: messages.account = telepathyHelper.accounts[head.sections.selectedIndex] |
1961 | } |
1962 | |
1963 | Component { |
1964 | @@ -277,30 +296,13 @@ |
1965 | filterTerm: multiRecipient.searchString |
1966 | showSections: false |
1967 | autoHideKeyboard: false |
1968 | - |
1969 | - states: [ |
1970 | - State { |
1971 | - name: "empty" |
1972 | - when: contactSearch.count === 0 |
1973 | - PropertyChanges { |
1974 | - target: contactSearch |
1975 | - height: 0 |
1976 | - } |
1977 | - } |
1978 | - ] |
1979 | - |
1980 | anchors { |
1981 | top: parent.top |
1982 | topMargin: units.gu(1) |
1983 | left: parent.left |
1984 | right: parent.right |
1985 | - bottom: bottomPanel.top |
1986 | - } |
1987 | - |
1988 | - Behavior on height { |
1989 | - UbuntuNumberAnimation { } |
1990 | - } |
1991 | - |
1992 | + bottom: parent.bottom |
1993 | + } |
1994 | InvalidFilter { |
1995 | id: invalidFilter |
1996 | } |
1997 | @@ -359,7 +361,7 @@ |
1998 | } |
1999 | height: units.gu(2) |
2000 | text: { |
2001 | - // this is necessary to keep the string in the original format |
2002 | + // this is necessary to keep the string in the original foverdrawormat |
2003 | var originalText = contact.displayLabel.label |
2004 | var lowerSearchText = multiRecipient.searchString.toLowerCase() |
2005 | var lowerText = originalText.toLowerCase() |
2006 | @@ -404,16 +406,27 @@ |
2007 | } |
2008 | |
2009 | Loader { |
2010 | - active: multiRecipient.searchString !== "" && multiRecipient.focus |
2011 | - sourceComponent: contactSearchComponent |
2012 | + property int resultCount: (status === Loader.Ready) ? item.view.count : 0 |
2013 | + |
2014 | + sourceComponent: (multiRecipient.searchString !== "") && multiRecipient.focus ? contactSearchComponent : null |
2015 | clip: true |
2016 | anchors { |
2017 | top: parent.top |
2018 | left: parent.left |
2019 | right: parent.right |
2020 | - bottom: bottomPanel.top |
2021 | } |
2022 | + height: resultCount > 0 ? parent.height - keyboard.height : 0 |
2023 | z: 1 |
2024 | + // WORKAROUND: we need to use opacity here visible FALSE cause the item to not load |
2025 | + opacity: height > 0 ? 1.0 : 0.0 |
2026 | + Behavior on height { |
2027 | + UbuntuNumberAnimation { } |
2028 | + } |
2029 | + |
2030 | + Rectangle { |
2031 | + anchors.fill: parent |
2032 | + color: Theme.palette.normal.background |
2033 | + } |
2034 | } |
2035 | |
2036 | ContactWatcher { |
2037 | @@ -470,7 +483,13 @@ |
2038 | Action { |
2039 | objectName: "selectionModeSelectAllAction" |
2040 | iconName: "select" |
2041 | - onTriggered: messageList.selectAll() |
2042 | + onTriggered: { |
2043 | + if (messageList.selectedItems.count === messageList.count) { |
2044 | + messageList.clearSelection() |
2045 | + } else { |
2046 | + messageList.selectAll() |
2047 | + } |
2048 | + } |
2049 | }, |
2050 | Action { |
2051 | objectName: "selectionModeDeleteAction" |
2052 | @@ -627,86 +646,66 @@ |
2053 | header: Item { |
2054 | height: units.gu(1) |
2055 | } |
2056 | - |
2057 | - spacing: units.gu(1) |
2058 | listModel: participants.length > 0 ? sortProxy : null |
2059 | verticalLayoutDirection: ListView.BottomToTop |
2060 | - highlightFollowsCurrentItem: false |
2061 | - /*add: Transition { |
2062 | - UbuntuNumberAnimation { |
2063 | - properties: "anchors.leftMargin" |
2064 | - from: -width |
2065 | - to: 0 |
2066 | - } |
2067 | - UbuntuNumberAnimation { |
2068 | - properties: "anchors.rightMargin" |
2069 | - from: -width |
2070 | - to: 0 |
2071 | - } |
2072 | - }*/ |
2073 | + highlightFollowsCurrentItem: true |
2074 | + currentIndex: 0 |
2075 | + // keep the last item as currentItem |
2076 | |
2077 | - listDelegate: MessageDelegate { |
2078 | + listDelegate: Column { |
2079 | id: messageDelegate |
2080 | - objectName: "message%1".arg(index) |
2081 | - incoming: senderId != "self" |
2082 | - // TODO: we have several items inside |
2083 | - selected: messageList.isSelected(messageDelegate) |
2084 | - unread: newEvent |
2085 | - selectionMode: messages.selectionMode |
2086 | - accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : "" |
2087 | - // TODO: need select only the item |
2088 | - onItemClicked: { |
2089 | - if (messageList.isInSelectionMode) { |
2090 | - if (!messageList.selectItem(messageDelegate)) { |
2091 | - messageList.deselectItem(messageDelegate) |
2092 | - } |
2093 | - } |
2094 | - } |
2095 | - onItemPressAndHold: { |
2096 | - messageList.startSelection() |
2097 | - messageList.selectItem(messageDelegate) |
2098 | - } |
2099 | - |
2100 | - Component.onCompleted: { |
2101 | - if (newEvent) { |
2102 | - messages.markMessageAsRead(accountId, threadId, eventId, type); |
2103 | - } |
2104 | - } |
2105 | - onResend: { |
2106 | - // resend this message and remove the old one |
2107 | - if (textMessageAttachments.length > 0) { |
2108 | - var newAttachments = [] |
2109 | - for (var i = 0; i < textMessageAttachments.length; i++) { |
2110 | - var attachment = [] |
2111 | - var item = textMessageAttachments[i] |
2112 | - // we dont include smil files. they will be auto generated |
2113 | - if (item.contentType.toLowerCase() == "application/smil") { |
2114 | - continue |
2115 | + |
2116 | + // WORKAROUND: we can not use sections because the verticalLayoutDirection is ListView.BottomToTop the sections will appear |
2117 | + // bellow the item |
2118 | + MessageDateSection { |
2119 | + text: DateUtils.friendlyDay(timestamp) |
2120 | + anchors { |
2121 | + left: parent.left |
2122 | + right: parent.right |
2123 | + leftMargin: units.gu(2) |
2124 | + rightMargin: units.gu(2) |
2125 | + } |
2126 | + visible: (index === messageList.count) || !DateUtils.areSameDay(sortProxy.get(index+1).timestamp, timestamp) |
2127 | + } |
2128 | + |
2129 | + MessageDelegateFactory { |
2130 | + objectName: "message%1".arg(index) |
2131 | + incoming: senderId != "self" |
2132 | + // TODO: we have several items inside |
2133 | + selected: messageList.isSelected(messageDelegate) |
2134 | + selectionMode: messages.selectionMode |
2135 | + accountLabel: multipleAccounts ? telepathyHelper.accountForId(accountId).displayName : "" |
2136 | + // TODO: need select only the item |
2137 | + onItemClicked: { |
2138 | + if (messageList.isInSelectionMode) { |
2139 | + if (!messageList.selectItem(messageDelegate)) { |
2140 | + messageList.deselectItem(messageDelegate) |
2141 | } |
2142 | - attachment.push(item.attachmentId) |
2143 | - attachment.push(item.contentType) |
2144 | - attachment.push(item.filePath) |
2145 | - newAttachments.push(attachment) |
2146 | - } |
2147 | - eventModel.removeEvent(accountId, threadId, eventId, type) |
2148 | - chatManager.sendMMS(participants, textMessage, newAttachments, messages.account.accountId) |
2149 | - return |
2150 | - } |
2151 | - eventModel.removeEvent(accountId, threadId, eventId, type) |
2152 | - chatManager.sendMessage(messages.participants, textMessage, messages.account.accountId) |
2153 | + } |
2154 | + } |
2155 | + onItemPressAndHold: { |
2156 | + messageList.startSelection() |
2157 | + messageList.selectItem(messageDelegate) |
2158 | + } |
2159 | + |
2160 | + Component.onCompleted: { |
2161 | + if (newEvent) { |
2162 | + messages.markMessageAsRead(accountId, threadId, eventId, type); |
2163 | + } |
2164 | + } |
2165 | } |
2166 | } |
2167 | + |
2168 | onSelectionDone: { |
2169 | for (var i=0; i < items.count; i++) { |
2170 | var event = items.get(i).model |
2171 | eventModel.removeEvent(event.accountId, event.threadId, event.eventId, event.type) |
2172 | } |
2173 | } |
2174 | + |
2175 | onCountChanged: { |
2176 | - if (messages.pendingMessage) { |
2177 | - messageList.contentY = 0 |
2178 | - messages.pendingMessage = false |
2179 | - } |
2180 | + currentIndex = 0 |
2181 | + positionViewAtBeginning() |
2182 | } |
2183 | } |
2184 | |
2185 | @@ -891,7 +890,7 @@ |
2186 | height: units.gu(4.3) |
2187 | style: MultiRecipientFieldStyle {} |
2188 | autoSize: true |
2189 | - maximumLineCount: 0 |
2190 | + maximumLineCount: attachments.count == 0 ? 8 : 4 |
2191 | placeholderText: i18n.tr("Write a message...") |
2192 | focus: textEntry.focus |
2193 | font.family: "Ubuntu" |
2194 | @@ -935,20 +934,25 @@ |
2195 | return false |
2196 | } |
2197 | onClicked: { |
2198 | + // check if at least one account is selected |
2199 | + if (!messages.account) { |
2200 | + Qt.inputMethod.hide() |
2201 | + PopupUtils.open(Qt.createComponent("Dialogs/NoSIMCardSelectedDialog.qml").createObject(messages)) |
2202 | + return |
2203 | + } |
2204 | if (!checkNetwork()) { |
2205 | Qt.inputMethod.hide() |
2206 | PopupUtils.open(noNetworkDialog) |
2207 | return |
2208 | } |
2209 | + if (multipleAccounts && !telepathyHelper.defaultMessagingAccount && !settings.messagesDontAsk) { |
2210 | + PopupUtils.open(Qt.createComponent("Dialogs/SetDefaultSIMCardDialog.qml").createObject(messages)) |
2211 | + } |
2212 | // make sure we flush everything we have prepared in the OSK preedit |
2213 | Qt.inputMethod.commit(); |
2214 | if (textEntry.text == "" && attachments.count == 0) { |
2215 | return |
2216 | } |
2217 | - if (!messages.account) { |
2218 | - // FIXME: handle dual sim |
2219 | - messages.account = telepathyHelper.accounts[0] |
2220 | - } |
2221 | // dont change the participants list |
2222 | if (participants.length == 0) { |
2223 | participants = multiRecipient.recipients |
2224 | @@ -961,7 +965,6 @@ |
2225 | true) |
2226 | |
2227 | updateFilters() |
2228 | - messages.pendingMessage = true |
2229 | if (attachments.count > 0) { |
2230 | var newAttachments = [] |
2231 | for (var i = 0; i < attachments.count; i++) { |
2232 | |
2233 | === modified file 'src/qml/MultiRecipientInput.qml' |
2234 | --- src/qml/MultiRecipientInput.qml 2014-07-30 16:19:08 +0000 |
2235 | +++ src/qml/MultiRecipientInput.qml 2014-08-12 15:31:06 +0000 |
2236 | @@ -16,7 +16,7 @@ |
2237 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2238 | */ |
2239 | |
2240 | -import QtQuick 2.0 |
2241 | +import QtQuick 2.2 |
2242 | import Ubuntu.Components 1.1 |
2243 | import Ubuntu.Contacts 0.1 |
2244 | import Ubuntu.Telephony 0.1 |
2245 | |
2246 | === modified file 'src/qml/NewRecipientPage.qml' |
2247 | --- src/qml/NewRecipientPage.qml 2014-08-01 14:51:29 +0000 |
2248 | +++ src/qml/NewRecipientPage.qml 2014-08-12 15:31:06 +0000 |
2249 | @@ -16,7 +16,7 @@ |
2250 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2251 | */ |
2252 | |
2253 | -import QtQuick 2.0 |
2254 | +import QtQuick 2.2 |
2255 | import Ubuntu.Components 1.1 |
2256 | import Ubuntu.Contacts 0.1 |
2257 | import QtContacts 5.0 |
2258 | |
2259 | === added file 'src/qml/SMSDelegate.qml' |
2260 | --- src/qml/SMSDelegate.qml 1970-01-01 00:00:00 +0000 |
2261 | +++ src/qml/SMSDelegate.qml 2014-08-12 15:31:06 +0000 |
2262 | @@ -0,0 +1,75 @@ |
2263 | +/* |
2264 | + * Copyright 2012, 2013, 2014 Canonical Ltd. |
2265 | + * |
2266 | + * This file is part of messaging-app. |
2267 | + * |
2268 | + * messaging-app is free software; you can redistribute it and/or modify |
2269 | + * it under the terms of the GNU General Public License as published by |
2270 | + * the Free Software Foundation; version 3. |
2271 | + * |
2272 | + * messaging-app is distributed in the hope that it will be useful, |
2273 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2274 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2275 | + * GNU General Public License for more details. |
2276 | + * |
2277 | + * You should have received a copy of the GNU General Public License |
2278 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2279 | + */ |
2280 | + |
2281 | +import QtQuick 2.2 |
2282 | +import Ubuntu.Components 1.1 |
2283 | + |
2284 | +import "dateUtils.js" as DateUtils |
2285 | + |
2286 | +MessageDelegate { |
2287 | + id: root |
2288 | + |
2289 | + function deleteMessage() |
2290 | + { |
2291 | + eventModel.removeEvent(accountId, threadId, eventId, type) |
2292 | + } |
2293 | + |
2294 | + function resendMessage() |
2295 | + { |
2296 | + eventModel.removeEvent(accountId, threadId, eventId, type) |
2297 | + chatManager.sendMessage(messages.participants, textMessage, messages.accountId) |
2298 | + } |
2299 | + |
2300 | + function copyMessage() |
2301 | + { |
2302 | + Clipboard.push(bubble.messageText) |
2303 | + } |
2304 | + |
2305 | + height: bubble.height |
2306 | + _lastItem: bubble |
2307 | + |
2308 | + MessageBubble { |
2309 | + id: bubble |
2310 | + |
2311 | + states: [ |
2312 | + State { |
2313 | + name: "incoming" |
2314 | + when: incoming |
2315 | + AnchorChanges { |
2316 | + target: bubble |
2317 | + anchors.left: parent.left |
2318 | + } |
2319 | + }, |
2320 | + State { |
2321 | + name: "outgoing" |
2322 | + when: !incoming |
2323 | + AnchorChanges { |
2324 | + target: bubble |
2325 | + anchors.right: parent.right |
2326 | + } |
2327 | + } |
2328 | + |
2329 | + ] |
2330 | + visible: (root.text !== "") |
2331 | + messageIncoming: root.incoming |
2332 | + messageText: root.text |
2333 | + messageTimeStamp: root.timestamp |
2334 | + accountName: root.accountLabel |
2335 | + messageStatus: textMessageStatus |
2336 | + } |
2337 | +} |
2338 | |
2339 | === modified file 'src/qml/StandardAnimation.qml' |
2340 | --- src/qml/StandardAnimation.qml 2013-07-17 21:47:45 +0000 |
2341 | +++ src/qml/StandardAnimation.qml 2014-08-12 15:31:06 +0000 |
2342 | @@ -16,7 +16,7 @@ |
2343 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2344 | */ |
2345 | |
2346 | -import QtQuick 2.0 |
2347 | +import QtQuick 2.2 |
2348 | |
2349 | NumberAnimation { |
2350 | duration: 300 |
2351 | |
2352 | === modified file 'src/qml/ThreadDelegate.qml' |
2353 | --- src/qml/ThreadDelegate.qml 2014-07-31 19:01:08 +0000 |
2354 | +++ src/qml/ThreadDelegate.qml 2014-08-12 15:31:06 +0000 |
2355 | @@ -16,7 +16,7 @@ |
2356 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2357 | */ |
2358 | |
2359 | -import QtQuick 2.0 |
2360 | +import QtQuick 2.2 |
2361 | import Ubuntu.Components 1.1 |
2362 | import Ubuntu.Components.Popups 0.1 |
2363 | import Ubuntu.Telephony 0.1 |
2364 | @@ -44,7 +44,6 @@ |
2365 | return firstRecipient |
2366 | } |
2367 | |
2368 | - property bool selectionMode: false |
2369 | property string textMessage: { |
2370 | // check if this is an mms, if so, search for the actual text |
2371 | var imageCount = 0 |
2372 | @@ -111,9 +110,17 @@ |
2373 | ContactAvatar { |
2374 | id: avatar |
2375 | |
2376 | - fallbackAvatarUrl: delegateHelper.avatar !== "" ? delegateHelper.avatar : "image://theme/contact" |
2377 | + fallbackAvatarUrl: { |
2378 | + if (groupChat) { |
2379 | + return "image://theme/contact-group" |
2380 | + } else if (delegateHelper.avatar !== "") { |
2381 | + return delegateHelper.avatar |
2382 | + } else { |
2383 | + return "image://theme/contact" |
2384 | + } |
2385 | + } |
2386 | fallbackDisplayName: delegateHelper.alias |
2387 | - showAvatarPicture: (delegateHelper.avatar !== "") || (initials.length === 0) |
2388 | + showAvatarPicture: groupChat || (delegateHelper.avatar !== "") || (initials.length === 0) |
2389 | anchors { |
2390 | left: parent.left |
2391 | top: parent.top |
2392 | @@ -127,24 +134,35 @@ |
2393 | id: contactName |
2394 | anchors { |
2395 | top: avatar.top |
2396 | + topMargin: units.gu(0.5) |
2397 | left: avatar.right |
2398 | leftMargin: units.gu(1) |
2399 | } |
2400 | - fontSize: "medium" |
2401 | color: UbuntuColors.lightAubergine |
2402 | text: groupChat ? groupChatLabel : unknownContact ? delegateHelper.phoneNumber : delegateHelper.alias |
2403 | } |
2404 | |
2405 | - Label { |
2406 | + Row { |
2407 | id: time |
2408 | + |
2409 | anchors { |
2410 | verticalCenter: contactName.verticalCenter |
2411 | right: parent.right |
2412 | } |
2413 | - fontSize: "x-small" |
2414 | - text: Qt.formatDateTime(eventTimestamp,"h:mm ap") |
2415 | + Label { |
2416 | + fontSize: "x-small" |
2417 | + font.weight: Font.DemiBold |
2418 | + opacity: 0.70 |
2419 | + text: Qt.formatDateTime(eventTimestamp,"h:mm") |
2420 | + } |
2421 | + Label { |
2422 | + fontSize: "x-small" |
2423 | + opacity: 0.70 |
2424 | + text: Qt.formatDateTime(eventTimestamp," ap") |
2425 | + } |
2426 | } |
2427 | - |
2428 | + |
2429 | + |
2430 | UbuntuShape { |
2431 | id: unreadCountIndicator |
2432 | height: units.gu(2) |
2433 | @@ -181,20 +199,18 @@ |
2434 | |
2435 | Label { |
2436 | id: latestMessage |
2437 | - height: units.gu(3) |
2438 | + |
2439 | anchors { |
2440 | top: contactName.bottom |
2441 | topMargin: units.gu(0.5) |
2442 | left: contactName.left |
2443 | right: time.left |
2444 | rightMargin: units.gu(3) |
2445 | + bottom: avatar.bottom |
2446 | } |
2447 | elide: Text.ElideRight |
2448 | - maximumLineCount: 2 |
2449 | fontSize: "x-small" |
2450 | - wrapMode: Text.WordWrap |
2451 | text: textMessage |
2452 | - font.weight: Font.Light |
2453 | } |
2454 | |
2455 | Item { |
2456 | |
2457 | === modified file 'src/qml/assets/conversation_incoming@27.png' |
2458 | Binary 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:31:06 +0000 differ |
2459 | === modified file 'src/qml/messaging-app.qml' |
2460 | --- src/qml/messaging-app.qml 2014-07-31 19:16:57 +0000 |
2461 | +++ src/qml/messaging-app.qml 2014-08-12 15:31:06 +0000 |
2462 | @@ -16,7 +16,8 @@ |
2463 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2464 | */ |
2465 | |
2466 | -import QtQuick 2.0 |
2467 | +import QtQuick 2.2 |
2468 | +import Qt.labs.settings 1.0 |
2469 | import Ubuntu.Components 1.1 |
2470 | import Ubuntu.Components.ListItems 0.1 as ListItem |
2471 | import Ubuntu.Components.Popups 0.1 |
2472 | @@ -27,6 +28,16 @@ |
2473 | id: mainView |
2474 | |
2475 | property string newPhoneNumber |
2476 | + property bool multipleAccounts: telepathyHelper.accounts.length > 1 |
2477 | + property QtObject defaultAccount: { |
2478 | + // we only use the default account property if we have more |
2479 | + // than one account, otherwise we use always the first one |
2480 | + if (multipleAccounts) { |
2481 | + return telepathyHelper.defaultMessagingAccount |
2482 | + } else { |
2483 | + return telepathyHelper.accounts[0] |
2484 | + } |
2485 | + } |
2486 | |
2487 | automaticOrientation: true |
2488 | width: units.gu(40) |
2489 | @@ -40,6 +51,23 @@ |
2490 | mainStack.push(Qt.resolvedUrl("MainPage.qml")) |
2491 | } |
2492 | |
2493 | + Connections { |
2494 | + target: telepathyHelper |
2495 | + onSetupReady: { |
2496 | + if (multipleAccounts && !telepathyHelper.defaultMessagingAccount && |
2497 | + settings.mainViewDontAskCount < 3 && mainStack.depth === 1) { |
2498 | + PopupUtils.open(Qt.createComponent("Dialogs/NoDefaultSIMCardDialog.qml").createObject(mainView)) |
2499 | + } |
2500 | + } |
2501 | + } |
2502 | + |
2503 | + Settings { |
2504 | + id: settings |
2505 | + category: "DualSim" |
2506 | + property bool messagesDontAsk: false |
2507 | + property int mainViewDontAskCount: 0 |
2508 | + } |
2509 | + |
2510 | Component { |
2511 | id: resultComponent |
2512 | ContentItem {} |
2513 | |
2514 | === modified file 'tests/autopilot/messaging_app/emulators.py' |
2515 | --- tests/autopilot/messaging_app/emulators.py 2014-08-05 19:37:08 +0000 |
2516 | +++ tests/autopilot/messaging_app/emulators.py 2014-08-12 15:31:06 +0000 |
2517 | @@ -57,8 +57,8 @@ |
2518 | """ |
2519 | |
2520 | time.sleep(2) # message is not always found on slow emulator |
2521 | - for message in self.select_many(MessageDelegate): |
2522 | - for item in self.select_many('Label'): |
2523 | + for message in self.select_many(MessageDelegateFactory): |
2524 | + for item in message.select_many('Label'): |
2525 | if "text" in item.get_properties(): |
2526 | if item.get_properties()['text'] == text: |
2527 | return message |
2528 | @@ -280,7 +280,7 @@ |
2529 | def enable_messages_selection_mode(self): |
2530 | """Enable the selection mode on the messages page by pressing and |
2531 | holding the first item""" |
2532 | - message = self.wait_select_single("MessageDelegate", |
2533 | + message = self.wait_select_single("MessageDelegateFactory", |
2534 | objectName="message0") |
2535 | self.long_press(message) |
2536 | |
2537 | @@ -375,6 +375,8 @@ |
2538 | """ |
2539 | thread = self.get_thread_from_number(phone_number) |
2540 | thread.swipe_to_delete() |
2541 | + # wait for the animation to end |
2542 | + time.sleep(1) |
2543 | thread.confirm_removal() |
2544 | |
2545 | def delete_message(self, text): |
2546 | @@ -473,8 +475,7 @@ |
2547 | |
2548 | def _get_message_delegate(self, index): |
2549 | return self.wait_select_single( |
2550 | - 'MessageDelegate', objectName='message{}'.format(index), |
2551 | - unread=False) |
2552 | + 'MessageDelegateFactory', objectName='message{}'.format(index)) |
2553 | |
2554 | def _long_press_to_select_message(self, message): |
2555 | # XXX We used to leave the pointing device pressed for three seconds, |
2556 | @@ -537,5 +538,5 @@ |
2557 | """Autopilot helper for ThreadDelegate.""" |
2558 | |
2559 | |
2560 | -class MessageDelegate(ListItemWithActions): |
2561 | - """Autopilot helper for the MessageDelegate.""" |
2562 | +class MessageDelegateFactory(ListItemWithActions): |
2563 | + """Autopilot helper for the MessageDelegateFactory.""" |
2564 | |
2565 | === modified file 'tests/qml/tst_MessageBubble.qml' |
2566 | --- tests/qml/tst_MessageBubble.qml 2014-07-31 17:24:57 +0000 |
2567 | +++ tests/qml/tst_MessageBubble.qml 2014-08-12 15:31:06 +0000 |
2568 | @@ -34,7 +34,7 @@ |
2569 | |
2570 | height: parent.height / 3 |
2571 | |
2572 | - incoming: true |
2573 | + messageIncoming: true |
2574 | } |
2575 | |
2576 | MessageBubble { |
2577 | @@ -44,7 +44,7 @@ |
2578 | anchors.top: incomingMessageBubble.bottom |
2579 | height: parent.height / 3 |
2580 | |
2581 | - incoming: false |
2582 | + messageIncoming: false |
2583 | } |
2584 | |
2585 | MessageBubble { |
2586 | @@ -54,7 +54,7 @@ |
2587 | anchors.top: outgoingMessageBubble.bottom |
2588 | height: parent.height / 3 |
2589 | |
2590 | - incoming: true |
2591 | + messageIncoming: true |
2592 | } |
2593 | |
2594 | UbuntuTestCase { |
2595 | @@ -67,7 +67,7 @@ |
2596 | } |
2597 | |
2598 | function cleanup() { |
2599 | - changeIncomingMessageBubble.incoming = true; |
2600 | + changeIncomingMessageBubble.messageIncoming = true; |
2601 | } |
2602 | |
2603 | function getFileName(filePath) { |
2604 | @@ -93,7 +93,7 @@ |
2605 | function test_changeIncomingMustUpdateSource() { |
2606 | var changeIncomingMessageBubble = findChild( |
2607 | root, 'changeIncomingMessageBubble'); |
2608 | - changeIncomingMessageBubble.incoming = false; |
2609 | + changeIncomingMessageBubble.messageIncoming = false; |
2610 | compare( |
2611 | getFileName(changeIncomingMessageBubble.source), |
2612 | 'conversation_outgoing.sci'); |
FAILED: Continuous integration, rev:201 jenkins. qa.ubuntu. com/job/ messaging- app-ci/ 340/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/2848/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 2265/console jenkins. qa.ubuntu. com/job/ messaging- app-utopic- amd64-ci/ 134/console jenkins. qa.ubuntu. com/job/ messaging- app-utopic- armhf-ci/ 134/console jenkins. qa.ubuntu. com/job/ messaging- app-utopic- i386-ci/ 134/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/4091/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/2528/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/messaging- app-ci/ 340/rebuild
http://