Merge lp:~boiko/messaging-app/compose_bar into lp:messaging-app

Proposed by Gustavo Pichorim Boiko
Status: Merged
Merged at revision: 486
Proposed branch: lp:~boiko/messaging-app/compose_bar
Merge into: lp:messaging-app
Prerequisite: lp:~tiagosh/messaging-app/update-sim-dialogs
Diff against target: 1193 lines (+655/-449)
7 files modified
src/qml/ComposeBar.qml (+312/-0)
src/qml/Messages.qml (+56/-448)
src/qml/MessagesHeader.qml (+1/-1)
src/qml/ThumbnailContact.qml (+106/-0)
src/qml/ThumbnailImage.qml (+49/-0)
src/qml/ThumbnailUnknown.qml (+45/-0)
src/qml/TransparentButton.qml (+86/-0)
To merge this branch: bzr merge lp:~boiko/messaging-app/compose_bar
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Tiago Salem Herrmann (community) Needs Fixing
Review via email: mp+278208@code.launchpad.net

Commit message

Move the bottom part of Messages view to a separate QML file for better code readability.

Description of the change

Move the bottom part of Messages view to a separate QML file for better code readability.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~boiko/messaging-app/compose_bar updated
444. By Gustavo Pichorim Boiko

Merge latest changes from trunk.

445. By Gustavo Pichorim Boiko

Remove unused include.

446. By Gustavo Pichorim Boiko

Add missing thumbnail files.

447. By Gustavo Pichorim Boiko

Merge latest changes from trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~boiko/messaging-app/compose_bar updated
448. By Gustavo Pichorim Boiko

Merge latest changes from trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tiago Salem Herrmann (tiagosh) :
review: Needs Fixing
lp:~boiko/messaging-app/compose_bar updated
449. By Gustavo Pichorim Boiko

Fix import version.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~boiko/messaging-app/compose_bar updated
450. By Gustavo Pichorim Boiko

Add missing copyright.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tiago Salem Herrmann (tiagosh) :
review: Needs Fixing
lp:~boiko/messaging-app/compose_bar updated
451. By Gustavo Pichorim Boiko

Add missing pressAndHold() signal and make use of it

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~boiko/messaging-app/compose_bar updated
452. By Gustavo Pichorim Boiko

Merge trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~boiko/messaging-app/compose_bar updated
453. By Gustavo Pichorim Boiko

