Merge lp:~phablet-team/messaging-app/configure_sort into lp:messaging-app/staging

Proposed by Renato Araujo Oliveira Filho
Status: Merged
Approved by: Tiago Salem Herrmann
Approved revision: 665
Merged at revision: 658
Proposed branch: lp:~phablet-team/messaging-app/configure_sort
Merge into: lp:messaging-app/staging
Prerequisite: lp:~phablet-team/messaging-app/mark_threads_as_read
Diff against target: 537 lines (+294/-58)
7 files modified
debian/control (+1/-0)
src/qml/MainPage.qml (+10/-2)
src/qml/Messages.qml (+2/-2)
src/qml/SettingsPage.qml (+200/-45)
src/qml/ThreadDelegate.qml (+45/-6)
src/qml/ThreadsSectionDelegate.qml (+7/-1)
src/qml/messaging-app.qml (+29/-2)
To merge this branch: bzr merge lp:~phablet-team/messaging-app/configure_sort
Reviewer Review Type Date Requested Status
Tiago Salem Herrmann (community) Approve
Review via email: mp+316702@code.launchpad.net

Commit message

Allow user to select the sort field for conversation list.

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

Merged 'lp:~phablet-team/messaging-app/mark_threads_as_read'

647. By Renato Araujo Oliveira Filho

Allow user to hide conversation icon using settings.

648. By Renato Araujo Oliveira Filho

Fix currentIndex lost duing the sort order value change.

649. By Renato Araujo Oliveira Filho

Fixed sort order for timestamp sort.

650. By Renato Araujo Oliveira Filho

Implement compact view for thread list.

651. By Renato Araujo Oliveira Filho

Does not show unread message count on compact view.

652. By Renato Araujo Oliveira Filho

Branch merged.

653. By Renato Araujo Oliveira Filho

Parent branch merged.

654. By Tiago Salem Herrmann

merge parent branch

655. By Tiago Salem Herrmann

merge parent branch

656. By Renato Araujo Oliveira Filho

Mark conversation as bold when it contains unread messages.

657. By Renato Araujo Oliveira Filho

Added missing dep.

658. By Tiago Salem Herrmann

merge parent branch

659. By Renato Araujo Oliveira Filho

Parent merged.

660. By Renato Araujo Oliveira Filho

Show unread count on compact view.

661. By Tiago Salem Herrmann

merge parent branch

662. By Gustavo Pichorim Boiko

Merge parent branch

663. By Tiago Salem Herrmann

merge parent branch

664. By Renato Araujo Oliveira Filho

Fixed typo.

665. By Tiago Salem Herrmann

merge parent branch

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

just one remark. looks good otherwise.

review: Needs Fixing
666. By Tiago Salem Herrmann

