Merge lp:~phablet-team/messaging-app/disconnect-on-exit-favorite-channels into lp:messaging-app/staging

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Tiago Salem Herrmann
Approved revision: 681
Merged at revision: 660
Proposed branch: lp:~phablet-team/messaging-app/disconnect-on-exit-favorite-channels
Merge into: lp:messaging-app/staging
Prerequisite: lp:~phablet-team/messaging-app/improve-participants-screen
Diff against target: 802 lines (+314/-142)
12 files modified
debian/messaging-app-apparmor.additions (+4/-0)
src/main.cpp (+3/-0)
src/messagingapplication.cpp (+1/-2)
src/qml/GroupChatInfoPage.qml (+6/-1)
src/qml/MainPage.qml (+8/-2)
src/qml/Messages.qml (+70/-24)
src/qml/MessagingContactEditorPage.qml (+2/-2)
src/qml/MessagingContactViewPage.qml (+34/-15)
src/qml/NewRecipientPage.qml (+46/-9)
src/qml/ParticipantInfoPage.qml (+80/-69)
src/qml/messaging-app.qml (+54/-18)
tests/qml/tst_MessagesView.qml (+6/-0)
To merge this branch: bzr merge lp:~phablet-team/messaging-app/disconnect-on-exit-favorite-channels
Reviewer Review Type Date Requested Status
Tiago Salem Herrmann (community) Approve
Review via email: mp+317267@code.launchpad.net

Commit message

* Add a configuration option to disconnect from server on application exit.
* Allow to favorite a channels and store it on settings.
* Mark thread as not connected (opacity = 0.5)

To post a comment you must log in.
652. By Renato Araujo Oliveira Filho

Revert changes related with disabling unactive channels.

653. By Renato Araujo Oliveira Filho

Use ChatEntry object on delegates to check if the channel is connected or not.

654. By Renato Araujo Oliveira Filho

Avoid auto-connect on channels.

655. By Renato Araujo Oliveira Filho

Removed deprecated code.

656. By Renato Araujo Oliveira Filho

Fixed favorites settings.

Remove '\' from account id before save on settings to avoid it to be saved as section.

657. By Renato Araujo Oliveira Filho

merged.

658. By Renato Araujo Oliveira Filho

Does not set appliaction name more than once.
Disable favorite auto-connection until fix the server.

659. By Renato Araujo Oliveira Filho

reconnect with favorite channels on app startup.

660. By Renato Araujo Oliveira Filho

revert changes setting organization name (Fixed on SDK).

661. By Renato Araujo Oliveira Filho

Allow create contacts with IRC accounts from messaging app.

662. By Tiago Salem Herrmann

merge parent branch

663. By Tiago Salem Herrmann

fix first participant when contact matching is disabled

664. By Tiago Salem Herrmann

fix conflict

665. By Tiago Salem Herrmann

fix broken test

666. By Renato Araujo Oliveira Filho

Update contact view variable type.

This is necessary because the accountToAdd now is a dictonary with account protocol and uri.

667. By Renato Araujo Oliveira Filho

Does contact match on 1-1 conversation.

668. By Renato Araujo Oliveira Filho

Remove debug message.

669. By Renato Araujo Oliveira Filho

Enter in "newMessage" when no threadId is set.

Make sure that participants appear on multirecipient list.

670. By Renato Araujo Oliveira Filho

Re-designe contact info page.

671. By Renato Araujo Oliveira Filho

Do contact match using server address.

672. By Tiago Salem Herrmann

Register service to notify handler the app was launched

673. By Tiago Salem Herrmann

handler will disconnect the account. we don't need to request leave the channels

674. By Tiago Salem Herrmann

fix variable name

675. By Tiago Salem Herrmann

Allow dbus service registration on dbus

676. By Tiago Salem Herrmann

show connecting state when threads sorted by accounts

677. By Tiago Salem Herrmann

merge parent branch

678. By Tiago Salem Herrmann

merge parent

679. By Tiago Salem Herrmann

merge parent

680. By Tiago Salem Herrmann

only show call button for tel protocols

681. By Tiago Salem Herrmann

merge parent branch

Revision history for this message
Tiago Salem Herrmann (tiagosh) wrote :