Merge trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'src/qml/ComposeBar.qml'
--- src/qml/ComposeBar.qml 1970-01-01 00:00:00 +0000
+++ src/qml/ComposeBar.qml 2015-12-08 17:14:16 +0000
@@ -0,0 +1,312 @@
1/*
2 * Copyright 2012-2015 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 1.3
21import Ubuntu.Components.ListItems 1.3 as ListItem
22import Ubuntu.Components.Popups 1.3
23import Ubuntu.Content 0.1
24import Ubuntu.Telephony 0.1
25
26Item {
27 id: composeBar
28
29 property bool showContents: true
30 property int maxHeight: textEntry.height + units.gu(2)
31 property variant attachments: []
32 property bool canSend: true
33 property alias text: messageTextArea.text
34
35 signal sendRequested(string text, var attachments)
36
37 // internal properties
38 property int _activeAttachmentIndex: -1
39 property int _defaultHeight: textEntry.height + units.gu(2)
40
41 function forceFocus() {
42 messageTextArea.forceActiveFocus()
43 }
44
45 function reset() {
46 textEntry.text = ""
47 attachments.clear()
48 }
49
50 function addAttachments(transfer) {
51 for (var i = 0; i < transfer.items.length; i++) {
52 if (String(transfer.items[i].text).length > 0) {
53 composeBar.text = String(transfer.items[i].text)
54 continue
55 }
56 var attachment = {}
57 if (!startsWith(String(transfer.items[i].url),"file://")) {
58 composeBar.text = String(transfer.items[i].url)
59 continue
60 }
61 var filePath = String(transfer.items[i].url).replace('file://', '')
62 // get only the basename
63 attachment["contentType"] = application.fileMimeType(filePath)
64 if (startsWith(attachment["contentType"], "text/vcard") ||
65 startsWith(attachment["contentType"], "text/x-vcard")) {
66 attachment["name"] = "contact.vcf"
67 } else {
68 attachment["name"] = filePath.split('/').reverse()[0]
69 }
70 attachment["filePath"] = filePath
71 attachments.append(attachment)
72 }
73 }
74
75 function formattedTime(time) {
76 var d = new Date(0, 0, 0, 0, 0, time)
77 return d.getHours() == 0 ? Qt.formatTime(d, "mm:ss") : Qt.formatTime(d, "h:mm:ss")
78 }
79
80 anchors.bottom: isSearching ? parent.bottom : keyboard.top
81 anchors.left: parent.left
82 anchors.right: parent.right
83 height: showContents ? Math.min(_defaultHeight, maxHeight) : 0
84 visible: showContents
85 clip: true
86
87 Behavior on height {
88 UbuntuNumberAnimation { }
89 }
90
91 MouseArea {
92 anchors.fill: parent
93 onClicked: {
94 forceFocus()
95 }
96 }
97
98 ListModel {
99 id: attachments
100 }
101
102 Component {
103 id: attachmentPopover
104
105 Popover {
106 id: popover
107 Column {
108 id: containerLayout
109 anchors {
110 left: parent.left
111 top: parent.top
112 right: parent.right
113 }
114 ListItem.Standard {
115 text: i18n.tr("Remove")
116 onClicked: {
117 attachments.remove(_activeAttachmentIndex)
118 PopupUtils.close(popover)
119 }
120 }
121 }
122 Component.onDestruction: _activeAttachmentIndex = -1
123 }
124 }
125
126 ListItem.ThinDivider {
127 anchors.top: parent.top
128 }
129
130 Row {
131 id: leftSideActions
132
133 width: childrenRect.width
134 height: childrenRect.height
135
136 anchors {
137 left: parent.left
138 leftMargin: units.gu(2)
139 verticalCenter: sendButton.verticalCenter
140 }
141 spacing: units.gu(2)
142
143 PictureImport {
144 id: pictureImporter
145
146 onPictureReceived: {
147 var attachment = {}
148 var filePath = String(pictureUrl).replace('file://', '')
149 attachment["contentType"] = application.fileMimeType(filePath)
150 attachment["name"] = filePath.split('/').reverse()[0]
151 attachment["filePath"] = filePath
152 attachments.append(attachment)
153 textEntry.forceActiveFocus()
154 }
155 }
156
157 TransparentButton {
158 id: attachButton
159 objectName: "attachButton"
160 iconName: "camera-app-symbolic"
161 onClicked: {
162 Qt.inputMethod.hide()
163 pictureImporter.requestNewPicture()
164 }
165 }
166 }
167
168 StyledItem {
169 id: textEntry
170 property alias text: messageTextArea.text
171 property alias inputMethodComposing: messageTextArea.inputMethodComposing
172 property int fullSize: attachmentThumbnails.height + messageTextArea.height
173 style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry)
174 anchors {
175 topMargin: units.gu(1)
176 top: parent.top
177 left: leftSideActions.right
178 leftMargin: units.gu(2)
179 right: sendButton.left
180 rightMargin: units.gu(2)
181 }
182 height: attachments.count !== 0 ? fullSize + units.gu(1.5) : fullSize
183 onActiveFocusChanged: {
184 if(activeFocus) {
185 messageTextArea.forceActiveFocus()
186 } else {
187 focus = false
188 }
189 }
190 focus: false
191 MouseArea {
192 anchors.fill: parent
193 onClicked: forceFocus()
194 }
195 Flow {
196 id: attachmentThumbnails
197 spacing: units.gu(1)
198 anchors{
199 left: parent.left
200 right: parent.right
201 top: parent.top
202 topMargin: units.gu(1)
203 leftMargin: units.gu(1)
204 rightMargin: units.gu(1)
205 }
206 height: childrenRect.height
207
208 Repeater {
209 model: attachments
210 delegate: Loader {
211 id: loader
212 height: units.gu(8)
213 source: {
214 var contentType = getContentType(filePath)
215 console.log(contentType)
216 switch(contentType) {
217 case ContentType.Contacts:
218 return Qt.resolvedUrl("ThumbnailContact.qml")
219 case ContentType.Pictures:
220 return Qt.resolvedUrl("ThumbnailImage.qml")
221 case ContentType.Unknown:
222 return Qt.resolvedUrl("ThumbnailUnknown.qml")
223 default:
224 console.log("unknown content Type")
225 }
226 }
227 onStatusChanged: {
228 if (status == Loader.Ready) {
229 item.index = index
230 item.filePath = filePath
231 }
232 }
233
234 Connections {
235 target: loader.status == Loader.Ready ? loader.item : null
236 ignoreUnknownSignals: true
237 onPressAndHold: {
238 Qt.inputMethod.hide()
239 _activeAttachmentIndex = target.index
240 PopupUtils.open(attachmentPopover, parent)
241 }
242 }
243 }
244 }
245 }
246
247 ListItem.ThinDivider {
248 id: divider
249
250 anchors {
251 left: parent.left
252 right: parent.right
253 top: attachmentThumbnails.bottom
254 margins: units.gu(0.5)
255 }
256 visible: attachments.count > 0
257 }
258
259 TextArea {
260 id: messageTextArea
261 objectName: "messageTextArea"
262 anchors {
263 top: attachments.count == 0 ? textEntry.top : attachmentThumbnails.bottom
264 left: parent.left
265 right: parent.right
266 }
267 // this value is to avoid letter being cut off
268 height: units.gu(4.3)
269 style: LocalTextAreaStyle {}
270 autoSize: true
271 maximumLineCount: attachments.count == 0 ? 8 : 4
272 placeholderText: {
273 if (telepathyHelper.ready) {
274 var account = telepathyHelper.accountForId(presenceRequest.accountId)
275 if (account &&
276 (presenceRequest.type != PresenceRequest.PresenceTypeUnknown &&
277 presenceRequest.type != PresenceRequest.PresenceTypeUnset) &&
278 account.protocolInfo.serviceName !== "") {
279 console.log(presenceRequest.accountId)
280 console.log(presenceRequest.type)
281 return account.protocolInfo.serviceName
282 }
283 }
284 return i18n.tr("Write a message...")
285 }
286 focus: textEntry.focus
287 font.family: "Ubuntu"
288 font.pixelSize: FontUtils.sizeToPixels("medium")
289 color: "#5d5d5d"
290 }
291 }
292
293 TransparentButton {
294 id: sendButton
295 objectName: "sendButton"
296 anchors.verticalCenter: textEntry.verticalCenter
297 anchors.right: parent.right
298 anchors.rightMargin: units.gu(2)
299 iconSource: Qt.resolvedUrl("./assets/send.svg")
300 enabled: (canSend && (textEntry.text != "" || textEntry.inputMethodComposing || attachments.count > 0))
301
302 onClicked: {
303 // make sure we flush everything we have prepared in the OSK preedit
304 Qt.inputMethod.commit();
305 if (textEntry.text == "" && attachments.count == 0) {
306 return
307 }
308
309 composeBar.sendRequested(textEntry.text, attachments)
310 }
311 }
312}
0313
=== modified file 'src/qml/Messages.qml'
--- src/qml/Messages.qml 2015-12-07 17:55:17 +0000
+++ src/qml/Messages.qml 2015-12-08 17:14:16 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright 2012, 2013, 2014 Canonical Ltd.2 * Copyright 2012-2015 Canonical Ltd.
3 *3 *
4 * This file is part of messaging-app.4 * This file is part of messaging-app.
5 *5 *
@@ -272,32 +272,6 @@
272 sections.selectedIndex: getSelectedIndex()272 sections.selectedIndex: getSelectedIndex()
273 }273 }
274274
275
276 function addAttachmentsToModel(transfer) {
277 for (var i in transfer.items) {
278 if (String(transfer.items[i].text).length > 0) {
279 messages.text = String(transfer.items[i].text)
280 continue
281 }
282 var attachment = {}
283 if (!startsWith(String(transfer.items[i].url),"file://")) {
284 messages.text = String(transfer.items[i].url)
285 continue
286 }
287 var filePath = String(transfer.items[i].url).replace('file://', '')
288 // get only the basename
289 attachment["contentType"] = application.fileMimeType(filePath)
290 if (startsWith(attachment["contentType"], "text/vcard") ||
291 startsWith(attachment["contentType"], "text/x-vcard")) {
292 attachment["name"] = "contact.vcf"
293 } else {
294 attachment["name"] = filePath.split('/').reverse()[0]
295 }
296 attachment["filePath"] = filePath
297 attachments.append(attachment)
298 }
299 }
300
301 function sendMessageNetworkCheck() {275 function sendMessageNetworkCheck() {
302 if (messages.account.simLocked) {276 if (messages.account.simLocked) {
303 Qt.inputMethod.hide()277 Qt.inputMethod.hide()
@@ -500,24 +474,6 @@
500 visible: running474 visible: running
501 }475 }
502476
503 ListModel {
504 id: attachments
505 }
506
507 PictureImport {
508 id: pictureImporter
509
510 onPictureReceived: {
511 var attachment = {}
512 var filePath = String(pictureUrl).replace('file://', '')
513 attachment["contentType"] = application.fileMimeType(filePath)
514 attachment["name"] = filePath.split('/').reverse()[0]
515 attachment["filePath"] = filePath
516 attachments.append(attachment)
517 textEntry.forceActiveFocus()
518 }
519 }
520
521 flickable: null477 flickable: null
522478
523 property bool isReady: false479 property bool isReady: false
@@ -560,7 +516,7 @@
560 }516 }
561 }517 }
562 }518 }
563 addAttachmentsToModel(sharedAttachmentsTransfer)519 composeBar.addAttachments(sharedAttachmentsTransfer)
564 }520 }
565521
566 onActiveChanged: {522 onActiveChanged: {
@@ -642,30 +598,6 @@
642 }598 }
643599
644 Component {600 Component {
645 id: attachmentPopover
646
647 Popover {
648 id: popover
649 Column {
650 id: containerLayout
651 anchors {
652 left: parent.left
653 top: parent.top
654 right: parent.right
655 }
656 ListItem.Standard {
657 text: i18n.tr("Remove")
658 onClicked: {
659 attachments.remove(activeAttachmentIndex)
660 PopupUtils.close(popover)
661 }
662 }
663 }
664 Component.onDestruction: activeAttachmentIndex = -1
665 }
666 }
667
668 Component {
669 id: participantsPopover601 id: participantsPopover
670602
671 Popover {603 Popover {
@@ -748,7 +680,7 @@
748 topMargin: units.gu(2)680 topMargin: units.gu(2)
749 left: parent.left681 left: parent.left
750 right: parent.right682 right: parent.right
751 bottom: bottomPanel.top683 bottom: composeBar.top
752 }684 }
753 z: 1685 z: 1
754 Behavior on height {686 Behavior on height {
@@ -1029,386 +961,62 @@
1029 top: screenTop.bottom961 top: screenTop.bottom
1030 left: parent.left962 left: parent.left
1031 right: parent.right963 right: parent.right
1032 bottom: bottomPanel.top964 bottom: composeBar.top
1033 }965 }
1034 }966 }
1035967
1036 Item {968 ComposeBar {
1037 id: bottomPanel969 id: composeBar
1038 property int defaultHeight: textEntry.height + units.gu(2)970 anchors {
1039 anchors.bottom: isSearching ? parent.bottom : keyboard.top971 bottom: isSearching ? parent.bottom : keyboard.top
1040 anchors.left: parent.left972 left: parent.left
1041 anchors.right: parent.right973 right: parent.right
1042 height: {974 }
1043 if (selectionMode || (participants.length > 0 && !contactWatcher.interactive)) {975
1044 return 0976 showContents: !selectionMode && !isSearching
1045 } else {977 maxHeight: messages.height - keyboard.height - screenTop.y
1046 if (messages.height - keyboard.height - screenTop.y > defaultHeight) {978 text: messages.text
1047 return defaultHeight979 canSend: participants.length > 0 || multiRecipient.recipientCount > 0 || multiRecipient.searchString !== ""
1048 } else {980
1049 return messages.height - keyboard.height - screenTop.y981 Component.onCompleted: {
1050 }982 // if page is active, it means this is not a bottom edge page
1051 }983 if (messages.active && messages.keyboardFocus && participants.length != 0) {
1052 }984 forceFocus()
1053 visible: !selectionMode && !isSearching985 }
1054 clip: true986 }
1055 MouseArea {987
1056 anchors.fill: parent988 onSendRequested: {
1057 onClicked: {989 // refresh the recipient list
1058 messageTextArea.forceActiveFocus()990 multiRecipient.focus = false
1059 }991
1060 }992 if (messages.account && messages.accountId == "") {
1061993 messages.accountId = messages.account.accountId
1062 Behavior on height {994 messages.head.sections.selectedIndex = Qt.binding(getSelectedIndex)
1063 UbuntuNumberAnimation { }995 }
1064 }996
1065997 var newAttachments = []
1066 ListItem.ThinDivider {998 for (var i = 0; i < attachments.count; i++) {
1067 anchors.top: parent.top999 var attachment = []
1068 }1000 var item = attachments.get(i)
10691001 // we dont include smil files. they will be auto generated
1070 Icon {1002 if (item.contentType.toLowerCase() === "application/smil") {
1071 id: attachButton1003 continue
1072 objectName: "attachButton"1004 }
1073 anchors.left: parent.left1005 attachment.push(item.name)
1074 anchors.leftMargin: units.gu(2)1006 attachment.push(item.contentType)
1075 anchors.verticalCenter: sendButton.verticalCenter1007 attachment.push(item.filePath)
1076 height: units.gu(3)1008 newAttachments.push(attachment)
1077 width: units.gu(3)1009 }
1078 color: "gray"1010
1079 name: "camera-app-symbolic"1011 var recipients = participantIds.length > 0 ? participantIds :
1080 MouseArea {1012 multiRecipient.recipients
1081 anchors.fill: parent1013 // if sendMessage succeeds it means the message was either sent or
1082 anchors.margins: units.gu(-2)1014 // injected into the history service so the user can retry later
1083 onClicked: {1015 if (sendMessage(text, recipients, newAttachments)) {
1084 Qt.inputMethod.hide()1016 composeBar.reset()
1085 pictureImporter.requestNewPicture()1017 }
1086 }1018 if (eventModel.filter == null) {
1087 }1019 reloadFilters = !reloadFilters
1088 }
1089
1090 StyledItem {
1091 id: textEntry
1092 property alias text: messageTextArea.text
1093 property alias inputMethodComposing: messageTextArea.inputMethodComposing
1094 property int fullSize: attachmentThumbnails.height + messageTextArea.height
1095 style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry)
1096 anchors.bottomMargin: units.gu(1)
1097 anchors.bottom: parent.bottom
1098 anchors.left: attachButton.right
1099 anchors.leftMargin: units.gu(1)
1100 anchors.right: sendButton.left
1101 anchors.rightMargin: units.gu(1)
1102 height: attachments.count !== 0 ? fullSize + units.gu(1.5) : fullSize
1103 onActiveFocusChanged: {
1104 if(activeFocus) {
1105 messageTextArea.forceActiveFocus()
1106 } else {
1107 focus = false
1108 }
1109 }
1110 focus: false
1111 MouseArea {
1112 anchors.fill: parent
1113 onClicked: messageTextArea.forceActiveFocus()
1114 }
1115 Flow {
1116 id: attachmentThumbnails
1117 spacing: units.gu(1)
1118 anchors{
1119 left: parent.left
1120 right: parent.right
1121 top: parent.top
1122 topMargin: units.gu(1)
1123 leftMargin: units.gu(1)
1124 rightMargin: units.gu(1)
1125 }
1126 height: childrenRect.height
1127
1128 Component {
1129 id: thumbnailImage
1130 UbuntuShape {
1131 property int index
1132 property string filePath
1133
1134 width: childrenRect.width
1135 height: childrenRect.height
1136
1137 image: Image {
1138 id: avatarImage
1139 width: units.gu(8)
1140 height: units.gu(8)
1141 sourceSize.height: height
1142 sourceSize.width: width
1143 fillMode: Image.PreserveAspectCrop
1144 source: filePath
1145 asynchronous: true
1146 }
1147 MouseArea {
1148 anchors.fill: parent
1149 onPressAndHold: {
1150 mouse.accept = true
1151 Qt.inputMethod.hide()
1152 activeAttachmentIndex = index
1153 PopupUtils.open(attachmentPopover, parent)
1154 }
1155 }
1156 }
1157 }
1158
1159 Component {
1160 id: thumbnailContact
1161 Item {
1162 id: attachment
1163
1164 readonly property int contactsCount:vcardParser.contacts ? vcardParser.contacts.length : 0
1165 property int index
1166 property string filePath
1167 property alias vcard: vcardParser
1168 property string contactDisplayName: {
1169 if (contactsCount > 0) {
1170 var contact = vcard.contacts[0]
1171 if (contact.displayLabel.label && (contact.displayLabel.label != "")) {
1172 return contact.displayLabel.label
1173 } else if (contact.name) {
1174 var contacFullName = contact.name.firstName
1175 if (contact.name.midleName) {
1176 contacFullName += " " + contact.name.midleName
1177 }
1178 if (contact.name.lastName) {
1179 contacFullName += " " + contact.name.lastName
1180 }
1181 return contacFullName
1182 }
1183 return i18n.tr("Unknown contact")
1184 }
1185 return ""
1186 }
1187 property string title: {
1188 var result = attachment.contactDisplayName
1189 if (attachment.contactsCount > 1) {
1190 return result + " (+%1)".arg(attachment.contactsCount-1)
1191 } else {
1192 return result
1193 }
1194 }
1195
1196 height: units.gu(6)
1197 width: textEntry.width
1198
1199 ContactAvatar {
1200 id: avatar
1201
1202 anchors {
1203 top: parent.top
1204 bottom: parent.bottom
1205 left: parent.left
1206 }
1207 contactElement: attachment.contactsCount === 1 ? attachment.vcard.contacts[0] : null
1208 fallbackAvatarUrl: attachment.contactsCount === 1 ? "image://theme/contact" : "image://theme/contact-group"
1209 fallbackDisplayName: attachment.contactsCount === 1 ? attachment.contactDisplayName : ""
1210 width: height
1211 }
1212 Label {
1213 id: label
1214
1215 anchors {
1216 left: avatar.right
1217 leftMargin: units.gu(1)
1218 top: avatar.top
1219 bottom: avatar.bottom
1220 right: parent.right
1221 rightMargin: units.gu(1)
1222 }
1223
1224 verticalAlignment: Text.AlignVCenter
1225 text: attachment.title
1226 elide: Text.ElideMiddle
1227 color: UbuntuColors.lightAubergine
1228 }
1229 MouseArea {
1230 anchors.fill: parent
1231 onPressAndHold: {
1232 mouse.accept = true
1233 Qt.inputMethod.hide()
1234 activeAttachmentIndex = index
1235 PopupUtils.open(attachmentPopover, parent)
1236 }
1237 }
1238 VCardParser {
1239 id: vcardParser
1240
1241 vCardUrl: attachment ? Qt.resolvedUrl(attachment.filePath) : ""
1242 }
1243 }
1244 }
1245
1246 Component {
1247 id: thumbnailUnknown
1248
1249 UbuntuShape {
1250 property int index
1251 property string filePath
1252
1253 width: units.gu(8)
1254 height: units.gu(8)
1255
1256 Icon {
1257 anchors.centerIn: parent
1258 width: units.gu(6)
1259 height: units.gu(6)
1260 name: "attachment"
1261 }
1262 MouseArea {
1263 anchors.fill: parent
1264 onPressAndHold: {
1265 mouse.accept = true
1266 Qt.inputMethod.hide()
1267 activeAttachmentIndex = index
1268 PopupUtils.open(attachmentPopover, parent)
1269 }
1270 }
1271 }
1272 }
1273
1274 Repeater {
1275 model: attachments
1276 delegate: Loader {
1277 height: units.gu(8)
1278 sourceComponent: {
1279 var contentType = getContentType(filePath)
1280 console.log(contentType)
1281 switch(contentType) {
1282 case ContentType.Contacts:
1283 return thumbnailContact
1284 case ContentType.Pictures:
1285 return thumbnailImage
1286 case ContentType.Unknown:
1287 return thumbnailUnknown
1288 default:
1289 console.log("unknown content Type")
1290 }
1291 }
1292 onStatusChanged: {
1293 if (status == Loader.Ready) {
1294 item.index = index
1295 item.filePath = filePath
1296 }
1297 }
1298 }
1299 }
1300 }
1301
1302 ListItem.ThinDivider {
1303 id: divider
1304
1305 anchors {
1306 left: parent.left
1307 right: parent.right
1308 top: attachmentThumbnails.bottom
1309 margins: units.gu(0.5)
1310 }
1311 visible: attachments.count > 0
1312 }
1313
1314 TextArea {
1315 id: messageTextArea
1316 objectName: "messageTextArea"
1317 anchors {
1318 top: attachments.count == 0 ? textEntry.top : attachmentThumbnails.bottom
1319 left: parent.left
1320 right: parent.right
1321 }
1322 // this value is to avoid letter being cut off
1323 height: units.gu(4.3)
1324 style: LocalTextAreaStyle {}
1325 autoSize: true
1326 maximumLineCount: attachments.count == 0 ? 8 : 4
1327 placeholderText: i18n.tr("Write a message...")
1328 focus: textEntry.focus
1329 font.family: "Ubuntu"
1330 font.pixelSize: FontUtils.sizeToPixels("medium")
1331 color: "#5d5d5d"
1332 text: messages.text
1333 }
1334
1335 /*InverseMouseArea {
1336 anchors.fill: parent
1337 visible: textEntry.activeFocus
1338 onClicked: {
1339 textEntry.focus = false;
1340 }
1341 }*/
1342 Component.onCompleted: {
1343 // if page is active, it means this is not a bottom edge page
1344 if (messages.active && messages.keyboardFocus && participants.length != 0) {
1345 messageTextArea.forceActiveFocus()
1346 }
1347 }
1348 }
1349
1350 Icon {
1351 id: sendButton
1352 objectName: "sendButton"
1353 anchors.verticalCenter: textEntry.verticalCenter
1354 anchors.right: parent.right
1355 anchors.rightMargin: units.gu(2)
1356 color: "gray"
1357 source: Qt.resolvedUrl("./assets/send.svg")
1358 width: units.gu(3)
1359 height: units.gu(3)
1360 enabled: {
1361 if (participants.length > 0 || multiRecipient.recipientCount > 0 || multiRecipient.searchString !== "") {
1362 if (textEntry.text != "" || textEntry.inputMethodComposing || attachments.count > 0) {
1363 return true
1364 }
1365 }
1366 return false
1367 }
1368
1369 MouseArea {
1370 anchors.fill: parent
1371 anchors.margins: units.gu(-2)
1372 onClicked: {
1373 // make sure we flush everything we have prepared in the OSK preedit
1374 Qt.inputMethod.commit();
1375 if (textEntry.text == "" && attachments.count == 0) {
1376 return
1377 }
1378 // refresh the recipient list
1379 multiRecipient.focus = false
1380
1381 if (messages.account && messages.accountId == "") {
1382 messages.accountId = messages.account.accountId
1383 messages.head.sections.selectedIndex = Qt.binding(getSelectedIndex)
1384 }
1385
1386 var newAttachments = []
1387 for (var i = 0; i < attachments.count; i++) {
1388 var attachment = []
1389 var item = attachments.get(i)
1390 // we dont include smil files. they will be auto generated
1391 if (item.contentType.toLowerCase() === "application/smil") {
1392 continue
1393 }
1394 attachment.push(item.name)
1395 attachment.push(item.contentType)
1396 attachment.push(item.filePath)
1397 newAttachments.push(attachment)
1398 }
1399
1400 var recipients = participantIds.length > 0 ? participantIds :
1401 multiRecipient.recipients
1402 // if sendMessage succeeds it means the message was either sent or
1403 // injected into the history service so the user can retry later
1404 if (sendMessage(textEntry.text, recipients, newAttachments)) {
1405 textEntry.text = ""
1406 attachments.clear()
1407 }
1408 if (eventModel.filter == null) {
1409 reloadFilters = !reloadFilters
1410 }
1411 }
1412 }1020 }
1413 }1021 }
1414 }1022 }
14151023
=== modified file 'src/qml/MessagesHeader.qml'
--- src/qml/MessagesHeader.qml 2015-08-04 01:06:06 +0000
+++ src/qml/MessagesHeader.qml 2015-12-08 17:14:16 +0000
@@ -18,7 +18,7 @@
1818
1919
20import QtQuick 2.220import QtQuick 2.2
21import Ubuntu.Components 1.121import Ubuntu.Components 1.3
2222
23Item {23Item {
24 id: header24 id: header
2525
=== added file 'src/qml/ThumbnailContact.qml'
--- src/qml/ThumbnailContact.qml 1970-01-01 00:00:00 +0000
+++ src/qml/ThumbnailContact.qml 2015-12-08 17:14:16 +0000
@@ -0,0 +1,106 @@
1/*
2 * Copyright 2012-2015 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 1.3
21import Ubuntu.Contacts 0.1
22
23Item {
24 id: attachment
25
26 readonly property int contactsCount:vcardParser.contacts ? vcardParser.contacts.length : 0
27 property int index
28 property string filePath
29 property alias vcard: vcardParser
30 property string contactDisplayName: {
31 if (contactsCount > 0) {
32 var contact = vcard.contacts[0]
33 if (contact.displayLabel.label && (contact.displayLabel.label != "")) {
34 return contact.displayLabel.label
35 } else if (contact.name) {
36 var contacFullName = contact.name.firstName
37 if (contact.name.midleName) {
38 contacFullName += " " + contact.name.midleName
39 }
40 if (contact.name.lastName) {
41 contacFullName += " " + contact.name.lastName
42 }
43 return contacFullName
44 }
45 return i18n.tr("Unknown contact")
46 }
47 return ""
48 }
49 property string title: {
50 var result = attachment.contactDisplayName
51 if (attachment.contactsCount > 1) {
52 return result + " (+%1)".arg(attachment.contactsCount-1)
53 } else {
54 return result
55 }
56 }
57
58 signal pressAndHold()
59
60 height: units.gu(6)
61 width: textEntry.width
62
63 ContactAvatar {
64 id: avatar
65
66 anchors {
67 top: parent.top
68 bottom: parent.bottom
69 left: parent.left
70 }
71 contactElement: attachment.contactsCount === 1 ? attachment.vcard.contacts[0] : null
72 fallbackAvatarUrl: attachment.contactsCount === 1 ? "image://theme/contact" : "image://theme/contact-group"
73 fallbackDisplayName: attachment.contactsCount === 1 ? attachment.contactDisplayName : ""
74 width: height
75 }
76 Label {
77 id: label
78
79 anchors {
80 left: avatar.right
81 leftMargin: units.gu(1)
82 top: avatar.top
83 bottom: avatar.bottom
84 right: parent.right
85 rightMargin: units.gu(1)
86 }
87
88 verticalAlignment: Text.AlignVCenter
89 text: attachment.title
90 elide: Text.ElideMiddle
91 color: UbuntuColors.lightAubergine
92 }
93 MouseArea {
94 anchors.fill: parent
95 onPressAndHold: {
96 mouse.accept = true
97 attachment.pressAndHold()
98 }
99 }
100 VCardParser {
101 id: vcardParser
102
103 vCardUrl: attachment ? Qt.resolvedUrl(attachment.filePath) : ""
104 }
105}
106
0107
=== added file 'src/qml/ThumbnailImage.qml'
--- src/qml/ThumbnailImage.qml 1970-01-01 00:00:00 +0000
+++ src/qml/ThumbnailImage.qml 2015-12-08 17:14:16 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright 2012-2015 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 1.3
21
22UbuntuShape {
23 id: thumbnail
24 property int index
25 property string filePath
26
27 signal pressAndHold()
28
29 width: childrenRect.width
30 height: childrenRect.height
31
32 image: Image {
33 id: avatarImage
34 width: units.gu(8)
35 height: units.gu(8)
36 sourceSize.height: height
37 sourceSize.width: width
38 fillMode: Image.PreserveAspectCrop
39 source: filePath
40 asynchronous: true
41 }
42 MouseArea {
43 anchors.fill: parent
44 onPressAndHold: {
45 mouse.accept = true
46 thumbnail.pressAndHold()
47 }
48 }
49}
050
=== added file 'src/qml/ThumbnailUnknown.qml'
--- src/qml/ThumbnailUnknown.qml 1970-01-01 00:00:00 +0000
+++ src/qml/ThumbnailUnknown.qml 2015-12-08 17:14:16 +0000
@@ -0,0 +1,45 @@
1/*
2 * Copyright 2012-2015 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 1.3
21
22UbuntuShape {
23 id: thumbnail
24 property int index
25 property string filePath
26
27 signal pressAndHold()
28
29 width: units.gu(8)
30 height: units.gu(8)
31
32 Icon {
33 anchors.centerIn: parent
34 width: units.gu(6)
35 height: units.gu(6)
36 name: "attachment"
37 }
38 MouseArea {
39 anchors.fill: parent
40 onPressAndHold: {
41 mouse.accept = true
42 thumbnail.pressAndHold()
43 }
44 }
45}
046
=== added file 'src/qml/TransparentButton.qml'
--- src/qml/TransparentButton.qml 1970-01-01 00:00:00 +0000
+++ src/qml/TransparentButton.qml 2015-12-08 17:14:16 +0000
@@ -0,0 +1,86 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This file is part of messaging-app.
5 *
6 * messaging-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * messaging-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.0
20import Ubuntu.Components 1.3
21
22Item {
23 id: button
24
25 width: icon.width
26 height: icon.height + label.height + spacing
27
28 property alias iconName: icon.name
29 property alias iconSource: icon.source
30 property alias iconColor: icon.color
31 property int iconSize: units.gu(2)
32 property alias iconRotation: icon.rotation
33 property alias text: label.text
34 property alias textSize: label.font.pixelSize
35 property int spacing: 0
36
37 signal clicked()
38 signal pressed()
39 signal released()
40
41 Icon {
42 id: icon
43
44 anchors {
45 left: parent.left
46 right: parent.right
47 top: parent.top
48 }
49
50 height: iconSize
51 width: iconSize
52 color: "gray"
53 Behavior on rotation {
54 UbuntuNumberAnimation { }
55 }
56 }
57
58 MouseArea {
59 anchors {
60 fill: parent
61 margins: units.gu(-2)
62 }
63 onClicked: {
64 mouse.accepted = true
65 button.clicked()
66 }
67
68 onPressed: button.pressed()
69 onReleased: button.released()
70 }
71
72 Text {
73 id: label
74 color: "gray"
75 height: text !== "" ? paintedHeight : 0
76 anchors {
77 left: parent.left
78 right: parent.right
79 bottom: parent.bottom
80 }
81 horizontalAlignment: Text.AlignHCenter
82 verticalAlignment: Text.AlignBottom
83 font.family: "Ubuntu"
84 font.pixelSize: FontUtils.sizeToPixels("small")
85 }
86}

Subscribers

People subscribed via source and target branches