remove comments

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/control'
2--- debian/control 2016-11-05 00:46:55 +0000
3+++ debian/control 2017-03-22 20:49:22 +0000
4@@ -26,6 +26,7 @@
5 qtdeclarative5-ubuntu-content1,
6 qtdeclarative5-ubuntu-addressbook0.1,
7 qtdeclarative5-ubuntu-thumbnailer0.1,
8+ qtdeclarative5-ubuntu-keyboard-extensions0.1,
9 qtdeclarative5-qtcontacts-plugin,
10 qtdeclarative5-folderlistmodel-plugin,
11 qtmultimedia5-dev,
12
13=== modified file 'src/qml/MainPage.qml'
14--- src/qml/MainPage.qml 2017-03-22 20:49:22 +0000
15+++ src/qml/MainPage.qml 2017-03-22 20:49:22 +0000
16@@ -209,6 +209,14 @@
17 Component {
18 id: sectionDelegate
19 ThreadsSectionDelegate {
20+ function formatSectionTitle(title) {
21+ if (mainView.sortTrheadsBy === "timestamp")
22+ return DateUtils.friendlyDay(Qt.formatDate(section, "yyyy/MM/dd"), i18n);
23+ else if (telepathyHelper.ready)
24+ return telepathyHelper.accountForId(title).displayName
25+ else
26+ return title
27+ }
28 }
29 }
30
31@@ -228,9 +236,9 @@
32 // but not completely revealed.
33 enabled: bottomEdgeLoader.item.status !== BottomEdge.Revealed
34 clip: true
35- section.property: "eventDate"
36 currentIndex: -1
37 //spacing: searchField.text === "" ? units.gu(-2) : 0
38+ section.property: mainView.sortTrheadsBy === "title" ? "accountId" : "eventDate"
39 section.delegate: searching && searchField.text !== "" ? null : sectionDelegate
40 header: ListItem.Standard {
41 // FIXME: update
42@@ -286,7 +294,7 @@
43 left: parent.left
44 right: parent.right
45 }
46- height: units.gu(8)
47+ compactView: mainView.compactView
48 selectMode: threadList.isInSelectionMode
49 selected: {
50 if (selectMode) {
51
52=== modified file 'src/qml/Messages.qml'
53--- src/qml/Messages.qml 2017-03-22 20:49:22 +0000
54+++ src/qml/Messages.qml 2017-03-22 20:49:22 +0000
55@@ -1254,7 +1254,7 @@
56 }
57
58 HistoryGroupedThreadsModel {
59- id: threadsModel
60+ id: messagesModel
61 type: HistoryThreadModel.EventTypeText
62 sort: HistorySort {}
63 groupingProperty: "participants"
64@@ -1269,7 +1269,7 @@
65 property var localPendingParticipants: null
66 property var remotePendingParticipants: null
67 property var threads: null
68- model: threadsModel
69+ model: messagesModel
70 visible: false
71 delegate: Item {
72 property var threads: model.threads
73
74=== modified file 'src/qml/SettingsPage.qml'
75--- src/qml/SettingsPage.qml 2017-03-22 20:49:22 +0000
76+++ src/qml/SettingsPage.qml 2017-03-22 20:49:22 +0000
77@@ -19,25 +19,57 @@
78 import QtQuick 2.2
79 import Ubuntu.Components 1.3
80 import Ubuntu.OnlineAccounts.Client 0.1
81+import Qt.labs.settings 1.0
82
83 Page {
84 id: settingsPage
85 title: i18n.tr("Settings")
86
87- property var setMethods: {
88- "mmsEnabled": function(value) { telepathyHelper.mmsEnabled = value }/*,
89- "characterCountEnabled": function(value) { msgSettings.showCharacterCount = value }*/
90- }
91- property var settingsModel: [
92- { "name": "mmsEnabled",
93- "description": i18n.tr("Enable MMS messages"),
94- "property": telepathyHelper.mmsEnabled,
95- "activatedFuncion": null
96- },
97- { "name": "addAccount",
98- "description": i18n.tr("Add an online account"),
99- "onActivated": "createAccount",
100- "property": null
101+ function createAccount()
102+ {
103+ if (onlineAccountHelper.item)
104+ onlineAccountHelper.item.run()
105+ }
106+
107+ readonly property var setMethods: {
108+ "mmsEnabled": function(value) { telepathyHelper.mmsEnabled = value },
109+ "threadSort": function(value) { mainView.sortThreadsBy = value },
110+ "compactView": function(value) { mainView.compactView = value }
111+ //"characterCountEnabled": function(value) { msgSettings.showCharacterCount = value }
112+ }
113+
114+ property var sortByModel: {
115+ "timestamp": i18n.tr("Sort by timestamp"),
116+ "title": i18n.tr("Sort by title")
117+ }
118+
119+ readonly property var settingsModel: [
120+ { "type": "boolean",
121+ "data": {"name": "mmsEnabled",
122+ "description": i18n.tr("Enable MMS messages"),
123+ "property": telepathyHelper.mmsEnabled,
124+ "activatedFuncion": null,
125+ "setMethod": "mmsEnabled"}
126+ },
127+ { "type": "boolean",
128+ "data": {"name": "compactView",
129+ "description": i18n.tr("Simplified conversation view"),
130+ "property": mainView.compactView,
131+ "activatedFuncion": null,
132+ "setMethod": "compactView"}
133+ },
134+ { "type": "action",
135+ "data": { "name": "addAccount",
136+ "description": i18n.tr("Add an online account"),
137+ "onActivated": "createAccount" }
138+ },
139+ { "type": "options",
140+ "data": { "name": "threadSort",
141+ "description": i18n.tr("Sort threads"),
142+ "currentValue": mainView.sortTrheadsBy,
143+ "subtitle": settingsPage.sortByModel[mainView.sortTrheadsBy],
144+ "options": sortByModel,
145+ "setMethod": "threadSort"}
146 }
147 /*,
148 { "name": "characterCountEnabled",
149@@ -82,33 +114,164 @@
150 id: settingDelegate
151 ListItem {
152 onClicked: {
153- if (checkbox.visible) {
154- checkbox.checked = !checkbox.checked
155- } else {
156- settingsPage[modelData.onActivated]()
157- }
158+ layoutDelegate.item.activate()
159+ settingsList.currentIndex = index
160+
161 }
162 ListItemLayout {
163- title.text: modelData.description
164-
165- CheckBox {
166- id: checkbox
167- objectName: modelData.name
168-
169- visible: modelData.property !== null
170- SlotsLayout.position: SlotsLayout.trailing
171- checked: modelData.property
172- onCheckedChanged: {
173- if (checked != modelData.property) {
174- settingsPage.setMethods[modelData.name](checked)
175+ title.text: modelData.data.description
176+ subtitle.text: modelData.data.subtitle ? modelData.data.subtitle : ""
177+
178+ Loader {
179+ id: layoutDelegate
180+
181+ sourceComponent: {
182+ switch(modelData.type) {
183+ case "action":
184+ return actionDelegate
185+ case "boolean":
186+ return booleanDelegate
187+ case "options":
188+ return optionsDelegate
189 }
190 }
191- }
192-
193- ProgressionSlot {
194- visible: modelData.property === null
195- }
196- }
197+
198+ Binding {
199+ target: layoutDelegate.item
200+ property: "modelData"
201+ value: modelData.data
202+ when: layoutDelegate.status === Loader.Ready
203+ }
204+ Binding {
205+ target: layoutDelegate.item
206+ property: "index"
207+ value: index
208+ when: layoutDelegate.status === Loader.Ready
209+ }
210+ }
211+ }
212+ }
213+ }
214+
215+ Component {
216+ id: booleanDelegate
217+
218+ CheckBox {
219+ id: checkbox
220+ objectName: modelData.name
221+
222+ property var modelData: null
223+ property int index: -1
224+
225+ function activate()
226+ {
227+ checkbox.checked = !checkbox.checked
228+ }
229+
230+ SlotsLayout.position: SlotsLayout.Trailing
231+ checked: modelData.property
232+ onCheckedChanged: {
233+ if (checked != modelData.property) {
234+ settingsPage.setMethods[modelData.setMethod](checked)
235+ }
236+ }
237+ }
238+ }
239+
240+ Component {
241+ id: actionDelegate
242+
243+ ProgressionSlot {
244+ id: progression
245+ objectName: modelData.name
246+
247+ property var modelData: null
248+ property int index: -1
249+ function activate()
250+ {
251+ settingsPage[modelData.onActivated]()
252+ }
253+ }
254+ }
255+
256+ Component {
257+ id: optionsDelegate
258+
259+ ProgressionSlot {
260+ id: progression
261+ objectName: modelData.name
262+
263+ property var modelData: null
264+ property int index: -1
265+ function activate()
266+ {
267+ pageStack.addPageToNextColumn(settingsPage, optionsDelegatePage,
268+ {"title": modelData.description,
269+ "model": modelData.options,
270+ "index": index,
271+ "currentIndex": modelData.currentValue,
272+ "setMethod": modelData.setMethod})
273+ }
274+ }
275+ }
276+
277+ Component {
278+ id: optionsDelegatePage
279+
280+ Page {
281+ id: optionsPage
282+
283+ property alias title: pageHeader.title
284+ property var model
285+ property string currentIndex
286+ property string setMethod
287+ property int index: -1
288+
289+ signal selected(string key)
290+
291+ function indexOf(key) {
292+ return Object.keys(optionsPage.model).indexOf(key)
293+ }
294+
295+ onSelected: {
296+ if (key !== "") {
297+ settingsPage.setMethods[optionsPage.setMethod](key)
298+ }
299+ //WORKAROUND: re-set index of settings page because the list is
300+ // rebuild after a value change and that cause the index to reset to 0
301+ settingsList.currentIndex = index
302+ pageStack.removePages(optionsPage)
303+ }
304+
305+ header: PageHeader {
306+ id: pageHeader
307+
308+ leadingActionBar.actions: [
309+ Action {
310+ iconName: "back"
311+ text: i18n.tr("Back")
312+ shortcut: "Esc"
313+ onTriggered: optionsPage.selected("")
314+ }
315+ ]
316+ flickable: pageView
317+ }
318+
319+ UbuntuListView {
320+ id: pageView
321+
322+ model: Object.keys(optionsPage.model)
323+ anchors.fill: parent
324+ currentIndex: optionsPage.indexOf(optionsPage.currentIndex)
325+ delegate: ListItem {
326+ ListItemLayout {
327+ title.text: optionsPage.model[modelData]
328+ }
329+ onClicked: optionsPage.selected(modelData)
330+ }
331+ }
332+
333+ onActiveChanged: this.forceActiveFocus()
334 }
335 }
336
337@@ -139,12 +302,6 @@
338 }
339 }
340
341- function createAccount()
342- {
343- if (onlineAccountHelper.item)
344- onlineAccountHelper.item.run()
345- }
346-
347 Loader {
348 id: onlineAccountHelper
349
350@@ -152,6 +309,4 @@
351 asynchronous: true
352 source: Qt.resolvedUrl("OnlineAccountsHelper.qml")
353 }
354-
355-
356 }
357
358=== modified file 'src/qml/ThreadDelegate.qml'
359--- src/qml/ThreadDelegate.qml 2016-11-22 15:03:31 +0000
360+++ src/qml/ThreadDelegate.qml 2017-03-22 20:49:22 +0000
361@@ -28,6 +28,7 @@
362 ListItem {
363 id: delegate
364
365+ property bool compactView: false
366 property var participant: participants ? participants[0] : {}
367 property bool groupChat: chatType == HistoryThreadModel.ChatTypeRoom || participants.length > 1
368 property string searchTerm
369@@ -119,9 +120,46 @@
370 }
371 return formatDisplayedText(displayedEventTextMessage)
372 }
373+
374+ state: compactView ? "compactView" : ""
375+ states: [
376+ State {
377+ name: "compactView"
378+ PropertyChanges {
379+ target: avatar
380+ visible: false
381+ height: 0
382+ width: 0
383+ }
384+ PropertyChanges {
385+ target: delegate
386+ height: units.gu(4)
387+ }
388+ PropertyChanges {
389+ target: latestMessage
390+ visible: false
391+ }
392+ PropertyChanges {
393+ target: protocolIcon
394+ visible: false
395+ }
396+ AnchorChanges {
397+ target: unreadCountIndicator
398+ anchors.left: contactName.left
399+ anchors.verticalCenter: contactName.verticalCenter
400+ anchors.right: undefined
401+ anchors.top: undefined
402+ anchors.bottom: undefined
403+ }
404+ AnchorChanges {
405+ target: contactName
406+ anchors.right: time.left
407+ }
408+ }
409+ ]
410 anchors.left: parent.left
411 anchors.right: parent.right
412- height: units.gu(10)
413+ height: units.gu(8)
414 divider.visible: false
415 contentItem.anchors {
416 leftMargin: units.gu(2)
417@@ -194,11 +232,12 @@
418 if (isBroadcast) {
419 return Qt.resolvedUrl("assets/broadcast_icon.png")
420 } else if (groupChat) {
421- return Qt.resolvedUrl("assets/group_icon.png")
422+ return "image://theme/contact-group"
423 }
424- return ""
425+ return "image://theme/contact"
426 }
427 asynchronous: true
428+ sourceSize.height: units.gu(2)
429 }
430
431 Label {
432@@ -207,12 +246,12 @@
433 top: avatar.top
434 topMargin: units.gu(0.5)
435 left: chatTypeIcon.right
436- leftMargin: chatTypeIcon.visible ? units.gu(0.5) : 0
437 right: time.left
438+ rightMargin: unreadCountIndicator.width
439 }
440 elide: Text.ElideRight
441 color: Theme.palette.normal.backgroundText
442- font.bold: unreadCountIndicator.visible
443+ font.bold: unreadCount > 0
444 text: {
445 if (groupChat) {
446 return groupChatLabel
447@@ -285,7 +324,7 @@
448 top: avatar.top
449 topMargin: units.gu(-0.5)
450 left: avatar.left
451- leftMargin: units.gu(-0.5)
452+ leftMargin: delegate.state == "compactView" ? contactName.paintedWidth + units.gu(0.5) : units.gu(-0.5)
453 }
454 z: 1
455 visible: unreadCount > 0
456
457=== modified file 'src/qml/ThreadsSectionDelegate.qml'
458--- src/qml/ThreadsSectionDelegate.qml 2016-10-14 14:00:18 +0000
459+++ src/qml/ThreadsSectionDelegate.qml 2017-03-22 20:49:22 +0000
460@@ -23,6 +23,12 @@
461
462 Item {
463 id: threadsSectionDelegate
464+
465+ function formatSectionTitle(title)
466+ {
467+ return title
468+ }
469+
470 anchors {
471 left: parent.left
472 right: parent.right
473@@ -32,7 +38,7 @@
474 Label {
475 anchors.fill: parent
476 elide: Text.ElideRight
477- text: DateUtils.friendlyDay(Qt.formatDate(section, "yyyy/MM/dd"), i18n);
478+ text: formatSectionTitle(section)
479 verticalAlignment: Text.AlignVCenter
480 fontSize: "small"
481 color: Theme.palette.normal.backgroundTertiaryText
482
483=== modified file 'src/qml/messaging-app.qml'
484--- src/qml/messaging-app.qml 2017-03-22 20:49:22 +0000
485+++ src/qml/messaging-app.qml 2017-03-22 20:49:22 +0000
486@@ -36,6 +36,10 @@
487 property bool dualPanel: mainStack.columns > 1
488 property bool composingNewMessage: activeMessagesView && activeMessagesView.newMessage
489 property QtObject activeMessagesView: null
490+ // settings
491+ property alias sortThreadsBy: globalSettings.sortThreadsBy
492+ property alias compactView: globalSettings.compactView
493+ // private
494 property var _pendingProperties: null
495
496 function updateNewMessageStatus() {
497@@ -200,8 +204,25 @@
498
499 type: HistoryThreadModel.EventTypeText
500 sort: HistorySort {
501- sortField: "lastEventTimestamp"
502- sortOrder: HistorySort.DescendingOrder
503+ sortField: {
504+ switch(mainView.sortThreadsBy) {
505+ case "title":
506+ //FIXME: ThreadId works for IRC, not sure if that will work for other protocols
507+ return "accountId, threadId"
508+ case "timestamp":
509+ default:
510+ return "lastEventTimestamp"
511+ }
512+ }
513+ sortOrder: {
514+ switch(mainView.sortThreadsBy) {
515+ case "title":
516+ return HistorySort.AscendingOrder
517+ case "timestamp":
518+ default:
519+ return HistorySort.DescendingOrder
520+ }
521+ }
522 }
523 groupingProperty: "participants"
524 filter: HistoryFilter {}
525@@ -222,6 +243,12 @@
526 property bool showCharacterCount: false
527 }
528
529+ Settings {
530+ id: globalSettings
531+ property string sortThreadsBy: "timestamp"
532+ property bool compactView: false
533+ }
534+
535 StickerPacksModel {
536 id: stickerPacksModel
537 }

Subscribers

People subscribed via source and target branches

to all changes: