Merge lp:~phablet-team/messaging-app/configure_sort into lp:messaging-app/staging
- configure_sort
- Merge into 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 |
Related bugs: |
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.
Description of the change
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
- 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 | } |
just one remark. looks good otherwise.