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
1=== added file 'src/qml/ComposeBar.qml'
2--- src/qml/ComposeBar.qml 1970-01-01 00:00:00 +0000
3+++ src/qml/ComposeBar.qml 2015-12-08 17:14:16 +0000
4@@ -0,0 +1,312 @@
5+/*
6+ * Copyright 2012-2015 Canonical Ltd.
7+ *
8+ * This file is part of messaging-app.
9+ *
10+ * messaging-app is free software; you can redistribute it and/or modify
11+ * it under the terms of the GNU General Public License as published by
12+ * the Free Software Foundation; version 3.
13+ *
14+ * messaging-app is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
21+ */
22+
23+import QtQuick 2.0
24+import Ubuntu.Components 1.3
25+import Ubuntu.Components.ListItems 1.3 as ListItem
26+import Ubuntu.Components.Popups 1.3
27+import Ubuntu.Content 0.1
28+import Ubuntu.Telephony 0.1
29+
30+Item {
31+ id: composeBar
32+
33+ property bool showContents: true
34+ property int maxHeight: textEntry.height + units.gu(2)
35+ property variant attachments: []
36+ property bool canSend: true
37+ property alias text: messageTextArea.text
38+
39+ signal sendRequested(string text, var attachments)
40+
41+ // internal properties
42+ property int _activeAttachmentIndex: -1
43+ property int _defaultHeight: textEntry.height + units.gu(2)
44+
45+ function forceFocus() {
46+ messageTextArea.forceActiveFocus()
47+ }
48+
49+ function reset() {
50+ textEntry.text = ""
51+ attachments.clear()
52+ }
53+
54+ function addAttachments(transfer) {
55+ for (var i = 0; i < transfer.items.length; i++) {
56+ if (String(transfer.items[i].text).length > 0) {
57+ composeBar.text = String(transfer.items[i].text)
58+ continue
59+ }
60+ var attachment = {}
61+ if (!startsWith(String(transfer.items[i].url),"file://")) {
62+ composeBar.text = String(transfer.items[i].url)
63+ continue
64+ }
65+ var filePath = String(transfer.items[i].url).replace('file://', '')
66+ // get only the basename
67+ attachment["contentType"] = application.fileMimeType(filePath)
68+ if (startsWith(attachment["contentType"], "text/vcard") ||
69+ startsWith(attachment["contentType"], "text/x-vcard")) {
70+ attachment["name"] = "contact.vcf"
71+ } else {
72+ attachment["name"] = filePath.split('/').reverse()[0]
73+ }
74+ attachment["filePath"] = filePath
75+ attachments.append(attachment)
76+ }
77+ }
78+
79+ function formattedTime(time) {
80+ var d = new Date(0, 0, 0, 0, 0, time)
81+ return d.getHours() == 0 ? Qt.formatTime(d, "mm:ss") : Qt.formatTime(d, "h:mm:ss")
82+ }
83+
84+ anchors.bottom: isSearching ? parent.bottom : keyboard.top
85+ anchors.left: parent.left
86+ anchors.right: parent.right
87+ height: showContents ? Math.min(_defaultHeight, maxHeight) : 0
88+ visible: showContents
89+ clip: true
90+
91+ Behavior on height {
92+ UbuntuNumberAnimation { }
93+ }
94+
95+ MouseArea {
96+ anchors.fill: parent
97+ onClicked: {
98+ forceFocus()
99+ }
100+ }
101+
102+ ListModel {
103+ id: attachments
104+ }
105+
106+ Component {
107+ id: attachmentPopover
108+
109+ Popover {
110+ id: popover
111+ Column {
112+ id: containerLayout
113+ anchors {
114+ left: parent.left
115+ top: parent.top
116+ right: parent.right
117+ }
118+ ListItem.Standard {
119+ text: i18n.tr("Remove")
120+ onClicked: {
121+ attachments.remove(_activeAttachmentIndex)
122+ PopupUtils.close(popover)
123+ }
124+ }
125+ }
126+ Component.onDestruction: _activeAttachmentIndex = -1
127+ }
128+ }
129+
130+ ListItem.ThinDivider {
131+ anchors.top: parent.top
132+ }
133+
134+ Row {
135+ id: leftSideActions
136+
137+ width: childrenRect.width
138+ height: childrenRect.height
139+
140+ anchors {
141+ left: parent.left
142+ leftMargin: units.gu(2)
143+ verticalCenter: sendButton.verticalCenter
144+ }
145+ spacing: units.gu(2)
146+
147+ PictureImport {
148+ id: pictureImporter
149+
150+ onPictureReceived: {
151+ var attachment = {}
152+ var filePath = String(pictureUrl).replace('file://', '')
153+ attachment["contentType"] = application.fileMimeType(filePath)
154+ attachment["name"] = filePath.split('/').reverse()[0]
155+ attachment["filePath"] = filePath
156+ attachments.append(attachment)
157+ textEntry.forceActiveFocus()
158+ }
159+ }
160+
161+ TransparentButton {
162+ id: attachButton
163+ objectName: "attachButton"
164+ iconName: "camera-app-symbolic"
165+ onClicked: {
166+ Qt.inputMethod.hide()
167+ pictureImporter.requestNewPicture()
168+ }
169+ }
170+ }
171+
172+ StyledItem {
173+ id: textEntry
174+ property alias text: messageTextArea.text
175+ property alias inputMethodComposing: messageTextArea.inputMethodComposing
176+ property int fullSize: attachmentThumbnails.height + messageTextArea.height
177+ style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry)
178+ anchors {
179+ topMargin: units.gu(1)
180+ top: parent.top
181+ left: leftSideActions.right
182+ leftMargin: units.gu(2)
183+ right: sendButton.left
184+ rightMargin: units.gu(2)
185+ }
186+ height: attachments.count !== 0 ? fullSize + units.gu(1.5) : fullSize
187+ onActiveFocusChanged: {
188+ if(activeFocus) {
189+ messageTextArea.forceActiveFocus()
190+ } else {
191+ focus = false
192+ }
193+ }
194+ focus: false
195+ MouseArea {
196+ anchors.fill: parent
197+ onClicked: forceFocus()
198+ }
199+ Flow {
200+ id: attachmentThumbnails
201+ spacing: units.gu(1)
202+ anchors{
203+ left: parent.left
204+ right: parent.right
205+ top: parent.top
206+ topMargin: units.gu(1)
207+ leftMargin: units.gu(1)
208+ rightMargin: units.gu(1)
209+ }
210+ height: childrenRect.height
211+
212+ Repeater {
213+ model: attachments
214+ delegate: Loader {
215+ id: loader
216+ height: units.gu(8)
217+ source: {
218+ var contentType = getContentType(filePath)
219+ console.log(contentType)
220+ switch(contentType) {
221+ case ContentType.Contacts:
222+ return Qt.resolvedUrl("ThumbnailContact.qml")
223+ case ContentType.Pictures:
224+ return Qt.resolvedUrl("ThumbnailImage.qml")
225+ case ContentType.Unknown:
226+ return Qt.resolvedUrl("ThumbnailUnknown.qml")
227+ default:
228+ console.log("unknown content Type")
229+ }
230+ }
231+ onStatusChanged: {
232+ if (status == Loader.Ready) {
233+ item.index = index
234+ item.filePath = filePath
235+ }
236+ }
237+
238+ Connections {
239+ target: loader.status == Loader.Ready ? loader.item : null
240+ ignoreUnknownSignals: true
241+ onPressAndHold: {
242+ Qt.inputMethod.hide()
243+ _activeAttachmentIndex = target.index
244+ PopupUtils.open(attachmentPopover, parent)
245+ }
246+ }
247+ }
248+ }
249+ }
250+
251+ ListItem.ThinDivider {
252+ id: divider
253+
254+ anchors {
255+ left: parent.left
256+ right: parent.right
257+ top: attachmentThumbnails.bottom
258+ margins: units.gu(0.5)
259+ }
260+ visible: attachments.count > 0
261+ }
262+
263+ TextArea {
264+ id: messageTextArea
265+ objectName: "messageTextArea"
266+ anchors {
267+ top: attachments.count == 0 ? textEntry.top : attachmentThumbnails.bottom
268+ left: parent.left
269+ right: parent.right
270+ }
271+ // this value is to avoid letter being cut off
272+ height: units.gu(4.3)
273+ style: LocalTextAreaStyle {}
274+ autoSize: true
275+ maximumLineCount: attachments.count == 0 ? 8 : 4
276+ placeholderText: {
277+ if (telepathyHelper.ready) {
278+ var account = telepathyHelper.accountForId(presenceRequest.accountId)
279+ if (account &&
280+ (presenceRequest.type != PresenceRequest.PresenceTypeUnknown &&
281+ presenceRequest.type != PresenceRequest.PresenceTypeUnset) &&
282+ account.protocolInfo.serviceName !== "") {
283+ console.log(presenceRequest.accountId)
284+ console.log(presenceRequest.type)
285+ return account.protocolInfo.serviceName
286+ }
287+ }
288+ return i18n.tr("Write a message...")
289+ }
290+ focus: textEntry.focus
291+ font.family: "Ubuntu"
292+ font.pixelSize: FontUtils.sizeToPixels("medium")
293+ color: "#5d5d5d"
294+ }
295+ }
296+
297+ TransparentButton {
298+ id: sendButton
299+ objectName: "sendButton"
300+ anchors.verticalCenter: textEntry.verticalCenter
301+ anchors.right: parent.right
302+ anchors.rightMargin: units.gu(2)
303+ iconSource: Qt.resolvedUrl("./assets/send.svg")
304+ enabled: (canSend && (textEntry.text != "" || textEntry.inputMethodComposing || attachments.count > 0))
305+
306+ onClicked: {
307+ // make sure we flush everything we have prepared in the OSK preedit
308+ Qt.inputMethod.commit();
309+ if (textEntry.text == "" && attachments.count == 0) {
310+ return
311+ }
312+
313+ composeBar.sendRequested(textEntry.text, attachments)
314+ }
315+ }
316+}
317
318=== modified file 'src/qml/Messages.qml'
319--- src/qml/Messages.qml 2015-12-07 17:55:17 +0000
320+++ src/qml/Messages.qml 2015-12-08 17:14:16 +0000
321@@ -1,5 +1,5 @@
322 /*
323- * Copyright 2012, 2013, 2014 Canonical Ltd.
324+ * Copyright 2012-2015 Canonical Ltd.
325 *
326 * This file is part of messaging-app.
327 *
328@@ -272,32 +272,6 @@
329 sections.selectedIndex: getSelectedIndex()
330 }
331
332-
333- function addAttachmentsToModel(transfer) {
334- for (var i in transfer.items) {
335- if (String(transfer.items[i].text).length > 0) {
336- messages.text = String(transfer.items[i].text)
337- continue
338- }
339- var attachment = {}
340- if (!startsWith(String(transfer.items[i].url),"file://")) {
341- messages.text = String(transfer.items[i].url)
342- continue
343- }
344- var filePath = String(transfer.items[i].url).replace('file://', '')
345- // get only the basename
346- attachment["contentType"] = application.fileMimeType(filePath)
347- if (startsWith(attachment["contentType"], "text/vcard") ||
348- startsWith(attachment["contentType"], "text/x-vcard")) {
349- attachment["name"] = "contact.vcf"
350- } else {
351- attachment["name"] = filePath.split('/').reverse()[0]
352- }
353- attachment["filePath"] = filePath
354- attachments.append(attachment)
355- }
356- }
357-
358 function sendMessageNetworkCheck() {
359 if (messages.account.simLocked) {
360 Qt.inputMethod.hide()
361@@ -500,24 +474,6 @@
362 visible: running
363 }
364
365- ListModel {
366- id: attachments
367- }
368-
369- PictureImport {
370- id: pictureImporter
371-
372- onPictureReceived: {
373- var attachment = {}
374- var filePath = String(pictureUrl).replace('file://', '')
375- attachment["contentType"] = application.fileMimeType(filePath)
376- attachment["name"] = filePath.split('/').reverse()[0]
377- attachment["filePath"] = filePath
378- attachments.append(attachment)
379- textEntry.forceActiveFocus()
380- }
381- }
382-
383 flickable: null
384
385 property bool isReady: false
386@@ -560,7 +516,7 @@
387 }
388 }
389 }
390- addAttachmentsToModel(sharedAttachmentsTransfer)
391+ composeBar.addAttachments(sharedAttachmentsTransfer)
392 }
393
394 onActiveChanged: {
395@@ -642,30 +598,6 @@
396 }
397
398 Component {
399- id: attachmentPopover
400-
401- Popover {
402- id: popover
403- Column {
404- id: containerLayout
405- anchors {
406- left: parent.left
407- top: parent.top
408- right: parent.right
409- }
410- ListItem.Standard {
411- text: i18n.tr("Remove")
412- onClicked: {
413- attachments.remove(activeAttachmentIndex)
414- PopupUtils.close(popover)
415- }
416- }
417- }
418- Component.onDestruction: activeAttachmentIndex = -1
419- }
420- }
421-
422- Component {
423 id: participantsPopover
424
425 Popover {
426@@ -748,7 +680,7 @@
427 topMargin: units.gu(2)
428 left: parent.left
429 right: parent.right
430- bottom: bottomPanel.top
431+ bottom: composeBar.top
432 }
433 z: 1
434 Behavior on height {
435@@ -1029,386 +961,62 @@
436 top: screenTop.bottom
437 left: parent.left
438 right: parent.right
439- bottom: bottomPanel.top
440+ bottom: composeBar.top
441 }
442 }
443
444- Item {
445- id: bottomPanel
446- property int defaultHeight: textEntry.height + units.gu(2)
447- anchors.bottom: isSearching ? parent.bottom : keyboard.top
448- anchors.left: parent.left
449- anchors.right: parent.right
450- height: {
451- if (selectionMode || (participants.length > 0 && !contactWatcher.interactive)) {
452- return 0
453- } else {
454- if (messages.height - keyboard.height - screenTop.y > defaultHeight) {
455- return defaultHeight
456- } else {
457- return messages.height - keyboard.height - screenTop.y
458- }
459- }
460- }
461- visible: !selectionMode && !isSearching
462- clip: true
463- MouseArea {
464- anchors.fill: parent
465- onClicked: {
466- messageTextArea.forceActiveFocus()
467- }
468- }
469-
470- Behavior on height {
471- UbuntuNumberAnimation { }
472- }
473-
474- ListItem.ThinDivider {
475- anchors.top: parent.top
476- }
477-
478- Icon {
479- id: attachButton
480- objectName: "attachButton"
481- anchors.left: parent.left
482- anchors.leftMargin: units.gu(2)
483- anchors.verticalCenter: sendButton.verticalCenter
484- height: units.gu(3)
485- width: units.gu(3)
486- color: "gray"
487- name: "camera-app-symbolic"
488- MouseArea {
489- anchors.fill: parent
490- anchors.margins: units.gu(-2)
491- onClicked: {
492- Qt.inputMethod.hide()
493- pictureImporter.requestNewPicture()
494- }
495- }
496- }
497-
498- StyledItem {
499- id: textEntry
500- property alias text: messageTextArea.text
501- property alias inputMethodComposing: messageTextArea.inputMethodComposing
502- property int fullSize: attachmentThumbnails.height + messageTextArea.height
503- style: Theme.createStyleComponent("TextAreaStyle.qml", textEntry)
504- anchors.bottomMargin: units.gu(1)
505- anchors.bottom: parent.bottom
506- anchors.left: attachButton.right
507- anchors.leftMargin: units.gu(1)
508- anchors.right: sendButton.left
509- anchors.rightMargin: units.gu(1)
510- height: attachments.count !== 0 ? fullSize + units.gu(1.5) : fullSize
511- onActiveFocusChanged: {
512- if(activeFocus) {
513- messageTextArea.forceActiveFocus()
514- } else {
515- focus = false
516- }
517- }
518- focus: false
519- MouseArea {
520- anchors.fill: parent
521- onClicked: messageTextArea.forceActiveFocus()
522- }
523- Flow {
524- id: attachmentThumbnails
525- spacing: units.gu(1)
526- anchors{
527- left: parent.left
528- right: parent.right
529- top: parent.top
530- topMargin: units.gu(1)
531- leftMargin: units.gu(1)
532- rightMargin: units.gu(1)
533- }
534- height: childrenRect.height
535-
536- Component {
537- id: thumbnailImage
538- UbuntuShape {
539- property int index
540- property string filePath
541-
542- width: childrenRect.width
543- height: childrenRect.height
544-
545- image: Image {
546- id: avatarImage
547- width: units.gu(8)
548- height: units.gu(8)
549- sourceSize.height: height
550- sourceSize.width: width
551- fillMode: Image.PreserveAspectCrop
552- source: filePath
553- asynchronous: true
554- }
555- MouseArea {
556- anchors.fill: parent
557- onPressAndHold: {
558- mouse.accept = true
559- Qt.inputMethod.hide()
560- activeAttachmentIndex = index
561- PopupUtils.open(attachmentPopover, parent)
562- }
563- }
564- }
565- }
566-
567- Component {
568- id: thumbnailContact
569- Item {
570- id: attachment
571-
572- readonly property int contactsCount:vcardParser.contacts ? vcardParser.contacts.length : 0
573- property int index
574- property string filePath
575- property alias vcard: vcardParser
576- property string contactDisplayName: {
577- if (contactsCount > 0) {
578- var contact = vcard.contacts[0]
579- if (contact.displayLabel.label && (contact.displayLabel.label != "")) {
580- return contact.displayLabel.label
581- } else if (contact.name) {
582- var contacFullName = contact.name.firstName
583- if (contact.name.midleName) {
584- contacFullName += " " + contact.name.midleName
585- }
586- if (contact.name.lastName) {
587- contacFullName += " " + contact.name.lastName
588- }
589- return contacFullName
590- }
591- return i18n.tr("Unknown contact")
592- }
593- return ""
594- }
595- property string title: {
596- var result = attachment.contactDisplayName
597- if (attachment.contactsCount > 1) {
598- return result + " (+%1)".arg(attachment.contactsCount-1)
599- } else {
600- return result
601- }
602- }
603-
604- height: units.gu(6)
605- width: textEntry.width
606-
607- ContactAvatar {
608- id: avatar
609-
610- anchors {
611- top: parent.top
612- bottom: parent.bottom
613- left: parent.left
614- }
615- contactElement: attachment.contactsCount === 1 ? attachment.vcard.contacts[0] : null
616- fallbackAvatarUrl: attachment.contactsCount === 1 ? "image://theme/contact" : "image://theme/contact-group"
617- fallbackDisplayName: attachment.contactsCount === 1 ? attachment.contactDisplayName : ""
618- width: height
619- }
620- Label {
621- id: label
622-
623- anchors {
624- left: avatar.right
625- leftMargin: units.gu(1)
626- top: avatar.top
627- bottom: avatar.bottom
628- right: parent.right
629- rightMargin: units.gu(1)
630- }
631-
632- verticalAlignment: Text.AlignVCenter
633- text: attachment.title
634- elide: Text.ElideMiddle
635- color: UbuntuColors.lightAubergine
636- }
637- MouseArea {
638- anchors.fill: parent
639- onPressAndHold: {
640- mouse.accept = true
641- Qt.inputMethod.hide()
642- activeAttachmentIndex = index
643- PopupUtils.open(attachmentPopover, parent)
644- }
645- }
646- VCardParser {
647- id: vcardParser
648-
649- vCardUrl: attachment ? Qt.resolvedUrl(attachment.filePath) : ""
650- }
651- }
652- }
653-
654- Component {
655- id: thumbnailUnknown
656-
657- UbuntuShape {
658- property int index
659- property string filePath
660-
661- width: units.gu(8)
662- height: units.gu(8)
663-
664- Icon {
665- anchors.centerIn: parent
666- width: units.gu(6)
667- height: units.gu(6)
668- name: "attachment"
669- }
670- MouseArea {
671- anchors.fill: parent
672- onPressAndHold: {
673- mouse.accept = true
674- Qt.inputMethod.hide()
675- activeAttachmentIndex = index
676- PopupUtils.open(attachmentPopover, parent)
677- }
678- }
679- }
680- }
681-
682- Repeater {
683- model: attachments
684- delegate: Loader {
685- height: units.gu(8)
686- sourceComponent: {
687- var contentType = getContentType(filePath)
688- console.log(contentType)
689- switch(contentType) {
690- case ContentType.Contacts:
691- return thumbnailContact
692- case ContentType.Pictures:
693- return thumbnailImage
694- case ContentType.Unknown:
695- return thumbnailUnknown
696- default:
697- console.log("unknown content Type")
698- }
699- }
700- onStatusChanged: {
701- if (status == Loader.Ready) {
702- item.index = index
703- item.filePath = filePath
704- }
705- }
706- }
707- }
708- }
709-
710- ListItem.ThinDivider {
711- id: divider
712-
713- anchors {
714- left: parent.left
715- right: parent.right
716- top: attachmentThumbnails.bottom
717- margins: units.gu(0.5)
718- }
719- visible: attachments.count > 0
720- }
721-
722- TextArea {
723- id: messageTextArea
724- objectName: "messageTextArea"
725- anchors {
726- top: attachments.count == 0 ? textEntry.top : attachmentThumbnails.bottom
727- left: parent.left
728- right: parent.right
729- }
730- // this value is to avoid letter being cut off
731- height: units.gu(4.3)
732- style: LocalTextAreaStyle {}
733- autoSize: true
734- maximumLineCount: attachments.count == 0 ? 8 : 4
735- placeholderText: i18n.tr("Write a message...")
736- focus: textEntry.focus
737- font.family: "Ubuntu"
738- font.pixelSize: FontUtils.sizeToPixels("medium")
739- color: "#5d5d5d"
740- text: messages.text
741- }
742-
743- /*InverseMouseArea {
744- anchors.fill: parent
745- visible: textEntry.activeFocus
746- onClicked: {
747- textEntry.focus = false;
748- }
749- }*/
750- Component.onCompleted: {
751- // if page is active, it means this is not a bottom edge page
752- if (messages.active && messages.keyboardFocus && participants.length != 0) {
753- messageTextArea.forceActiveFocus()
754- }
755- }
756- }
757-
758- Icon {
759- id: sendButton
760- objectName: "sendButton"
761- anchors.verticalCenter: textEntry.verticalCenter
762- anchors.right: parent.right
763- anchors.rightMargin: units.gu(2)
764- color: "gray"
765- source: Qt.resolvedUrl("./assets/send.svg")
766- width: units.gu(3)
767- height: units.gu(3)
768- enabled: {
769- if (participants.length > 0 || multiRecipient.recipientCount > 0 || multiRecipient.searchString !== "") {
770- if (textEntry.text != "" || textEntry.inputMethodComposing || attachments.count > 0) {
771- return true
772- }
773- }
774- return false
775- }
776-
777- MouseArea {
778- anchors.fill: parent
779- anchors.margins: units.gu(-2)
780- onClicked: {
781- // make sure we flush everything we have prepared in the OSK preedit
782- Qt.inputMethod.commit();
783- if (textEntry.text == "" && attachments.count == 0) {
784- return
785- }
786- // refresh the recipient list
787- multiRecipient.focus = false
788-
789- if (messages.account && messages.accountId == "") {
790- messages.accountId = messages.account.accountId
791- messages.head.sections.selectedIndex = Qt.binding(getSelectedIndex)
792- }
793-
794- var newAttachments = []
795- for (var i = 0; i < attachments.count; i++) {
796- var attachment = []
797- var item = attachments.get(i)
798- // we dont include smil files. they will be auto generated
799- if (item.contentType.toLowerCase() === "application/smil") {
800- continue
801- }
802- attachment.push(item.name)
803- attachment.push(item.contentType)
804- attachment.push(item.filePath)
805- newAttachments.push(attachment)
806- }
807-
808- var recipients = participantIds.length > 0 ? participantIds :
809- multiRecipient.recipients
810- // if sendMessage succeeds it means the message was either sent or
811- // injected into the history service so the user can retry later
812- if (sendMessage(textEntry.text, recipients, newAttachments)) {
813- textEntry.text = ""
814- attachments.clear()
815- }
816- if (eventModel.filter == null) {
817- reloadFilters = !reloadFilters
818- }
819- }
820+ ComposeBar {
821+ id: composeBar
822+ anchors {
823+ bottom: isSearching ? parent.bottom : keyboard.top
824+ left: parent.left
825+ right: parent.right
826+ }
827+
828+ showContents: !selectionMode && !isSearching
829+ maxHeight: messages.height - keyboard.height - screenTop.y
830+ text: messages.text
831+ canSend: participants.length > 0 || multiRecipient.recipientCount > 0 || multiRecipient.searchString !== ""
832+
833+ Component.onCompleted: {
834+ // if page is active, it means this is not a bottom edge page
835+ if (messages.active && messages.keyboardFocus && participants.length != 0) {
836+ forceFocus()
837+ }
838+ }
839+
840+ onSendRequested: {
841+ // refresh the recipient list
842+ multiRecipient.focus = false
843+
844+ if (messages.account && messages.accountId == "") {
845+ messages.accountId = messages.account.accountId
846+ messages.head.sections.selectedIndex = Qt.binding(getSelectedIndex)
847+ }
848+
849+ var newAttachments = []
850+ for (var i = 0; i < attachments.count; i++) {
851+ var attachment = []
852+ var item = attachments.get(i)
853+ // we dont include smil files. they will be auto generated
854+ if (item.contentType.toLowerCase() === "application/smil") {
855+ continue
856+ }
857+ attachment.push(item.name)
858+ attachment.push(item.contentType)
859+ attachment.push(item.filePath)
860+ newAttachments.push(attachment)
861+ }
862+
863+ var recipients = participantIds.length > 0 ? participantIds :
864+ multiRecipient.recipients
865+ // if sendMessage succeeds it means the message was either sent or
866+ // injected into the history service so the user can retry later
867+ if (sendMessage(text, recipients, newAttachments)) {
868+ composeBar.reset()
869+ }
870+ if (eventModel.filter == null) {
871+ reloadFilters = !reloadFilters
872 }
873 }
874 }
875
876=== modified file 'src/qml/MessagesHeader.qml'
877--- src/qml/MessagesHeader.qml 2015-08-04 01:06:06 +0000
878+++ src/qml/MessagesHeader.qml 2015-12-08 17:14:16 +0000
879@@ -18,7 +18,7 @@
880
881
882 import QtQuick 2.2
883-import Ubuntu.Components 1.1
884+import Ubuntu.Components 1.3
885
886 Item {
887 id: header
888
889=== added file 'src/qml/ThumbnailContact.qml'
890--- src/qml/ThumbnailContact.qml 1970-01-01 00:00:00 +0000
891+++ src/qml/ThumbnailContact.qml 2015-12-08 17:14:16 +0000
892@@ -0,0 +1,106 @@
893+/*
894+ * Copyright 2012-2015 Canonical Ltd.
895+ *
896+ * This file is part of messaging-app.
897+ *
898+ * messaging-app is free software; you can redistribute it and/or modify
899+ * it under the terms of the GNU General Public License as published by
900+ * the Free Software Foundation; version 3.
901+ *
902+ * messaging-app is distributed in the hope that it will be useful,
903+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
904+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
905+ * GNU General Public License for more details.
906+ *
907+ * You should have received a copy of the GNU General Public License
908+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
909+ */
910+
911+import QtQuick 2.0
912+import Ubuntu.Components 1.3
913+import Ubuntu.Contacts 0.1
914+
915+Item {
916+ id: attachment
917+
918+ readonly property int contactsCount:vcardParser.contacts ? vcardParser.contacts.length : 0
919+ property int index
920+ property string filePath
921+ property alias vcard: vcardParser
922+ property string contactDisplayName: {
923+ if (contactsCount > 0) {
924+ var contact = vcard.contacts[0]
925+ if (contact.displayLabel.label && (contact.displayLabel.label != "")) {
926+ return contact.displayLabel.label
927+ } else if (contact.name) {
928+ var contacFullName = contact.name.firstName
929+ if (contact.name.midleName) {
930+ contacFullName += " " + contact.name.midleName
931+ }
932+ if (contact.name.lastName) {
933+ contacFullName += " " + contact.name.lastName
934+ }
935+ return contacFullName
936+ }
937+ return i18n.tr("Unknown contact")
938+ }
939+ return ""
940+ }
941+ property string title: {
942+ var result = attachment.contactDisplayName
943+ if (attachment.contactsCount > 1) {
944+ return result + " (+%1)".arg(attachment.contactsCount-1)
945+ } else {
946+ return result
947+ }
948+ }
949+
950+ signal pressAndHold()
951+
952+ height: units.gu(6)
953+ width: textEntry.width
954+
955+ ContactAvatar {
956+ id: avatar
957+
958+ anchors {
959+ top: parent.top
960+ bottom: parent.bottom
961+ left: parent.left
962+ }
963+ contactElement: attachment.contactsCount === 1 ? attachment.vcard.contacts[0] : null
964+ fallbackAvatarUrl: attachment.contactsCount === 1 ? "image://theme/contact" : "image://theme/contact-group"
965+ fallbackDisplayName: attachment.contactsCount === 1 ? attachment.contactDisplayName : ""
966+ width: height
967+ }
968+ Label {
969+ id: label
970+
971+ anchors {
972+ left: avatar.right
973+ leftMargin: units.gu(1)
974+ top: avatar.top
975+ bottom: avatar.bottom
976+ right: parent.right
977+ rightMargin: units.gu(1)
978+ }
979+
980+ verticalAlignment: Text.AlignVCenter
981+ text: attachment.title
982+ elide: Text.ElideMiddle
983+ color: UbuntuColors.lightAubergine
984+ }
985+ MouseArea {
986+ anchors.fill: parent
987+ onPressAndHold: {
988+ mouse.accept = true
989+ attachment.pressAndHold()
990+ }
991+ }
992+ VCardParser {
993+ id: vcardParser
994+
995+ vCardUrl: attachment ? Qt.resolvedUrl(attachment.filePath) : ""
996+ }
997+}
998+
999
1000=== added file 'src/qml/ThumbnailImage.qml'
1001--- src/qml/ThumbnailImage.qml 1970-01-01 00:00:00 +0000
1002+++ src/qml/ThumbnailImage.qml 2015-12-08 17:14:16 +0000
1003@@ -0,0 +1,49 @@
1004+/*
1005+ * Copyright 2012-2015 Canonical Ltd.
1006+ *
1007+ * This file is part of messaging-app.
1008+ *
1009+ * messaging-app is free software; you can redistribute it and/or modify
1010+ * it under the terms of the GNU General Public License as published by
1011+ * the Free Software Foundation; version 3.
1012+ *
1013+ * messaging-app is distributed in the hope that it will be useful,
1014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1015+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1016+ * GNU General Public License for more details.
1017+ *
1018+ * You should have received a copy of the GNU General Public License
1019+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1020+ */
1021+
1022+import QtQuick 2.0
1023+import Ubuntu.Components 1.3
1024+
1025+UbuntuShape {
1026+ id: thumbnail
1027+ property int index
1028+ property string filePath
1029+
1030+ signal pressAndHold()
1031+
1032+ width: childrenRect.width
1033+ height: childrenRect.height
1034+
1035+ image: Image {
1036+ id: avatarImage
1037+ width: units.gu(8)
1038+ height: units.gu(8)
1039+ sourceSize.height: height
1040+ sourceSize.width: width
1041+ fillMode: Image.PreserveAspectCrop
1042+ source: filePath
1043+ asynchronous: true
1044+ }
1045+ MouseArea {
1046+ anchors.fill: parent
1047+ onPressAndHold: {
1048+ mouse.accept = true
1049+ thumbnail.pressAndHold()
1050+ }
1051+ }
1052+}
1053
1054=== added file 'src/qml/ThumbnailUnknown.qml'
1055--- src/qml/ThumbnailUnknown.qml 1970-01-01 00:00:00 +0000
1056+++ src/qml/ThumbnailUnknown.qml 2015-12-08 17:14:16 +0000
1057@@ -0,0 +1,45 @@
1058+/*
1059+ * Copyright 2012-2015 Canonical Ltd.
1060+ *
1061+ * This file is part of messaging-app.
1062+ *
1063+ * messaging-app is free software; you can redistribute it and/or modify
1064+ * it under the terms of the GNU General Public License as published by
1065+ * the Free Software Foundation; version 3.
1066+ *
1067+ * messaging-app is distributed in the hope that it will be useful,
1068+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1069+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1070+ * GNU General Public License for more details.
1071+ *
1072+ * You should have received a copy of the GNU General Public License
1073+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1074+ */
1075+
1076+import QtQuick 2.0
1077+import Ubuntu.Components 1.3
1078+
1079+UbuntuShape {
1080+ id: thumbnail
1081+ property int index
1082+ property string filePath
1083+
1084+ signal pressAndHold()
1085+
1086+ width: units.gu(8)
1087+ height: units.gu(8)
1088+
1089+ Icon {
1090+ anchors.centerIn: parent
1091+ width: units.gu(6)
1092+ height: units.gu(6)
1093+ name: "attachment"
1094+ }
1095+ MouseArea {
1096+ anchors.fill: parent
1097+ onPressAndHold: {
1098+ mouse.accept = true
1099+ thumbnail.pressAndHold()
1100+ }
1101+ }
1102+}
1103
1104=== added file 'src/qml/TransparentButton.qml'
1105--- src/qml/TransparentButton.qml 1970-01-01 00:00:00 +0000
1106+++ src/qml/TransparentButton.qml 2015-12-08 17:14:16 +0000
1107@@ -0,0 +1,86 @@
1108+/*
1109+ * Copyright 2015 Canonical Ltd.
1110+ *
1111+ * This file is part of messaging-app.
1112+ *
1113+ * messaging-app is free software; you can redistribute it and/or modify
1114+ * it under the terms of the GNU General Public License as published by
1115+ * the Free Software Foundation; version 3.
1116+ *
1117+ * messaging-app is distributed in the hope that it will be useful,
1118+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1119+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1120+ * GNU General Public License for more details.
1121+ *
1122+ * You should have received a copy of the GNU General Public License
1123+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1124+ */
1125+
1126+import QtQuick 2.0
1127+import Ubuntu.Components 1.3
1128+
1129+Item {
1130+ id: button
1131+
1132+ width: icon.width
1133+ height: icon.height + label.height + spacing
1134+
1135+ property alias iconName: icon.name
1136+ property alias iconSource: icon.source
1137+ property alias iconColor: icon.color
1138+ property int iconSize: units.gu(2)
1139+ property alias iconRotation: icon.rotation
1140+ property alias text: label.text
1141+ property alias textSize: label.font.pixelSize
1142+ property int spacing: 0
1143+
1144+ signal clicked()
1145+ signal pressed()
1146+ signal released()
1147+
1148+ Icon {
1149+ id: icon
1150+
1151+ anchors {
1152+ left: parent.left
1153+ right: parent.right
1154+ top: parent.top
1155+ }
1156+
1157+ height: iconSize
1158+ width: iconSize
1159+ color: "gray"
1160+ Behavior on rotation {
1161+ UbuntuNumberAnimation { }
1162+ }
1163+ }
1164+
1165+ MouseArea {
1166+ anchors {
1167+ fill: parent
1168+ margins: units.gu(-2)
1169+ }
1170+ onClicked: {
1171+ mouse.accepted = true
1172+ button.clicked()
1173+ }
1174+
1175+ onPressed: button.pressed()
1176+ onReleased: button.released()
1177+ }
1178+
1179+ Text {
1180+ id: label
1181+ color: "gray"
1182+ height: text !== "" ? paintedHeight : 0
1183+ anchors {
1184+ left: parent.left
1185+ right: parent.right
1186+ bottom: parent.bottom
1187+ }
1188+ horizontalAlignment: Text.AlignHCenter
1189+ verticalAlignment: Text.AlignBottom
1190+ font.family: "Ubuntu"
1191+ font.pixelSize: FontUtils.sizeToPixels("small")
1192+ }
1193+}

Subscribers

People subscribed via source and target branches