Merge lp:~nik90/ubuntu-clock-app/14-sync-listitem-actions-oct5 into lp:ubuntu-clock-app
- 14-sync-listitem-actions-oct5
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nekhelesh Ramananthan |
Approved revision: | 114 |
Merged at revision: | 137 |
Proposed branch: | lp:~nik90/ubuntu-clock-app/14-sync-listitem-actions-oct5 |
Merge into: | lp:ubuntu-clock-app |
Prerequisite: | lp:~nik90/ubuntu-clock-app/13-next-alarm-bottomedge |
Diff against target: |
376 lines (+147/-52) 3 files modified
app/upstreamcomponents/ListItemWithActions.qml (+130/-49) debian/changelog (+1/-0) tests/unit/tst_alarm.qml (+16/-3) |
To merge this branch: | bzr merge lp:~nik90/ubuntu-clock-app/14-sync-listitem-actions-oct5 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Nekhelesh Ramananthan | Approve | ||
Riccardo Padovani | Approve | ||
Review via email: mp+237189@code.launchpad.net |
Commit message
Just a regular sync of ListItemWithAct
Description of the change
Just a regular sync of ListItemWithAct
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Nekhelesh Ramananthan (nik90) wrote : | # |
#blocked on Jenkins. This requires a patch to the Jenkins environment since the xvfb package which is used to run the clock app tests takes input focus away from the clock app when it is launched. This is causing the AP tests to be pass. Francis and Nicholas have been informed. Once jenkins is fixed, we should be good to merge this branch.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:111
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:112
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
- 114. By Nekhelesh Ramananthan
-
Updated debian changelog
Nekhelesh Ramananthan (nik90) wrote : | # |
#unblocked Test failures fixed! Approving!
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:114
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'app/upstreamcomponents/ListItemWithActions.qml' |
2 | --- app/upstreamcomponents/ListItemWithActions.qml 2014-09-20 10:47:21 +0000 |
3 | +++ app/upstreamcomponents/ListItemWithActions.qml 2014-10-10 10:19:22 +0000 |
4 | @@ -34,63 +34,80 @@ |
5 | property alias internalAnchors: mainContents.anchors |
6 | default property alias contents: mainContents.children |
7 | |
8 | - readonly property double actionWidth: units.gu(5) |
9 | + readonly property double actionWidth: units.gu(4) |
10 | readonly property double leftActionWidth: units.gu(10) |
11 | readonly property double actionThreshold: actionWidth * 0.4 |
12 | readonly property double threshold: 0.4 |
13 | readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft" |
14 | readonly property alias swipping: mainItemMoving.running |
15 | + readonly property bool _showActions: mouseArea.pressed || swipeState != "Normal" || swipping |
16 | + |
17 | + /* internal */ |
18 | + property var _visibleRightSideActions: filterVisibleActions(rightSideActions) |
19 | |
20 | signal itemClicked(var mouse) |
21 | signal itemPressAndHold(var mouse) |
22 | |
23 | - function returnToBoundsRTL() |
24 | + function returnToBoundsRTL(direction) |
25 | { |
26 | var actionFullWidth = actionWidth + units.gu(2) |
27 | + |
28 | + // go back to normal state if swipping reverse |
29 | + if (direction === "LTR") { |
30 | + updatePosition(0) |
31 | + return |
32 | + } else if (!triggerActionOnMouseRelease) { |
33 | + updatePosition(-rightActionsView.width + units.gu(2)) |
34 | + return |
35 | + } |
36 | + |
37 | var xOffset = Math.abs(main.x) |
38 | - var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length) |
39 | - |
40 | - if (index < 1) { |
41 | - main.x = 0 |
42 | - } else if (index === rightSideActions.length) { |
43 | - main.x = -rightActionsView.width |
44 | - } else { |
45 | - main.x = -(actionFullWidth * index) |
46 | + var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length) |
47 | + var newX = 0 |
48 | + if (index === _visibleRightSideActions.length) { |
49 | + newX = -(rightActionsView.width - units.gu(2)) |
50 | + } else if (index >= 1) { |
51 | + newX = -(actionFullWidth * index) |
52 | } |
53 | + updatePosition(newX) |
54 | } |
55 | |
56 | - function returnToBoundsLTR() |
57 | + function returnToBoundsLTR(direction) |
58 | { |
59 | var finalX = leftActionWidth |
60 | - if (main.x > (finalX * root.threshold)) |
61 | - main.x = finalX |
62 | - else |
63 | - main.x = 0 |
64 | + if ((direction === "RTL") || (main.x <= (finalX * root.threshold))) |
65 | + finalX = 0 |
66 | + updatePosition(finalX) |
67 | } |
68 | |
69 | - function returnToBounds() |
70 | + function returnToBounds(direction) |
71 | { |
72 | if (main.x < 0) { |
73 | - returnToBoundsRTL() |
74 | + returnToBoundsRTL(direction) |
75 | } else if (main.x > 0) { |
76 | - returnToBoundsLTR() |
77 | + returnToBoundsLTR(direction) |
78 | + } else { |
79 | + updatePosition(0) |
80 | } |
81 | } |
82 | |
83 | - function contains(item, point) |
84 | + function contains(item, point, marginX) |
85 | { |
86 | - return (point.x >= item.x) && (point.x <= (item.x + item.width)) && (point.y >= item.y) && (point.y <= (item.y + item.height)); |
87 | + var itemStartX = item.x - marginX |
88 | + var itemEndX = item.x + item.width + marginX |
89 | + return (point.x >= itemStartX) && (point.x <= itemEndX) && |
90 | + (point.y >= item.y) && (point.y <= (item.y + item.height)); |
91 | } |
92 | |
93 | function getActionAt(point) |
94 | { |
95 | - if (contains(leftActionView, point)) { |
96 | + if (contains(leftActionView, point, 0)) { |
97 | return leftSideAction |
98 | - } else if (contains(rightActionsView, point)) { |
99 | + } else if (contains(rightActionsView, point, 0)) { |
100 | var newPoint = root.mapToItem(rightActionsView, point.x, point.y) |
101 | for (var i = 0; i < rightActionsRepeater.count; i++) { |
102 | var child = rightActionsRepeater.itemAt(i) |
103 | - if (contains(child, newPoint)) { |
104 | + if (contains(child, newPoint, units.gu(1))) { |
105 | return i |
106 | } |
107 | } |
108 | @@ -100,15 +117,16 @@ |
109 | |
110 | function updateActiveAction() |
111 | { |
112 | - if ((main.x <= -root.actionWidth) && |
113 | - (main.x > -rightActionsView.width)) { |
114 | + if (triggerActionOnMouseRelease && |
115 | + (main.x <= -(root.actionWidth + units.gu(2))) && |
116 | + (main.x > -(rightActionsView.width - units.gu(2)))) { |
117 | var actionFullWidth = actionWidth + units.gu(2) |
118 | var xOffset = Math.abs(main.x) |
119 | - var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length) |
120 | + var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length) |
121 | index = index - 1 |
122 | if (index > -1) { |
123 | root.activeItem = rightActionsRepeater.itemAt(index) |
124 | - root.activeAction = root.rightSideActions[index] |
125 | + root.activeAction = root._visibleRightSideActions[index] |
126 | } |
127 | } else { |
128 | root.activeAction = null |
129 | @@ -117,7 +135,29 @@ |
130 | |
131 | function resetSwipe() |
132 | { |
133 | - main.x = 0 |
134 | + updatePosition(0) |
135 | + } |
136 | + |
137 | + function filterVisibleActions(actions) |
138 | + { |
139 | + var visibleActions = [] |
140 | + for(var i = 0; i < actions.length; i++) { |
141 | + var action = actions[i] |
142 | + if (action.visible) { |
143 | + visibleActions.push(action) |
144 | + } |
145 | + } |
146 | + return visibleActions |
147 | + } |
148 | + |
149 | + function updatePosition(pos) |
150 | + { |
151 | + if (!root.triggerActionOnMouseRelease && (pos !== 0)) { |
152 | + mouseArea.state = pos > 0 ? "RightToLeft" : "LeftToRight" |
153 | + } else { |
154 | + mouseArea.state = "" |
155 | + } |
156 | + main.x = pos |
157 | } |
158 | |
159 | states: [ |
160 | @@ -153,45 +193,49 @@ |
161 | } |
162 | width: root.leftActionWidth + actionThreshold |
163 | visible: leftSideAction |
164 | - color: "red" |
165 | + color: UbuntuColors.red |
166 | |
167 | Icon { |
168 | anchors { |
169 | centerIn: parent |
170 | horizontalCenterOffset: actionThreshold / 2 |
171 | } |
172 | - name: leftSideAction ? leftSideAction.iconName : "" |
173 | + name: leftSideAction && _showActions ? leftSideAction.iconName : "" |
174 | color: Theme.palette.selected.field |
175 | height: units.gu(3) |
176 | width: units.gu(3) |
177 | } |
178 | } |
179 | |
180 | - Item { |
181 | + Rectangle { |
182 | id: rightActionsView |
183 | |
184 | anchors { |
185 | top: main.top |
186 | left: main.right |
187 | - leftMargin: units.gu(1) |
188 | bottom: main.bottom |
189 | } |
190 | - visible: rightSideActions.length > 0 |
191 | - width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + actionThreshold : 0 |
192 | + visible: _visibleRightSideActions.length > 0 |
193 | + width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + root.actionThreshold + units.gu(2) : 0 |
194 | + color: "white" |
195 | Row { |
196 | - anchors.fill: parent |
197 | + anchors{ |
198 | + top: parent.top |
199 | + left: parent.left |
200 | + leftMargin: units.gu(2) |
201 | + right: parent.right |
202 | + rightMargin: units.gu(2) |
203 | + bottom: parent.bottom |
204 | + } |
205 | spacing: units.gu(2) |
206 | Repeater { |
207 | id: rightActionsRepeater |
208 | |
209 | - model: rightSideActions |
210 | + model: _showActions ? _visibleRightSideActions : [] |
211 | Item { |
212 | property alias image: img |
213 | |
214 | - anchors { |
215 | - top: parent.top |
216 | - bottom: parent.bottom |
217 | - } |
218 | + height: rightActionsView.height |
219 | width: root.actionWidth |
220 | |
221 | Icon { |
222 | @@ -200,10 +244,10 @@ |
223 | anchors.centerIn: parent |
224 | width: units.gu(3) |
225 | height: units.gu(3) |
226 | - name: iconName |
227 | - color: root.activeAction === modelData || !root.triggerActionOnMouseRelease ? UbuntuColors.lightAubergine : Theme.palette.selected.background |
228 | + name: modelData.iconName |
229 | + color: root.activeAction === modelData ? UbuntuColors.lightAubergine : UbuntuColors.lightGrey |
230 | } |
231 | - } |
232 | + } |
233 | } |
234 | } |
235 | } |
236 | @@ -262,7 +306,6 @@ |
237 | } |
238 | } |
239 | Behavior on color { |
240 | - enabled: (root.color != root.selectedColor) |
241 | ColorAnimation {} |
242 | } |
243 | } |
244 | @@ -302,7 +345,10 @@ |
245 | value: 1.0 |
246 | } |
247 | ScriptAction { |
248 | - script: root.activeAction.triggered(root) |
249 | + script: { |
250 | + root.activeAction.triggered(root) |
251 | + mouseArea.state = "" |
252 | + } |
253 | } |
254 | PauseAnimation { |
255 | duration: 500 |
256 | @@ -318,24 +364,59 @@ |
257 | MouseArea { |
258 | id: mouseArea |
259 | |
260 | - property bool locked: root.locked || ((root.leftSideAction === null) && (root.rightSideActions.count === 0)) |
261 | + property bool locked: root.locked || ((root.leftSideAction === null) && (root._visibleRightSideActions.count === 0)) |
262 | property bool manual: false |
263 | + property string direction: "None" |
264 | + property real lastX: -1 |
265 | |
266 | anchors.fill: parent |
267 | drag { |
268 | target: locked ? null : main |
269 | axis: Drag.XAxis |
270 | - minimumX: rightActionsView.visible ? -(rightActionsView.width + root.actionThreshold) : 0 |
271 | + minimumX: rightActionsView.visible ? -(rightActionsView.width) : 0 |
272 | maximumX: leftActionView.visible ? leftActionView.width : 0 |
273 | + threshold: root.actionThreshold |
274 | + } |
275 | + |
276 | + states: [ |
277 | + State { |
278 | + name: "LeftToRight" |
279 | + PropertyChanges { |
280 | + target: mouseArea |
281 | + drag.maximumX: 0 |
282 | + } |
283 | + }, |
284 | + State { |
285 | + name: "RightToLeft" |
286 | + PropertyChanges { |
287 | + target: mouseArea |
288 | + drag.minimumX: 0 |
289 | + } |
290 | + } |
291 | + ] |
292 | + |
293 | + onMouseXChanged: { |
294 | + var offset = (lastX - mouseX) |
295 | + if (Math.abs(offset) <= root.actionThreshold) { |
296 | + return |
297 | + } |
298 | + lastX = mouseX |
299 | + direction = offset > 0 ? "RTL" : "LTR"; |
300 | + } |
301 | + |
302 | + onPressed: { |
303 | + lastX = mouse.x |
304 | } |
305 | |
306 | onReleased: { |
307 | if (root.triggerActionOnMouseRelease && root.activeAction) { |
308 | triggerAction.start() |
309 | } else { |
310 | - root.returnToBounds() |
311 | + root.returnToBounds(direction) |
312 | root.activeAction = null |
313 | } |
314 | + lastX = -1 |
315 | + direction = "None" |
316 | } |
317 | onClicked: { |
318 | if (main.x === 0) { |
319 | @@ -349,7 +430,7 @@ |
320 | var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y)) |
321 | if (actionIndex !== -1) { |
322 | root.activeItem = rightActionsRepeater.itemAt(actionIndex) |
323 | - root.activeAction = root.rightSideActions[actionIndex] |
324 | + root.activeAction = root._visibleRightSideActions[actionIndex] |
325 | triggerAction.start() |
326 | return |
327 | } |
328 | |
329 | === modified file 'debian/changelog' |
330 | --- debian/changelog 2014-10-09 19:14:27 +0000 |
331 | +++ debian/changelog 2014-10-10 10:19:22 +0000 |
332 | @@ -9,6 +9,7 @@ |
333 | * Design tweak to always show the remaining time to an alarm for one-time alarms |
334 | only. (LP: #1377538) |
335 | * Tweaked bottom edge to show the time to the next active alarm (LP: #1290793) |
336 | + * Synced ListItemWithActions with upstream |
337 | |
338 | [Akiva Shammai Avraham] |
339 | * Improved the analog clock performance by updating the clock hands every second |
340 | |
341 | === modified file 'tests/unit/tst_alarm.qml' |
342 | --- tests/unit/tst_alarm.qml 2014-10-05 16:00:28 +0000 |
343 | +++ tests/unit/tst_alarm.qml 2014-10-10 10:19:22 +0000 |
344 | @@ -174,6 +174,21 @@ |
345 | } |
346 | } |
347 | |
348 | + function _swipeToDeleteItem(item) |
349 | + { |
350 | + var startX = item.threshold |
351 | + var startY = item.height / 2 |
352 | + var endX = item.width |
353 | + var endY = startY |
354 | + mousePress(item, startX, startY) |
355 | + mouseMoveSlowly(item, |
356 | + startX, startY, |
357 | + endX - startX, endY - startY, |
358 | + 10, 100) |
359 | + mouseRelease(item, endX, endY) |
360 | + mouseClick(item, startX, startY) |
361 | + } |
362 | + |
363 | function _deleteAlarm(label, repeat, time, status) { |
364 | var alarmsList = findChild(alarmPage, "alarmListView") |
365 | var oldCount = alarmsList.count |
366 | @@ -182,9 +197,7 @@ |
367 | var alarmObject = findChild(alarmsList, "alarm"+index) |
368 | |
369 | if (index !== -1) { |
370 | - mouseDrag(alarmObject, alarmObject.width/4, alarmObject.height/2, units.gu(10), 0) |
371 | - mouseRelease(alarmObject, alarmObject.width/4+units.gu(10), alarmObject.height/2) |
372 | - mouseClick(alarmObject, units.gu(5), alarmObject.height/2) |
373 | + _swipeToDeleteItem(alarmObject) |
374 | } |
375 | |
376 | tryCompare(alarmsList, "count", oldCount-1, 10000, "Alarm count did not decrease after deleting the alarm") |
FAILED: Continuous integration, rev:110 91.189. 93.70:8080/ job/ubuntu- clock-app- ci/522/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic- python3/ 700/console 91.189. 93.70:8080/ job/ubuntu- clock-app- utopic- amd64-ci/ 169/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- clock-app- ci/522/ rebuild
http://