Looks good. thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/messaging-app-apparmor.additions'
2--- debian/messaging-app-apparmor.additions 2016-01-11 12:10:08 +0000
3+++ debian/messaging-app-apparmor.additions 2017-03-08 22:08:54 +0000
4@@ -12,6 +12,10 @@
5 bus=session
6 peer=(name=com.canonical.TelephonyServiceIndicator,label=unconfined),
7
8+ dbus bind
9+ bus=session
10+ name=com.canonical.MessagingApp,
11+
12 # make it possible for apps to register a telepathy observer
13 dbus bind
14 bus=session
15
16=== modified file 'src/main.cpp'
17--- src/main.cpp 2017-03-08 22:08:54 +0000
18+++ src/main.cpp 2017-03-08 22:08:54 +0000
19@@ -42,6 +42,9 @@
20 // as it doesn’t play well with QtFolks.
21 int main(int argc, char** argv)
22 {
23+ QCoreApplication::setOrganizationName("com.ubuntu.messaging-app");
24+ QCoreApplication::setApplicationName("MessagingApp");
25+
26 MessagingApplication application(argc, argv);
27
28 if (!application.setup()) {
29
30=== modified file 'src/messagingapplication.cpp'
31--- src/messagingapplication.cpp 2017-03-08 22:08:54 +0000
32+++ src/messagingapplication.cpp 2017-03-08 22:08:54 +0000
33@@ -89,8 +89,6 @@
34 MessagingApplication::MessagingApplication(int &argc, char **argv)
35 : QGuiApplication(argc, argv), m_view(0), m_applicationIsReady(false)
36 {
37- setApplicationName("MessagingApp");
38- setOrganizationName("com.ubuntu.messaging-app");
39 }
40
41 bool MessagingApplication::fullscreen() const
42@@ -101,6 +99,7 @@
43
44 bool MessagingApplication::setup()
45 {
46+ QDBusConnection::sessionBus().registerService("com.canonical.MessagingApp");
47 installIconPath();
48 static QList<QString> validSchemes;
49 bool fullScreen = false;
50
51=== modified file 'src/qml/GroupChatInfoPage.qml'
52--- src/qml/GroupChatInfoPage.qml 2017-03-08 22:08:54 +0000
53+++ src/qml/GroupChatInfoPage.qml 2017-03-08 22:08:54 +0000
54@@ -473,7 +473,12 @@
55 leadingActions: canRemove() ? participantLeadingActions : null
56 onClicked: {
57 if (openProfileButton.visible) {
58- mainStack.addPageToCurrentColumn(groupChatInfoPage, Qt.resolvedUrl("ParticipantInfoPage.qml"), {"delegate": participantDelegate, "chatEntry": chatEntry, "chatRoom": chatRoom})
59+ mainStack.addPageToCurrentColumn(groupChatInfoPage,
60+ Qt.resolvedUrl("ParticipantInfoPage.qml"),
61+ {"delegate": participantDelegate,
62+ "chatEntry": chatEntry,
63+ "chatRoom": chatRoom,
64+ "protocolName": account.protocolInfo.name })
65 }
66 }
67 Icon {
68
69=== modified file 'src/qml/MainPage.qml'
70--- src/qml/MainPage.qml 2017-03-08 22:08:54 +0000
71+++ src/qml/MainPage.qml 2017-03-08 22:08:54 +0000
72@@ -212,8 +212,14 @@
73 function formatSectionTitle(title) {
74 if (mainView.sortThreadsBy === "timestamp")
75 return DateUtils.friendlyDay(Qt.formatDate(section, "yyyy/MM/dd"), i18n);
76- else if (telepathyHelper.ready)
77- return telepathyHelper.accountForId(title).displayName
78+ else if (telepathyHelper.ready) {
79+ var account = telepathyHelper.accountForId(title)
80+ if (account.connectionStatus == AccountEntry.ConnectionStatusConnecting) {
81+ return i18n.tr("%1 - Connecting...").arg(account.displayName)
82+ } else {
83+ return account.displayName
84+ }
85+ }
86 else
87 return title
88 }
89
90=== modified file 'src/qml/Messages.qml'
91--- src/qml/Messages.qml 2017-03-08 22:08:54 +0000
92+++ src/qml/Messages.qml 2017-03-08 22:08:54 +0000
93@@ -88,7 +88,18 @@
94 property bool userTyping: false
95 property string userTypingId: ""
96 property string firstParticipantId: participantIds.length > 0 ? participantIds[0] : ""
97- property variant firstParticipant: (participants && participants.length > 0) ? participants[0] : null
98+ property variant firstParticipant: {
99+ if (!participants || participants.length == 0) {
100+ return null
101+ }
102+ var participant = participants[0]
103+ if (typeof participant === "string") {
104+ return {identifier: participant, alias: participant}
105+ } else {
106+ return participant
107+ }
108+ }
109+
110 property var threads: []
111 property QtObject presenceRequest: presenceItem
112 property var accountsModel: getAccountsModel()
113@@ -109,15 +120,16 @@
114 return chatEntry.title
115 }
116 var roomInfo = threadInformation.chatRoomInfo
117- if (roomInfo.Title != "") {
118- return roomInfo.Title
119- } else if (roomInfo.RoomName != "") {
120- return roomInfo.RoomName
121+ if (roomInfo) {
122+ if (roomInfo.Title != "") {
123+ return roomInfo.Title
124+ } else if (roomInfo.RoomName != "") {
125+ return roomInfo.RoomName
126+ }
127 }
128 return ""
129 }
130
131-
132 signal ready
133 signal cancel
134
135@@ -531,7 +543,7 @@
136 return
137 }
138
139- threadsModel.markThreadsAsRead(messages.threads);
140+ threadModel.markThreadsAsRead(messages.threads);
141 var properties = {'accountId': threads[0].accountId, 'threadId': threads[0].threadId, 'chatType': threads[0].chatType}
142 chatManager.acknowledgeAllMessages(properties)
143 }
144@@ -546,6 +558,28 @@
145 }
146 }
147
148+ function participantIdentifierByProtocol(account, baseIdentifier) {
149+ if (account && account.protocolInfo) {
150+ switch(account.protocolInfo.name) {
151+ case "irc":
152+ if (account.parameters.server != "")
153+ return "%1@%2".arg(baseIdentifier).arg(account.parameters.server)
154+ return baseIdentifier
155+ default:
156+ return baseIdentifier
157+ }
158+ }
159+ }
160+
161+ function contactMatchFieldFromProtocol(protocol, fallback) {
162+ switch(protocol) {
163+ case "irc":
164+ return ["X-IRC"];
165+ default:
166+ return fallback
167+ }
168+ }
169+
170 // Use a timer to make sure that 'threads' are correct set before try to select it
171 Timer {
172 id: selectThreadOnIdle
173@@ -733,12 +767,12 @@
174 State {
175 id: unknownContactState
176 name: "unknownContact"
177- when: participants.length == 1 && contactWatcher.isUnknown
178+ when: !messages.newMessage && (participants.length === 1) && contactWatcher.isUnknown
179
180 property list<QtObject> trailingActions: [
181 Action {
182 objectName: "contactCallAction"
183- visible: participants && participants.length === 1 && contactWatcher.interactive
184+ visible: participants && participants.length === 1 && contactWatcher.interactive && messages.account.addressableVCardFields.lastIndexOf("tel") != -1
185 iconName: "call-start"
186 text: i18n.tr("Call")
187 onTriggered: {
188@@ -750,12 +784,16 @@
189 Action {
190 objectName: "addContactAction"
191 visible: contactWatcher.isUnknown && participants && participants.length === 1 && contactWatcher.interactive
192+ enabled: messages.account != null
193 iconName: "contact-new"
194 text: i18n.tr("Add")
195 onTriggered: {
196 Qt.inputMethod.hide()
197- // FIXME: support other things than just phone numbers
198- mainView.addPhoneToContact(messages, "", contactWatcher.identifier, null, null)
199+ mainView.addAccountToContact(messages,
200+ "",
201+ messages.account.protocolInfo.name,
202+ contactWatcher.identifier,
203+ null, null)
204 }
205 }
206 ]
207@@ -836,7 +874,7 @@
208 State {
209 id: knownContactState
210 name: "knownContact"
211- when: participants.length == 1 && !contactWatcher.isUnknown
212+ when: !messages.newMessage && participants && participants.length === 1 && !contactWatcher.isUnknown
213
214 property list<QtObject> trailingActions: [
215 Action {
216@@ -888,11 +926,17 @@
217 }
218 }
219 }
220- newMessage = (messages.threadId == "") || (messages.accountId == "" && messages.participants.length === 0)
221 restoreBindings()
222 if (threadId !== "" && accountId !== "" && threads.length == 0) {
223 addNewThreadToFilter(accountId, {"threadId": threadId, "chatType": chatType})
224 }
225+ newMessage = (messages.threadId == "") || (messages.accountId == "" && messages.participants.length === 0)
226+ // if it is a new message we need to add participants into the multiRecipient list
227+ if (newMessage) {
228+ for (var i in participantIds) {
229+ multiRecipient.addRecipient(participantIds[i])
230+ }
231+ }
232 // if we add multiple attachments at the same time, it break the Repeater + Loaders
233 fillAttachmentsTimer.start()
234 mainView.updateNewMessageStatus()
235@@ -1102,7 +1146,7 @@
236 }
237
238 Repeater {
239- model: account.protocolInfo.enableChatStates ? messages.chatEntry.chatStates : null
240+ model: account ? (account.protocolInfo.enableChatStates ? messages.chatEntry.chatStates : null) : null
241 delegate: Item {
242 function processChatState() {
243 if (modelData.state == ChatEntry.ChannelChatStateComposing) {
244@@ -1123,8 +1167,9 @@
245
246 ContactWatcher {
247 id: typingContactWatcher
248- identifier: messages.userTypingId
249- addressableFields: messages.account ? messages.account.addressableVCardFields : []
250+ identifier: messages.participantIdentifierByProtocol(messages.account, userTypingId)
251+ addressableFields: messages.account ?
252+ messages.contactMatchFieldFromProtocol(messages.account.protocolInfo.name, messages.account.addressableVCardFields) : []
253 }
254
255 MessagesHeader {
256@@ -1272,12 +1317,13 @@
257
258 ContactWatcher {
259 id: contactWatcherInternal
260- identifier: firstParticipant ? firstParticipant.identifier : ""
261- contactId: firstParticipant ? firstParticipant.contactId : ""
262- alias: firstParticipant ? firstParticipant.alias : ""
263- avatar: firstParticipant ? firstParticipant.avatar : ""
264- detailProperties: firstParticipant ? firstParticipant.detailProperties : {}
265- addressableFields: messages.account ? messages.account.addressableVCardFields : []
266+ identifier: firstParticipant && firstParticipant.identifier ? messages.participantIdentifierByProtocol(messages.account, firstParticipant.identifier) : ""
267+ contactId: firstParticipant && firstParticipant.contactId ? firstParticipant.contactId : ""
268+ alias: firstParticipant && firstParticipant.alias ? firstParticipant.alias : ""
269+ avatar: firstParticipant && firstParticipant.avatar ? firstParticipant.avatar : ""
270+ detailProperties: firstParticipant && firstParticipant.detailProperties ? firstParticipant.detailProperties : {}
271+ addressableFields: messages.account && messages.account.protocolInfo ?
272+ messages.contactMatchFieldFromProtocol(messages.account.protocolInfo.name, messages.account.addressableVCardFields) : []
273 }
274
275 HistoryUnionFilter {
276@@ -1294,7 +1340,7 @@
277 sort: HistorySort {}
278 groupingProperty: "participants"
279 filter: messages.accountId != "" && messages.threadId != "" ? filters : null
280- matchContacts: messages.account.addressableVCardFields.length > 0
281+ matchContacts: messages.account ? messages.account.addressableVCardFields.length > 0 : false
282 }
283
284 ListView {
285@@ -1322,7 +1368,7 @@
286 id: eventModel
287 type: HistoryThreadModel.EventTypeText
288 filter: updateFilters(telepathyHelper.textAccounts.all, messages.chatType, messages.participantIds, messages.reloadFilters, messages.threads)
289- matchContacts: messages.account.addressableVCardFields.length > 0
290+ matchContacts: messages.account ? messages.account.addressableVCardFields.length > 0 : false
291 sort: HistorySort {
292 sortField: "timestamp"
293 sortOrder: HistorySort.DescendingOrder
294
295=== modified file 'src/qml/MessagingContactEditorPage.qml'
296--- src/qml/MessagingContactEditorPage.qml 2017-03-08 22:08:54 +0000
297+++ src/qml/MessagingContactEditorPage.qml 2017-03-08 22:08:54 +0000
298@@ -61,11 +61,11 @@
299
300 onContactSaved: {
301 if (root.contactListPage) {
302- if (root.contactListPage.phoneToAdd !== "") {
303+ if (root.contactListPage.accountToAdd !== "") {
304 mainStack.removePages(root.contactListPage)
305 } else {
306 root.contactListPage.moveListToContact(contact)
307- root.contactListPage.phoneToAdd = ""
308+ root.contactListPage.accountToAdd = null
309 }
310 }
311 }
312
313=== modified file 'src/qml/MessagingContactViewPage.qml'
314--- src/qml/MessagingContactViewPage.qml 2017-03-08 22:08:54 +0000
315+++ src/qml/MessagingContactViewPage.qml 2017-03-08 22:08:54 +0000
316@@ -33,26 +33,49 @@
317 objectName: "contactViewPage"
318
319 readonly property string contactEditorPageURL: Qt.resolvedUrl("MessagingContactEditorPage.qml")
320- property string addPhoneToContact: ""
321+ property var accountToAdd: null
322 property var contactListPage: null
323 model: null
324
325- function addPhoneToContactImpl(contact, phoneNumber)
326+ function createContact(contact, detailName, newDetailSrc)
327 {
328- var detailSourceTemplate = "import QtContacts 5.0; PhoneNumber{ number: \"" + phoneNumber.trim() + "\" }"
329- var newDetail = Qt.createQmlObject(detailSourceTemplate, contact)
330+ var newDetail = Qt.createQmlObject(newDetailSrc, contact)
331 if (newDetail) {
332 contact.addDetail(newDetail)
333 mainStack.addPageToCurrentColumn(root,
334 root.contactEditorPageURL,
335 { model: root.model,
336 contact: contact,
337- initialFocusSection: "phones",
338+ initialFocusSection: detailName,
339 newDetails: [newDetail],
340 contactListPage: root.contactListPage })
341- root.addPhoneToContact = ""
342 } else {
343- console.warn("Fail to create phone number detail")
344+ console.warn("Fail to create contact with new detail")
345+ }
346+
347+ }
348+
349+ function addPhoneToContactImpl(contact, phoneNumber)
350+ {
351+ var detailSourceTemplate = "import QtContacts 5.0; PhoneNumber{ number: \"" + phoneNumber.trim() + "\" }"
352+ createContact(contact, "phones", detailSourceTemplate)
353+ }
354+
355+ function addAccountToContactImpl(contact, account)
356+ {
357+ var detailSourceTemplate = "import QtContacts 5.0; OnlineAccount { protocol: " + account.protocol.trim() + "; accountUri: \"" + account.uri + "\" }"
358+ createContact(contact, "ims", detailSourceTemplate)
359+ }
360+
361+ function commit()
362+ {
363+ if (root.accountToAdd) {
364+ if (root.accountToAdd.protocol === "OnlineAccount.Unknown") {
365+ root.addPhoneToContactImpl(contact, root.accountToAdd.uri)
366+ } else {
367+ root.addAccountToContactImpl(contact, root.accountToAdd)
368+ root.accountToAdd = null
369+ }
370 }
371 }
372
373@@ -144,17 +167,13 @@
374 onContactRemoved: pageStack.removePages(root)
375 onContactFetched: {
376 root.contact = contact
377- if (root.active && root.addPhoneToContact != "") {
378- root.addPhoneToContactImpl(contact, root.addPhoneToContact)
379- root.addPhoneToContact = ""
380- }
381+ if (root.active)
382+ root.commit()
383 }
384
385 onActiveChanged: {
386- if (active && root.contact && root.addPhoneToContact != "") {
387- root.addPhoneToContactImpl(contact, root.addPhoneToContact)
388- root.addPhoneToContact = ""
389- }
390+ if (active)
391+ root.commit()
392 }
393
394 Component.onCompleted: {
395
396=== modified file 'src/qml/NewRecipientPage.qml'
397--- src/qml/NewRecipientPage.qml 2017-03-08 22:08:54 +0000
398+++ src/qml/NewRecipientPage.qml 2017-03-08 22:08:54 +0000
399@@ -26,7 +26,7 @@
400 objectName: "newRecipientPage"
401
402 property var itemCallback: null
403- property string phoneToAdd: ""
404+ property var accountToAdd: null
405 property QtObject contactIndex: null
406
407 function moveListToContact(contact)
408@@ -50,6 +50,30 @@
409 mainStack.removePages(newRecipientPage)
410 }
411
412+ function createEmptyContactWithAccount(account, parent)
413+ {
414+ var details = [ {detail: "EmailAddress", field: "emailAddress", value: ""},
415+ {detail: "Name", field: "firstName", value: ""}
416+ ]
417+
418+ var newContact = Qt.createQmlObject("import QtContacts 5.0; Contact{ }", parent)
419+ var detailSourceTemplate = "import QtContacts 5.0; %1{ %2: \"%3\" }"
420+ for (var i=0; i < details.length; i++) {
421+ var detailMetaData = details[i]
422+ var newDetail = Qt.createQmlObject(detailSourceTemplate.arg(detailMetaData.detail)
423+ .arg(detailMetaData.field)
424+ .arg(detailMetaData.value), parent)
425+ newContact.addDetail(newDetail)
426+ }
427+
428+ var accountSourceTemplate = "import QtContacts 5.0; OnlineAccount{ accountUri: \"%1\"; protocol: %2 }"
429+ var newDetail = Qt.createQmlObject(accountSourceTemplate
430+ .arg(account.uri)
431+ .arg(account.protocol), parent)
432+ newContact.addDetail(newDetail)
433+ return newContact
434+ }
435+
436 header: PageHeader {
437 id: pageHeader
438
439@@ -186,12 +210,13 @@
440
441 filterTerm: searchField.text
442 onContactClicked: {
443- if (newRecipientPage.phoneToAdd != "") {
444- mainView.addPhoneToContact(newRecipientPage,
445- contact,
446- newRecipientPage.phoneToAdd,
447- newRecipientPage,
448- contactList.listModel)
449+ if (newRecipientPage.accountToAdd) {
450+ mainView.addAccountToContact(newRecipientPage,
451+ contact,
452+ accountToAdd.protocol,
453+ accountToAdd.uri,
454+ newRecipientPage,
455+ contactList.listModel)
456 } else {
457 mainView.showContactDetails(newRecipientPage,
458 contact,
459@@ -201,12 +226,24 @@
460 }
461
462 onAddNewContactClicked: {
463- var newContact = ContactsJS.createEmptyContact(newRecipientPage.phoneToAdd, newRecipientPage)
464+ var newContact = newRecipientPage.createEmptyContactWithAccount(newRecipientPage.accountToAdd, newRecipientPage)
465+ var focusField = "name"
466+ if (newRecipientPage.accountToAdd) {
467+ switch (newRecipientPage.accountToAdd.protocol) {
468+ case "ofono":
469+ focusField = "phones"
470+ break
471+ default:
472+ focusField = "ims"
473+ break
474+ }
475+ }
476+
477 mainStack.addPageToCurrentColumn(newRecipientPage,
478 Qt.resolvedUrl("MessagingContactEditorPage.qml"),
479 { model: contactList.listModel,
480 contact: newContact,
481- initialFocusSection: (newRecipientPage.phoneToAdd != "" ? "phones" : "name"),
482+ initialFocusSection: focusField,
483 contactListPage: newRecipientPage })
484 }
485 }
486
487=== modified file 'src/qml/ParticipantInfoPage.qml'
488--- src/qml/ParticipantInfoPage.qml 2017-03-08 22:08:54 +0000
489+++ src/qml/ParticipantInfoPage.qml 2017-03-08 22:08:54 +0000
490@@ -26,8 +26,9 @@
491 property var delegate
492 property var participant: delegate.participant
493 property var chatEntry
494+ property string protocolName: "ofono"
495 property bool chatRoom: false
496- property bool knownContact: participant.contactId !== ""
497+ property bool knownContact: participant.contactId && (participant.contactId !== "")
498
499 header: PageHeader {
500 id: pageHeader
501@@ -37,7 +38,13 @@
502
503 Flickable {
504 id: contentsFlickable
505- anchors.fill: parent
506+ anchors {
507+ top: parent.top
508+ bottom: buttons.top
509+ left: parent.left
510+ right: parent.right
511+ }
512+
513 contentHeight: contentsColumn.height
514 clip: true
515
516@@ -105,73 +112,77 @@
517 }
518 }
519 }
520-
521- Item {
522- id: padding
523- height: units.gu(1)
524- anchors.left: parent.left
525- anchors.right: parent.right
526- }
527-
528- ListItems.ThinDivider {
529- anchors {
530- left: parent.left
531- right: parent.right
532- }
533- }
534-
535- Item {
536- id: padding3
537- height: units.gu(2)
538- anchors.left: parent.left
539- anchors.right: parent.right
540- }
541-
542- Column {
543- anchors {
544- left: parent.left
545- leftMargin: units.gu(2)
546- }
547- spacing: units.gu(2)
548- Button {
549- id: showInContactsButton
550- text: knownContact ? i18n.tr("See in contacts") : i18n.tr("Add to contacts")
551- onClicked: {
552- if (knownContact) {
553- mainView.showContactDetails(participantInfoPage, participant.contactId, null, null)
554- } else {
555- mainView.addPhoneToContact(participantInfoPage, "", participant.identifier, null, null)
556- }
557- }
558- }
559-
560- Button {
561- id: setAsAdminButton
562- text: i18n.tr("Set as admin")
563- visible: false
564- // disabled until backends support this feature
565- //visible: chatRoom && chatEntry.active && chatEntry.selfContactRoles == 3
566- }
567-
568- Button {
569- id: sendMessageButton
570- text: i18n.tr("Send private message")
571- onClicked: {
572- mainView.startChat({accountId: chatEntry.accountId, participantIds: [participant.identifier]})
573- pageStack.removePages(participantInfoPage)
574- }
575- }
576-
577- Button {
578- id: leaveButton
579- visible: delegate.canRemove()
580- text: i18n.tr("Remove from group")
581- color: Theme.palette.normal.negative
582- onClicked: {
583- delegate.removeFromGroup()
584- pageStack.removePages(participantInfoPage)
585- }
586- }
587+ }
588+ }
589+
590+ Column {
591+ id: buttons
592+ anchors {
593+ left: parent.left
594+ right: parent.right
595+ bottom: parent.bottom
596+ margins: units.gu(2)
597+ }
598+ spacing: units.gu(0.5)
599+
600+ Button {
601+ id: showInContactsButton
602+
603+ anchors {
604+ left: parent.left
605+ right: parent.right
606+ }
607+ text: knownContact ? i18n.tr("See in contacts") : i18n.tr("Add to contacts")
608+ onClicked: {
609+ console.debug("Know contact:" + participant.contactId)
610+ if (knownContact) {
611+ mainView.showContactDetails(participantInfoPage, participant.contactId, null, null)
612+ } else {
613+ mainView.addAccountToContact(participantInfoPage, "", protocolName, participant.identifier, null, null)
614+ }
615+ }
616+ }
617+
618+ Button {
619+ id: setAsAdminButton
620+
621+ anchors {
622+ left: parent.left
623+ right: parent.right
624+ }
625+ text: i18n.tr("Set as admin")
626+ visible: false
627+ // disabled until backends support this feature
628+ //visible: chatRoom && chatEntry.active && chatEntry.selfContactRoles == 3
629+ }
630+
631+ Button {
632+ id: sendMessageButton
633+
634+ anchors {
635+ left: parent.left
636+ right: parent.right
637+ }
638+ text: i18n.tr("Send private message")
639+ onClicked: {
640+ mainView.startChat({accountId: chatEntry.accountId, participantIds: [participant.identifier]})
641+ pageStack.removePages(participantInfoPage)
642+ }
643+ }
644+
645+ Button {
646+ id: leaveButton
647+
648+ anchors {
649+ left: parent.left
650+ right: parent.right
651+ }
652+ visible: delegate.canRemove()
653+ text: i18n.tr("Remove from group")
654+ color: Theme.palette.normal.negative
655+ onClicked: {
656+ delegate.removeFromGroup()
657+ pageStack.removePages(participantInfoPage)
658 }
659 }
660 }
661
662=== modified file 'src/qml/messaging-app.qml'
663--- src/qml/messaging-app.qml 2017-03-08 22:08:54 +0000
664+++ src/qml/messaging-app.qml 2017-03-08 22:08:54 +0000
665@@ -19,6 +19,7 @@
666 import QtQuick 2.2
667 import QtQuick.Window 2.2
668 import Qt.labs.settings 1.0
669+import QtContacts 5.0
670 import Ubuntu.Components 1.3
671 import Ubuntu.Components.Popups 1.3
672 import Ubuntu.Telephony 0.1
673@@ -81,13 +82,32 @@
674 initialProperties)
675 }
676
677- function addPhoneToContact(currentPage, contact, phoneNumber, contactListPage, contactsModel) {
678+ function protocolFromString(protocolName)
679+ {
680+ if (protocolName.indexOf("OnlineAccount.") === 0) {
681+ // protocol already converted
682+ return protocolName
683+ }
684+
685+ switch(protocolName) {
686+ case "irc":
687+ return "OnlineAccount.Irc"
688+ case "ofono":
689+ default:
690+ return "OnlineAccount.Unknown"
691+ }
692+ }
693+
694+ function addAccountToContact(currentPage, contact, accountProtocol, accountUri, contactListPage, contactsModel)
695+ {
696+ var accountDetails = {"protocol": protocolFromString(accountProtocol),
697+ "uri": accountUri}
698 if (contact === "") {
699 mainStack.addPageToCurrentColumn(currentPage,
700 Qt.resolvedUrl("NewRecipientPage.qml"),
701- { "phoneToAdd": phoneNumber })
702+ { "accountToAdd": accountDetails })
703 } else {
704- var initialProperties = { "addPhoneToContact": phoneNumber }
705+ var initialProperties = { "accountToAdd": accountDetails }
706 if (contactListPage) {
707 initialProperties["contactListPage"] = contactListPage
708 }
709@@ -110,13 +130,6 @@
710 //TODO: disconnect from server
711 }
712
713- onApplicationActiveChanged: {
714- if (applicationActive) {
715- telepathyHelper.registerChannelObserver()
716- } else {
717- telepathyHelper.unregisterChannelObserver()
718- }
719- }
720
721 function removeThreads(threads) {
722 for (var i in threads) {
723@@ -141,8 +154,36 @@
724 mainView.showMessagesView(properties)
725 }
726
727+ function connectToFavoriteChannels(account) {
728+ var favs = favoriteChannels.getFavoriteChannels(account.accountId)
729+ for (var c in favs) {
730+ var favChannel = favs[c]
731+ if (favChannel) {
732+ console.debug("Start channel:" + account.accountId + "/" + favChannel)
733+ var properties = {'chatType': HistoryThreadModel.ChatTypeRoom,
734+ 'accountId': account.accountId,
735+ 'threadId': favChannel}
736+ chatManager.startChat(account.accountId, properties)
737+ }
738+ }
739+ }
740+
741+ onApplicationActiveChanged: {
742+ if (applicationActive) {
743+ telepathyHelper.registerChannelObserver()
744+ } else {
745+ telepathyHelper.unregisterChannelObserver()
746+ }
747+ }
748+
749 Connections {
750 target: telepathyHelper.textAccounts
751+ onAccountChanged: {
752+ if (active) {
753+ connectToFavoriteChannels(entry)
754+ }
755+ }
756+
757 onActiveChanged: {
758 for (var i in telepathyHelper.textAccounts.active) {
759 if (telepathyHelper.textAccounts.active[i] == account) {
760@@ -151,15 +192,7 @@
761 }
762 account = Qt.binding(defaultPhoneAccount)
763 }
764- }
765
766- Component.onDestruction: {
767- for (var i in telepathyHelper.textAccounts.active) {
768- var account = telepathyHelper.textAccounts.active[i]
769- if (account.protocolInfo.leaveRoomsOnClose) {
770- chatManager.leaveRooms(account.accountId, "")
771- }
772- }
773 }
774
775 Connections {
776@@ -174,6 +207,9 @@
777 !settings.mainViewIgnoreFirstTimeDialog && mainPage.displayedThreadIndex < 0) {
778 PopupUtils.open(Qt.createComponent("Dialogs/NoDefaultSIMCardDialog.qml").createObject(mainView))
779 }
780+ for (var i in telepathyHelper.textAccounts.active) {
781+ connectToFavoriteChannels(telepathyHelper.textAccounts.active[i])
782+ }
783 }
784 }
785
786
787=== modified file 'tests/qml/tst_MessagesView.qml'
788--- tests/qml/tst_MessagesView.qml 2017-03-08 22:08:54 +0000
789+++ tests/qml/tst_MessagesView.qml 2017-03-08 22:08:54 +0000
790@@ -161,6 +161,12 @@
791 function updateNewMessageStatus() { }
792 }
793
794+ Item {
795+ id: threadModel
796+ function markThreadsAsRead(threads) {
797+ }
798+ }
799+
800 Messages {
801 id: messagesView
802 active: true

Subscribers

People subscribed via source and target branches

to all changes: