Merge lp:~ahayzen/music-app/now-playing-split-take-2 into lp:music-app/trusty
- now-playing-split-take-2
- Merge into trusty
Status: | Rejected |
---|---|
Rejected by: | Andrew Hayzen |
Proposed branch: | lp:~ahayzen/music-app/now-playing-split-take-2 |
Merge into: | lp:music-app/trusty |
Diff against target: |
1345 lines (+647/-631) 4 files modified
MusicNowPlaying.qml (+179/-622) MusicToolbar.qml (+2/-1) common/Queue.qml (+455/-0) music-app.qml (+11/-8) |
To merge this branch: | bzr merge lp:~ahayzen/music-app/now-playing-split-take-2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Needs Fixing | |
Andrew Hayzen | Needs Information | ||
Review via email: mp+226720@code.launchpad.net |
Commit message
* Split now playing and queue into separate subtabs
* Make a common/Queue.qml component which is reusable (for convergence later)
Description of the change
* Split now playing and queue into separate subtabs
* Make a common/Queue.qml component which is reusable (for convergence later)
This mp is to see the diff, and for any design/behaviour discussions NOT for code merging...yet ;)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:521
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Andrew Hayzen (ahayzen) wrote : | # |
Marking as WIP as I am going to defer this for now.
Unmerged revisions
- 521. By Andrew Hayzen
-
* Add support for MusicRow in Queue.qml
- 520. By Andrew Hayzen
-
* Merge of trunk
- 519. By Andrew Hayzen
-
* Fix to only jump to current if toolbar was raised on queue subtab
- 518. By Andrew Hayzen
-
* Performance tweaks
- 517. By Andrew Hayzen
-
* Switch to now playing when track selected from queue
* Toggle playback if current track is selected
* Fix for header not being shown correctly on now playing subtab
* Force toolbar to show when navigating to now playing - 516. By Andrew Hayzen
-
* Don't ensureVisible when clicking on queue
* Animate queue highlight to fade in/out
* Switch to now playing if current track play - 515. By Andrew Hayzen
-
* Tweaks to now playing page
* Fix to removing current track - 514. By Andrew Hayzen
-
* Add common/Queue.qml to bzr
- 513. By Andrew Hayzen
-
* Split now playing and queue into separate subtabs
* Make a common/Queue.qml component which is reusable (for convergence later)
Preview Diff
1 | === modified file 'MusicNowPlaying.qml' |
2 | --- MusicNowPlaying.qml 2014-06-24 19:35:57 +0000 |
3 | +++ MusicNowPlaying.qml 2014-07-14 17:57:04 +0000 |
4 | @@ -30,12 +30,21 @@ |
5 | |
6 | MusicPage { |
7 | id: nowPlaying |
8 | + flickable: queueSelected ? queueList : nowPlayingFlick |
9 | objectName: "nowplayingpage" |
10 | title: i18n.tr("Now Playing") |
11 | visible: false |
12 | |
13 | - property int ensureVisibleIndex: 0 // ensure first index is visible at startup |
14 | - |
15 | + onVisibleChanged: { |
16 | + if (visible && !nowPlayingHeader.queueSelected) { |
17 | + musicToolbar.showToolbar(); |
18 | + } |
19 | + } |
20 | + |
21 | + property alias ensureVisibleIndex: queueList.ensureVisibleIndex |
22 | + property alias queueSelected: nowPlayingHeader.queueSelected |
23 | + |
24 | + /* Main background */ |
25 | Rectangle { |
26 | anchors.fill: parent |
27 | color: styleMusic.nowPlaying.backgroundColor |
28 | @@ -45,629 +54,177 @@ |
29 | } |
30 | } |
31 | |
32 | - Component.onCompleted: { |
33 | - onToolbarShownChanged.connect(jumpToCurrent) |
34 | + /* Queue section */ |
35 | + Queue { |
36 | + id: queueList |
37 | + anchors { |
38 | + bottomMargin: musicToolbar.currentHeight |
39 | + fill: parent |
40 | + topMargin: nowPlayingHeader.height |
41 | + } |
42 | + clip: false |
43 | + onMovementStarted: musicToolbar.hideToolbar() |
44 | + visible: nowPlayingHeader.queueSelected |
45 | } |
46 | |
47 | Connections { |
48 | - target: player |
49 | - onCurrentIndexChanged: { |
50 | - if (player.source === "") { |
51 | - return; |
52 | - } |
53 | - |
54 | - collapseExpand(); // Collapse expanded tracks |
55 | - queuelist.currentIndex = player.currentIndex; |
56 | - |
57 | - customdebug("MusicQueue update currentIndex: " + player.source); |
58 | - |
59 | - // Always jump to current track |
60 | - nowPlaying.jumpToCurrent(musicToolbar.opened, nowPlaying, musicToolbar.currentTab) |
61 | - |
62 | - } |
63 | - } |
64 | - |
65 | - function jumpToCurrent(shown, currentPage, currentTab) |
66 | - { |
67 | - // If the toolbar is shown, the page is now playing and snaptrack is enabled |
68 | - if (shown && currentPage === nowPlaying && Settings.getSetting("snaptrack") === "1") |
69 | - { |
70 | - // Then position the view at the current index |
71 | - queuelist.positionViewAtIndex(queuelist.currentIndex, ListView.Beginning); |
72 | - } |
73 | - } |
74 | - |
75 | - function positionAt(index) { |
76 | - queuelist.positionViewAtIndex(index, ListView.Beginning); |
77 | - queuelist.contentY -= header.height; |
78 | - } |
79 | - |
80 | - ListView { |
81 | - id: queuelist |
82 | - objectName: "queuelist" |
83 | - anchors.fill: parent |
84 | - anchors.bottomMargin: musicToolbar.mouseAreaOffset + musicToolbar.minimizedHeight |
85 | - spacing: units.gu(1) |
86 | - delegate: queueDelegate |
87 | - model: trackQueue.model |
88 | - highlightFollowsCurrentItem: false |
89 | - state: "normal" |
90 | - states: [ |
91 | - State { |
92 | - name: "normal" |
93 | - PropertyChanges { |
94 | - target: queuelist |
95 | - interactive: true |
96 | - } |
97 | - }, |
98 | - State { |
99 | - name: "reorder" |
100 | - PropertyChanges { |
101 | - target: queuelist |
102 | - interactive: false |
103 | - } |
104 | - } |
105 | - ] |
106 | - footer: Item { |
107 | - height: mainView.height - (styleMusic.common.expandHeight + queuelist.currentHeight) + units.gu(8) |
108 | - } |
109 | - |
110 | - property int normalHeight: units.gu(12) |
111 | - property int currentHeight: units.gu(48) |
112 | - property int transitionDuration: 250 // transition length of animations |
113 | - |
114 | - onCountChanged: { |
115 | - customdebug("Queue: Now has: " + queuelist.count + " tracks") |
116 | - } |
117 | - |
118 | - onMovementStarted: { |
119 | - musicToolbar.hideToolbar(); |
120 | - } |
121 | - |
122 | - Component { |
123 | - id: queueDelegate |
124 | - ListItem.Standard { |
125 | - id: queueListItem |
126 | - height: queuelist.normalHeight |
127 | - state: queuelist.currentIndex == index ? "current" : "" |
128 | - |
129 | - // cached height used to restore the height after expansion |
130 | - property int cachedHeight: -1 |
131 | - |
132 | - SwipeDelete { |
133 | - id: swipeBackground |
134 | - duration: queuelist.transitionDuration |
135 | - |
136 | - onDeleteStateChanged: { |
137 | - if (deleteState === true) |
138 | - { |
139 | - queueListItemRemoveAnimation.start(); |
140 | - } |
141 | - } |
142 | - } |
143 | - |
144 | - function onCollapseSwipeDelete(indexCol) |
145 | - { |
146 | - if ((indexCol !== index || indexCol === -1) && swipeBackground !== undefined && swipeBackground.direction !== "") |
147 | - { |
148 | - customdebug("auto collapse swipeDelete") |
149 | - queueListItemResetStartAnimation.start(); |
150 | - } |
151 | - } |
152 | - |
153 | - Component.onCompleted: { |
154 | - collapseSwipeDelete.connect(onCollapseSwipeDelete); |
155 | - } |
156 | - |
157 | - MouseArea { |
158 | - id: queueArea |
159 | - anchors.fill: parent |
160 | - |
161 | - property int startX: queueListItem.x |
162 | - property int startY: queueListItem.y |
163 | - property int startMouseY: -1 |
164 | - |
165 | - // Allow dragging on the X axis for swipeDelete if not reordering |
166 | - drag.target: queueListItem |
167 | - drag.axis: Drag.XAxis |
168 | - drag.minimumX: queuelist.state == "reorder" ? 0 : -queueListItem.width |
169 | - drag.maximumX: queuelist.state == "reorder" ? 0 : queueListItem.width |
170 | - |
171 | - /* Get the mouse and item difference from the starting positions */ |
172 | - function getDiff(mouseY) |
173 | - { |
174 | - return (mouseY - startMouseY) + (queueListItem.y - startY); |
175 | - } |
176 | - |
177 | - /* |
178 | - * Has the mouse crossed the current item |
179 | - * True - it has crossed |
180 | - * NULL - it is on the current |
181 | - * False - it has not crossed |
182 | - */ |
183 | - function hasCrossedCurrent(diff, currentOffset) |
184 | - { |
185 | - // Only crossed if in same direction |
186 | - if ((diff > 0 || currentOffset > 0) && (diff <= 0 || currentOffset <= 0)) |
187 | - { |
188 | - return false; |
189 | - } |
190 | - |
191 | - if (Math.abs(diff) > (Math.abs(currentOffset) * queuelist.normalHeight) + queuelist.currentHeight) |
192 | - { |
193 | - return true; |
194 | - } |
195 | - else if (Math.abs(diff) > (Math.abs(currentOffset) * queuelist.normalHeight)) |
196 | - { |
197 | - return null; |
198 | - } |
199 | - else |
200 | - { |
201 | - return false; |
202 | - } |
203 | - } |
204 | - |
205 | - function getNewIndex(mouseY, index) |
206 | - { |
207 | - var diff = getDiff(mouseY); |
208 | - var negPos = diff < 0 ? -1 : 1; |
209 | - var currentOffset = queuelist.currentIndex - index; // get the current offset |
210 | - |
211 | - if (currentOffset < 0) // when current is less the offset is actually +1 |
212 | - { |
213 | - currentOffset += 1; |
214 | - } |
215 | - |
216 | - var hasCrossed = hasCrossedCurrent(diff, currentOffset); |
217 | - |
218 | - if (hasCrossed === true) |
219 | - { |
220 | - /* Take off difference so it just appears like a normalheight |
221 | - * minus when after and add when before */ |
222 | - diff -= negPos * (queuelist.currentHeight - queuelist.normalHeight); |
223 | - } |
224 | - else if (hasCrossed === null) |
225 | - { |
226 | - // Work out how far into the current item it is |
227 | - var tmpDiff = Math.abs(diff) - (Math.abs(currentOffset) * queuelist.normalHeight); |
228 | - |
229 | - // Scale difference so is the same as a normalHeight |
230 | - tmpDiff *= (queuelist.normalHeight / queuelist.currentHeight); |
231 | - |
232 | - // rebuild Diff with new values |
233 | - diff = (currentOffset * queuelist.normalHeight) + (negPos * tmpDiff); |
234 | - } |
235 | - |
236 | - return index + (Math.round(diff / queuelist.normalHeight)); |
237 | - } |
238 | - |
239 | - onClicked: { |
240 | - collapseSwipeDelete(-1); // collapse all expands |
241 | - customdebug("File: " + model.filename) // debugger |
242 | - trackQueueClick(index); // toggle track state |
243 | - } |
244 | - |
245 | - onMouseXChanged: { |
246 | - // Only allow XChange if not in reorder state |
247 | - if (queuelist.state == "reorder") |
248 | - { |
249 | - return; |
250 | - } |
251 | - |
252 | - // New X is less than start so swiping left |
253 | - if (queueListItem.x < startX) |
254 | - { |
255 | - collapseExpand(); |
256 | - swipeBackground.state = "swipingLeft"; |
257 | - startY = queueListItem.y; |
258 | - } |
259 | - // New X is greater sow swiping right |
260 | - else if (queueListItem.x > startX) |
261 | - { |
262 | - collapseExpand(); |
263 | - swipeBackground.state = "swipingRight"; |
264 | - startY = queueListItem.y; |
265 | - } |
266 | - // Same so reset state back to normal |
267 | - else |
268 | - { |
269 | - swipeBackground.state = "normal"; |
270 | - queuelist.state = "normal"; |
271 | - } |
272 | - } |
273 | - |
274 | - onMouseYChanged: { |
275 | - // Y change only affects when in reorder mode |
276 | - if (queuelist.state == "reorder") |
277 | - { |
278 | - /* update the listitem y position so that the |
279 | - * listitem horizontalCenter is under the mouse.y */ |
280 | - queueListItem.y += mouse.y - (queueListItem.height / 2); |
281 | - } |
282 | - } |
283 | - |
284 | - onPressed: { |
285 | - startX = queueListItem.x; |
286 | - startY = queueListItem.y; |
287 | - startMouseY = mouse.y; |
288 | - } |
289 | - |
290 | - onPressAndHold: { |
291 | - // Must be in a normal state to change to reorder state |
292 | - if (queuelist.state == "normal" && swipeBackground.state == "normal" && queuelist.currentIndex != index) |
293 | - { |
294 | - collapseSwipeDelete(-1); // collapse all swipedeletes |
295 | - collapseExpand(); // collapse all |
296 | - customdebug("Pressed and held queued track "+model.filename) |
297 | - queuelist.state = "reorder"; // enable reordering state |
298 | - trackContainerReorderAnimation.start(); |
299 | - } |
300 | - } |
301 | - |
302 | - onReleased: { |
303 | - // Get current state to determine what to do |
304 | - if (queuelist.state == "reorder") |
305 | - { |
306 | - var newIndex = getNewIndex(mouse.y + (queueListItem.height / 2), index); // get new index |
307 | - |
308 | - // Indexes larger than current need -1 because when it is moved the current is removed |
309 | - if (newIndex > index) |
310 | - { |
311 | - newIndex -= 1; |
312 | - } |
313 | - |
314 | - if (newIndex === index) |
315 | - { |
316 | - queueListItemResetAnimation.start(); // reset item position |
317 | - trackContainerResetAnimation.start(); // reset the trackContainer |
318 | - } |
319 | - else |
320 | - { |
321 | - queueListItem.x = startX; // ensure X position is correct |
322 | - trackContainerResetAnimation.start(); // reset the trackContainer |
323 | - |
324 | - // Check that the newIndex is within the range |
325 | - if (newIndex < 0) |
326 | - { |
327 | - newIndex = 0; |
328 | - } |
329 | - else if (newIndex > queuelist.count - 1) |
330 | - { |
331 | - newIndex = queuelist.count - 1; |
332 | - } |
333 | - |
334 | - console.debug("Move: " + index + " To: " + newIndex); |
335 | - queuelist.model.move(index, newIndex, 1); // update the model |
336 | - } |
337 | - } |
338 | - else if (swipeBackground.state == "swipingLeft" || swipeBackground.state == "swipingRight") |
339 | - { |
340 | - var moved = Math.abs(queueListItem.x - startX); |
341 | - |
342 | - // Make sure that item has been dragged far enough |
343 | - if (moved > queueListItem.width / 2 || (swipeBackground.primed === true && moved > units.gu(5))) |
344 | - { |
345 | - if (swipeBackground.primed === false) |
346 | - { |
347 | - collapseSwipeDelete(index); // collapse other swipeDeletes |
348 | - |
349 | - // Move the listitem half way across to reveal the delete button |
350 | - queueListItemPrepareRemoveAnimation.start(); |
351 | - } |
352 | - else |
353 | - { |
354 | - // Check that actually swiping to cancel |
355 | - if (swipeBackground.direction !== "" && |
356 | - swipeBackground.direction !== swipeBackground.state) |
357 | - { |
358 | - // Reset the listitem to the centre |
359 | - queueListItemResetStartAnimation.start(); |
360 | - } |
361 | - else |
362 | - { |
363 | - // Reset the listitem to the centre |
364 | - queueListItemResetAnimation.start(); |
365 | - } |
366 | - } |
367 | - } |
368 | - else |
369 | - { |
370 | - // Reset the listitem to the centre |
371 | - queueListItemResetAnimation.start(); |
372 | - } |
373 | - } |
374 | - |
375 | - // ensure states are normal |
376 | - swipeBackground.state = "normal"; |
377 | - queuelist.state = "normal"; |
378 | - } |
379 | - |
380 | - // Animation to reset the x, y of the queueitem |
381 | - ParallelAnimation { |
382 | - id: queueListItemResetAnimation |
383 | - running: false |
384 | - NumberAnimation { // reset X |
385 | - target: queueListItem |
386 | - property: "x" |
387 | - to: queueArea.startX |
388 | - duration: queuelist.transitionDuration |
389 | - } |
390 | - NumberAnimation { // reset Y |
391 | - target: queueListItem |
392 | - property: "y" |
393 | - to: queueArea.startY |
394 | - duration: queuelist.transitionDuration |
395 | - } |
396 | - } |
397 | - |
398 | - // Animation to reset the x, y of the item |
399 | - ParallelAnimation { |
400 | - id: queueListItemResetStartAnimation |
401 | - running: false |
402 | - NumberAnimation { // reset X |
403 | - target: queueListItem |
404 | - property: "x" |
405 | - to: 0 |
406 | - duration: queuelist.transitionDuration |
407 | - } |
408 | - NumberAnimation { // reset Y |
409 | - target: queueListItem |
410 | - property: "y" |
411 | - to: queueArea.startY |
412 | - duration: queuelist.transitionDuration |
413 | - } |
414 | - onRunningChanged: { |
415 | - if (running === true) |
416 | - { |
417 | - swipeBackground.direction = ""; |
418 | - swipeBackground.primed = false; |
419 | - } |
420 | - } |
421 | - } |
422 | - |
423 | - // Move the listitem half way across to reveal the delete button |
424 | - NumberAnimation { |
425 | - id: queueListItemPrepareRemoveAnimation |
426 | - target: queueListItem |
427 | - property: "x" |
428 | - to: swipeBackground.state == "swipingRight" ? queueListItem.width / 2 : 0 - (queueListItem.width / 2) |
429 | - duration: queuelist.transitionDuration |
430 | - onRunningChanged: { |
431 | - if (running === true) |
432 | - { |
433 | - swipeBackground.direction = swipeBackground.state; |
434 | - swipeBackground.primed = true; |
435 | - } |
436 | - } |
437 | - } |
438 | - |
439 | - ParallelAnimation { |
440 | - id: queueListItemRemoveAnimation |
441 | - running: false |
442 | - NumberAnimation { // 'slide' up |
443 | - target: queueListItem |
444 | - property: "height" |
445 | - to: 0 |
446 | - duration: queuelist.transitionDuration |
447 | - } |
448 | - NumberAnimation { // 'slide' in direction of removal |
449 | - target: queueListItem |
450 | - property: "x" |
451 | - to: swipeBackground.direction === "swipingLeft" ? 0 - queueListItem.width : queueListItem.width |
452 | - duration: queuelist.transitionDuration |
453 | - } |
454 | - onRunningChanged: { |
455 | - if (running === false) |
456 | - { |
457 | - // Remove the item |
458 | - if (index == queuelist.currentIndex) |
459 | - { |
460 | - if (queuelist.count > 1) |
461 | - { |
462 | - // Next song and only play if currently playing |
463 | - player.nextSong(player.isPlaying); |
464 | - } |
465 | - else |
466 | - { |
467 | - player.stop(); |
468 | - } |
469 | - } |
470 | - |
471 | - if (index < player.currentIndex) { |
472 | - player.currentIndex -= 1; |
473 | - } |
474 | - |
475 | - // Remove item from queue and clear caches |
476 | - trackQueue.model.remove(index); |
477 | - } |
478 | - } |
479 | - } |
480 | - } |
481 | - |
482 | - onFocusChanged: { |
483 | - if (focus == false) { |
484 | - selected = false |
485 | - } else { |
486 | - selected = false |
487 | - } |
488 | - } |
489 | - |
490 | - Rectangle { |
491 | - id: trackContainer; |
492 | - anchors { |
493 | - fill: parent |
494 | - margins: units.gu(0.5) |
495 | - rightMargin: expandable.expanderButtonWidth |
496 | - } |
497 | - color: "transparent" |
498 | - |
499 | - NumberAnimation { |
500 | - id: trackContainerReorderAnimation |
501 | - target: trackContainer; |
502 | - property: "anchors.leftMargin"; |
503 | - duration: queuelist.transitionDuration; |
504 | - to: units.gu(2) |
505 | - } |
506 | - |
507 | - NumberAnimation { |
508 | - id: trackContainerResetAnimation |
509 | - target: trackContainer; |
510 | - property: "anchors.leftMargin"; |
511 | - duration: queuelist.transitionDuration; |
512 | - to: units.gu(0.5) |
513 | - } |
514 | - |
515 | - UbuntuShape { |
516 | - id: trackImage |
517 | - anchors.left: parent.left |
518 | - anchors.leftMargin: units.gu(1.5) |
519 | - anchors.top: parent.top |
520 | - height: (queueListItem.state === "current" ? queuelist.currentHeight - units.gu(8) : queuelist.normalHeight) - units.gu(2) |
521 | - width: height |
522 | - image: Image { |
523 | - source: "image://albumart/artist=" + model.author + "&album=" + model.album |
524 | - onStatusChanged: { |
525 | - if (status === Image.Error) { |
526 | - source = Qt.resolvedUrl("images/music-app-cover@30.png") |
527 | - } |
528 | - } |
529 | - } |
530 | - |
531 | - function calcAnchors() { |
532 | - if (trackImage.height > queuelist.normalHeight && mainView.wideAspect) { |
533 | - trackImage.anchors.left = undefined |
534 | - trackImage.anchors.horizontalCenter = trackImage.parent.horizontalCenter |
535 | - } else { |
536 | - trackImage.anchors.left = trackImage.parent.left |
537 | - trackImage.anchors.horizontalCenter = undefined |
538 | - } |
539 | - |
540 | - trackImage.width = trackImage.height; // force width to match height |
541 | - } |
542 | - |
543 | - Connections { |
544 | - target: mainView |
545 | - onWideAspectChanged: trackImage.calcAnchors() |
546 | - } |
547 | - |
548 | - onHeightChanged: { |
549 | - calcAnchors() |
550 | - } |
551 | - Behavior on height { |
552 | - NumberAnimation { |
553 | - target: trackImage; |
554 | - property: "height"; |
555 | - duration: queuelist.transitionDuration; |
556 | - } |
557 | - } |
558 | - } |
559 | - Label { |
560 | - id: nowPlayingArtist |
561 | - objectName: "nowplayingartist" |
562 | - color: styleMusic.nowPlaying.labelSecondaryColor |
563 | - elide: Text.ElideRight |
564 | - height: units.gu(1) |
565 | - text: model.author |
566 | - fontSize: 'small' |
567 | - width: parent.width - trackImage.width - units.gu(3.5) |
568 | - x: trackImage.x + trackImage.width + units.gu(1) |
569 | - y: trackImage.y + units.gu(1) |
570 | - } |
571 | - Label { |
572 | - id: nowPlayingTitle |
573 | - objectName: "nowplayingtitle" |
574 | - color: styleMusic.common.white |
575 | - elide: Text.ElideRight |
576 | - height: units.gu(1) |
577 | - text: model.title |
578 | - fontSize: 'medium' |
579 | - width: parent.width - trackImage.width - units.gu(3.5) |
580 | - x: trackImage.x + trackImage.width + units.gu(1) |
581 | - y: nowPlayingArtist.y + nowPlayingArtist.height + units.gu(1.25) |
582 | - } |
583 | - Label { |
584 | - id: nowPlayingAlbum |
585 | - objectName: "nowplayingalbum" |
586 | - color: styleMusic.nowPlaying.labelSecondaryColor |
587 | - elide: Text.ElideRight |
588 | - height: units.gu(1) |
589 | - text: model.album |
590 | - fontSize: 'x-small' |
591 | - width: parent.width - trackImage.width - units.gu(3.5) |
592 | - x: trackImage.x + trackImage.width + units.gu(1) |
593 | - y: nowPlayingTitle.y + nowPlayingTitle.height + units.gu(1.25) |
594 | - } |
595 | - } |
596 | - |
597 | - Expander { |
598 | - id: expandable |
599 | - anchors { |
600 | - fill: parent |
601 | - } |
602 | - actualListItemHeight: queueListItem.state === "current" ? |
603 | - queuelist.currentHeight : |
604 | - queuelist.normalHeight |
605 | - buttonEnabled: !swipeBackground.primed |
606 | - expanderButtonCentreFromBottom: queuelist.normalHeight - (trackContainer.anchors.margins * 2) - nowPlayingTitle.y - (nowPlayingTitle.height / 2) |
607 | - listItem: queueListItem |
608 | - model: trackQueue.model.get(index) |
609 | - row: Row { |
610 | - AddToPlaylist { |
611 | - } |
612 | - } |
613 | - Behavior on actualListItemHeight { |
614 | - NumberAnimation { |
615 | - target: expandable; |
616 | - property: "actualListItemHeight"; |
617 | - duration: queuelist.transitionDuration; |
618 | - } |
619 | - } |
620 | - } |
621 | - |
622 | - states: State { |
623 | - name: "current" |
624 | - PropertyChanges { |
625 | - target: queueListItem |
626 | - height: queuelist.currentHeight |
627 | - } |
628 | - PropertyChanges { |
629 | - target: nowPlayingArtist |
630 | - width: trackImage.width |
631 | - x: trackImage.x |
632 | - y: trackImage.y + trackImage.height + units.gu(0.5) |
633 | - } |
634 | - PropertyChanges { |
635 | - target: nowPlayingTitle |
636 | - width: trackImage.width |
637 | - x: trackImage.x |
638 | - y: nowPlayingArtist.y + nowPlayingArtist.height + units.gu(1.25) |
639 | - } |
640 | - PropertyChanges { |
641 | - target: nowPlayingAlbum |
642 | - width: trackImage.width |
643 | - x: trackImage.x |
644 | - y: nowPlayingTitle.y + nowPlayingTitle.height + units.gu(1.25) |
645 | - } |
646 | - PropertyChanges { |
647 | - target: expandable |
648 | - expanderButtonCentreFromBottom: queuelist.currentHeight - (trackContainer.anchors.margins * 2) - nowPlayingTitle.y - (nowPlayingTitle.height / 2) |
649 | - } |
650 | - } |
651 | - transitions: Transition { |
652 | - from: ",current" |
653 | - to: "current," |
654 | - NumberAnimation { |
655 | - duration: queuelist.transitionDuration |
656 | - properties: "height,opacity,width,x,y" |
657 | - } |
658 | - |
659 | - onRunningChanged: { |
660 | - if (running === false && ensureVisibleIndex != -1) |
661 | - { |
662 | - queuelist.positionViewAtIndex(ensureVisibleIndex, ListView.Beginning); |
663 | - ensureVisibleIndex = -1; |
664 | - } |
665 | - } |
666 | + target: musicToolbar |
667 | + onOpenedChanged: { |
668 | + if (musicToolbar.opened && musicToolbar.currentPage === nowPlaying |
669 | + && queueSelected) { |
670 | + queueList.ensureVisibleIndex = -1; |
671 | + queueList.ensureVisibleIndex = player.currentIndex; |
672 | + } |
673 | + } |
674 | + } |
675 | + |
676 | + /* Now Playing section */ |
677 | + Flickable { |
678 | + id: nowPlayingFlick |
679 | + anchors { |
680 | + bottomMargin: musicToolbar.currentHeight |
681 | + fill: parent |
682 | + topMargin: nowPlayingHeader.height |
683 | + } |
684 | + contentHeight: trackContainer.height |
685 | + visible: !nowPlayingHeader.queueSelected |
686 | + |
687 | + Column { |
688 | + id: trackContainer; |
689 | + anchors { |
690 | + horizontalCenter: parent.horizontalCenter |
691 | + } |
692 | + spacing: units.gu(0.5) |
693 | + |
694 | + // Top margin |
695 | + Rectangle { |
696 | + color: "transparent" |
697 | + height: units.gu(1) |
698 | + width: parent.width |
699 | + } |
700 | + |
701 | + UbuntuShape { |
702 | + id: trackImage |
703 | + height: units.gu(32) |
704 | + width: height |
705 | + image: Image { |
706 | + source: "image://albumart/artist=" + player.currentMetaArtist + "&album=" + player.currentMetaAlbum |
707 | + onStatusChanged: { |
708 | + if (status === Image.Error) { |
709 | + source = Qt.resolvedUrl("images/music-app-cover@30.png") |
710 | + } |
711 | + } |
712 | + } |
713 | + } |
714 | + Label { |
715 | + id: nowPlayingArtist |
716 | + objectName: "nowplayingartist" |
717 | + color: styleMusic.nowPlaying.labelSecondaryColor |
718 | + elide: Text.ElideRight |
719 | + text: player.currentMetaArtist |
720 | + fontSize: 'small' |
721 | + width: parent.width |
722 | + } |
723 | + Label { |
724 | + id: nowPlayingTitle |
725 | + objectName: "nowplayingtitle" |
726 | + color: styleMusic.common.white |
727 | + elide: Text.ElideRight |
728 | + text: player.currentMetaTitle |
729 | + fontSize: 'medium' |
730 | + width: parent.width |
731 | + } |
732 | + Label { |
733 | + id: nowPlayingAlbum |
734 | + objectName: "nowplayingalbum" |
735 | + color: styleMusic.nowPlaying.labelSecondaryColor |
736 | + elide: Text.ElideRight |
737 | + text: player.currentMetaAlbum |
738 | + fontSize: 'x-small' |
739 | + width: parent.width |
740 | + } |
741 | + } |
742 | + |
743 | + MouseArea { |
744 | + anchors { |
745 | + fill: trackContainer |
746 | + } |
747 | + onClicked: player.toggle() |
748 | + } |
749 | + } |
750 | + |
751 | + /* Header section */ |
752 | + Rectangle { |
753 | + id: nowPlayingHeader |
754 | + anchors { |
755 | + left: parent.left |
756 | + right: parent.right |
757 | + top: parent.top |
758 | + topMargin: header.height + header.y // FIXME: minor hack |
759 | + } |
760 | + color: "transparent" |
761 | + height: units.gu(5) |
762 | + |
763 | + property bool queueSelected: true |
764 | + |
765 | + onQueueSelectedChanged: { |
766 | + if (!queueSelected) { |
767 | + musicToolbar.showToolbar(); |
768 | + } |
769 | + } |
770 | + |
771 | + Rectangle { |
772 | + anchors { |
773 | + fill: parent |
774 | + } |
775 | + color: styleMusic.nowPlaying.backgroundColor |
776 | + opacity: 0.75 |
777 | + } |
778 | + |
779 | + Row { |
780 | + anchors { |
781 | + fill: parent |
782 | + } |
783 | + Label { |
784 | + anchors { |
785 | + top: parent.top |
786 | + bottom: parent.bottom |
787 | + } |
788 | + color: nowPlayingHeader.queueSelected ? UbuntuColors.orange : UbuntuColors.warmGrey |
789 | + horizontalAlignment: Text.AlignHCenter |
790 | + text: i18n.tr("Queue") |
791 | + verticalAlignment: Text.AlignVCenter |
792 | + width: parent.width / 2 |
793 | + |
794 | + MouseArea { |
795 | + anchors.fill: parent |
796 | + onClicked: nowPlayingHeader.queueSelected = true |
797 | + } |
798 | + } |
799 | + |
800 | + Rectangle { |
801 | + anchors { |
802 | + top: parent.top |
803 | + bottom: parent.bottom |
804 | + margins: units.gu(1) |
805 | + } |
806 | + width: 1 |
807 | + } |
808 | + |
809 | + Label { |
810 | + anchors { |
811 | + top: parent.top |
812 | + bottom: parent.bottom |
813 | + } |
814 | + color: !nowPlayingHeader.queueSelected ? UbuntuColors.orange : UbuntuColors.warmGrey |
815 | + horizontalAlignment: Text.AlignHCenter |
816 | + text: i18n.tr("Now Playing") |
817 | + verticalAlignment: Text.AlignVCenter |
818 | + width: parent.width / 2 |
819 | + |
820 | + MouseArea { |
821 | + anchors.fill: parent |
822 | + onClicked: nowPlayingHeader.queueSelected = false |
823 | } |
824 | } |
825 | } |
826 | |
827 | === modified file 'MusicToolbar.qml' |
828 | --- MusicToolbar.qml 2014-07-02 22:28:59 +0000 |
829 | +++ MusicToolbar.qml 2014-07-14 17:57:04 +0000 |
830 | @@ -42,12 +42,13 @@ |
831 | property bool shown: false |
832 | property int transitionDuration: 100 |
833 | |
834 | - property alias currentHeight: musicToolbarPanel.height |
835 | property alias minimizedHeight: musicToolbarPanel.minimizedHeight |
836 | property alias expandedHeight: musicToolbarPanel.expandedHeight |
837 | property alias fullHeight: musicToolbarPanel.fullHeight |
838 | property alias mouseAreaOffset: musicToolbarPanel.hintSize |
839 | |
840 | + property int currentHeight: opened ? musicToolbarPanel.height : minimizedHeight |
841 | + |
842 | property alias animating: musicToolbarPanel.animating |
843 | property alias opened: musicToolbarPanel.opened |
844 | |
845 | |
846 | === added file 'common/Queue.qml' |
847 | --- common/Queue.qml 1970-01-01 00:00:00 +0000 |
848 | +++ common/Queue.qml 2014-07-14 17:57:04 +0000 |
849 | @@ -0,0 +1,455 @@ |
850 | +/* |
851 | + * Copyright (C) 2014 Andrew Hayzen <ahayzen@gmail.com> |
852 | + * Daniel Holm <d.holmen@gmail.com> |
853 | + * Victor Thompson <victor.thompson@gmail.com> |
854 | + * |
855 | + * This program is free software; you can redistribute it and/or modify |
856 | + * it under the terms of the GNU General Public License as published by |
857 | + * the Free Software Foundation; version 3. |
858 | + * |
859 | + * This program is distributed in the hope that it will be useful, |
860 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
861 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
862 | + * GNU General Public License for more details. |
863 | + * |
864 | + * You should have received a copy of the GNU General Public License |
865 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
866 | + */ |
867 | + |
868 | +import QtQuick 2.0 |
869 | +import Ubuntu.Components 0.1 |
870 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
871 | +import "ExpanderItems" |
872 | + |
873 | +ListView { |
874 | + id: queueListView |
875 | + anchors { |
876 | + fill: parent |
877 | + } |
878 | + clip: true |
879 | + model: trackQueue.model |
880 | + state: "normal" |
881 | + states: [ |
882 | + State { |
883 | + name: "normal" |
884 | + PropertyChanges { |
885 | + target: queueListView |
886 | + interactive: true |
887 | + } |
888 | + }, |
889 | + State { |
890 | + name: "reorder" |
891 | + PropertyChanges { |
892 | + target: queueListView |
893 | + interactive: false |
894 | + } |
895 | + } |
896 | + ] |
897 | + |
898 | + property int ensureVisibleIndex: 0 // ensure first index is visible at startup |
899 | + property int normalHeight: styleMusic.common.itemHeight |
900 | + property int transitionDuration: 250 // transition length of animations |
901 | + |
902 | + onEnsureVisibleIndexChanged: { |
903 | + if (ensureVisibleIndex === -1) { |
904 | + return |
905 | + } |
906 | + |
907 | + queueListView.positionViewAtIndex(ensureVisibleIndex, ListView.Center); |
908 | + } |
909 | + |
910 | + delegate: ListItem.Standard { |
911 | + id: queueListItem |
912 | + height: styleMusic.common.itemHeight |
913 | + |
914 | + // cached height used to restore the height after expansion |
915 | + property int cachedHeight: -1 |
916 | + |
917 | + SwipeDelete { |
918 | + id: swipeBackground |
919 | + duration: queueListView.transitionDuration |
920 | + |
921 | + onDeleteStateChanged: { |
922 | + if (deleteState === true) { |
923 | + queueListItemRemoveAnimation.start(); |
924 | + } |
925 | + } |
926 | + } |
927 | + |
928 | + function onCollapseSwipeDelete(indexCol) |
929 | + { |
930 | + if ((indexCol !== index || indexCol === -1) && swipeBackground !== undefined && swipeBackground.direction !== "") { |
931 | + customdebug("auto collapse swipeDelete") |
932 | + queueListItemResetStartAnimation.start(); |
933 | + } |
934 | + } |
935 | + |
936 | + Component.onCompleted: { |
937 | + collapseSwipeDelete.connect(onCollapseSwipeDelete); |
938 | + } |
939 | + |
940 | + MouseArea { |
941 | + id: queueArea |
942 | + anchors.fill: parent |
943 | + |
944 | + property int startX: queueListItem.x |
945 | + property int startY: queueListItem.y |
946 | + property int startMouseY: -1 |
947 | + |
948 | + // Allow dragging on the X axis for swipeDelete if not reordering |
949 | + drag.target: queueListItem |
950 | + drag.axis: Drag.XAxis |
951 | + drag.minimumX: queueListView.state === "reorder" ? 0 : -queueListItem.width |
952 | + drag.maximumX: queueListView.state === "reorder" ? 0 : queueListItem.width |
953 | + |
954 | + /* Get the mouse and item difference from the starting positions */ |
955 | + function getDiff(mouseY) |
956 | + { |
957 | + return (mouseY - startMouseY) + (queueListItem.y - startY); |
958 | + } |
959 | + |
960 | + function getNewIndex(mouseY, index) |
961 | + { |
962 | + var diff = getDiff(mouseY); |
963 | + var negPos = diff < 0 ? -1 : 1; |
964 | + var currentOffset = queueListView.currentIndex - index; // get the current offset |
965 | + |
966 | + if (currentOffset < 0) // when current is less the offset is actually +1 |
967 | + { |
968 | + currentOffset += 1; |
969 | + } |
970 | + |
971 | + return index + (Math.round(diff / queueListView.normalHeight)); |
972 | + } |
973 | + |
974 | + onClicked: { |
975 | + collapseSwipeDelete(-1); // collapse all expands |
976 | + customdebug("File: " + model.filename) // debugger |
977 | + trackQueueClick(index) |
978 | + } |
979 | + |
980 | + onMouseXChanged: { |
981 | + // Only allow XChange if not in reorder state |
982 | + if (queueListView.state === "reorder") |
983 | + { |
984 | + return; |
985 | + } |
986 | + |
987 | + // New X is less than start so swiping left |
988 | + if (queueListItem.x < startX) |
989 | + { |
990 | + collapseExpand(); |
991 | + swipeBackground.state = "swipingLeft"; |
992 | + startY = queueListItem.y; |
993 | + } |
994 | + // New X is greater sow swiping right |
995 | + else if (queueListItem.x > startX) |
996 | + { |
997 | + collapseExpand(); |
998 | + swipeBackground.state = "swipingRight"; |
999 | + startY = queueListItem.y; |
1000 | + } |
1001 | + // Same so reset state back to normal |
1002 | + else |
1003 | + { |
1004 | + swipeBackground.state = "normal"; |
1005 | + queueListView.state = "normal"; |
1006 | + } |
1007 | + } |
1008 | + |
1009 | + onMouseYChanged: { |
1010 | + // Y change only affects when in reorder mode |
1011 | + if (queueListView.state === "reorder") |
1012 | + { |
1013 | + /* update the listitem y position so that the |
1014 | + * listitem horizontalCenter is under the mouse.y */ |
1015 | + queueListItem.y += mouse.y - (queueListItem.height / 2); |
1016 | + } |
1017 | + } |
1018 | + |
1019 | + onPressed: { |
1020 | + startX = queueListItem.x; |
1021 | + startY = queueListItem.y; |
1022 | + startMouseY = mouse.y; |
1023 | + } |
1024 | + |
1025 | + onPressAndHold: { |
1026 | + // Must be in a normal state to change to reorder state |
1027 | + if (queueListView.state === "normal" && swipeBackground.state == "normal" && queueListView.currentIndex !== index) |
1028 | + { |
1029 | + collapseSwipeDelete(-1); // collapse all swipedeletes |
1030 | + collapseExpand(); // collapse all |
1031 | + customdebug("Pressed and held queued track "+model.filename) |
1032 | + queueListView.state = "reorder"; // enable reordering state |
1033 | + trackContainerReorderAnimation.start(); |
1034 | + } |
1035 | + } |
1036 | + |
1037 | + onReleased: { |
1038 | + // Get current state to determine what to do |
1039 | + if (queueListView.state === "reorder") |
1040 | + { |
1041 | + var newIndex = getNewIndex(mouse.y + (queueListItem.height / 2), index); // get new index |
1042 | + |
1043 | + // Indexes larger than current need -1 because when it is moved the current is removed |
1044 | + if (newIndex > index) |
1045 | + { |
1046 | + newIndex -= 1; |
1047 | + } |
1048 | + |
1049 | + if (newIndex === index) |
1050 | + { |
1051 | + queueListItemResetAnimation.start(); // reset item position |
1052 | + trackContainerResetAnimation.start(); // reset the trackContainer |
1053 | + } |
1054 | + else |
1055 | + { |
1056 | + queueListItem.x = startX; // ensure X position is correct |
1057 | + trackContainerResetAnimation.start(); // reset the trackContainer |
1058 | + |
1059 | + // Check that the newIndex is within the range |
1060 | + if (newIndex < 0) |
1061 | + { |
1062 | + newIndex = 0; |
1063 | + } |
1064 | + else if (newIndex > queueListView.count - 1) |
1065 | + { |
1066 | + newIndex = queueListView.count - 1; |
1067 | + } |
1068 | + |
1069 | + console.debug("Move: " + index + " To: " + newIndex); |
1070 | + queueListView.model.move(index, newIndex, 1); // update the model |
1071 | + } |
1072 | + } |
1073 | + else if (swipeBackground.state == "swipingLeft" || swipeBackground.state == "swipingRight") |
1074 | + { |
1075 | + var moved = Math.abs(queueListItem.x - startX); |
1076 | + |
1077 | + // Make sure that item has been dragged far enough |
1078 | + if (moved > queueListItem.width / 2 || (swipeBackground.primed === true && moved > units.gu(5))) |
1079 | + { |
1080 | + if (swipeBackground.primed === false) |
1081 | + { |
1082 | + collapseSwipeDelete(index); // collapse other swipeDeletes |
1083 | + |
1084 | + // Move the listitem half way across to reveal the delete button |
1085 | + queueListItemPrepareRemoveAnimation.start(); |
1086 | + } |
1087 | + else |
1088 | + { |
1089 | + // Check that actually swiping to cancel |
1090 | + if (swipeBackground.direction !== "" && |
1091 | + swipeBackground.direction !== swipeBackground.state) |
1092 | + { |
1093 | + // Reset the listitem to the centre |
1094 | + queueListItemResetStartAnimation.start(); |
1095 | + } |
1096 | + else |
1097 | + { |
1098 | + // Reset the listitem to the centre |
1099 | + queueListItemResetAnimation.start(); |
1100 | + } |
1101 | + } |
1102 | + } |
1103 | + else |
1104 | + { |
1105 | + // Reset the listitem to the centre |
1106 | + queueListItemResetAnimation.start(); |
1107 | + } |
1108 | + } |
1109 | + |
1110 | + // ensure states are normal |
1111 | + swipeBackground.state = "normal"; |
1112 | + queueListView.state = "normal"; |
1113 | + } |
1114 | + |
1115 | + // Animation to reset the x, y of the queueitem |
1116 | + ParallelAnimation { |
1117 | + id: queueListItemResetAnimation |
1118 | + running: false |
1119 | + NumberAnimation { // reset X |
1120 | + target: queueListItem |
1121 | + property: "x" |
1122 | + to: queueArea.startX |
1123 | + duration: queueListView.transitionDuration |
1124 | + } |
1125 | + NumberAnimation { // reset Y |
1126 | + target: queueListItem |
1127 | + property: "y" |
1128 | + to: queueArea.startY |
1129 | + duration: queueListView.transitionDuration |
1130 | + } |
1131 | + } |
1132 | + |
1133 | + // Animation to reset the x, y of the item |
1134 | + ParallelAnimation { |
1135 | + id: queueListItemResetStartAnimation |
1136 | + running: false |
1137 | + NumberAnimation { // reset X |
1138 | + target: queueListItem |
1139 | + property: "x" |
1140 | + to: 0 |
1141 | + duration: queueListView.transitionDuration |
1142 | + } |
1143 | + NumberAnimation { // reset Y |
1144 | + target: queueListItem |
1145 | + property: "y" |
1146 | + to: queueArea.startY |
1147 | + duration: queueListView.transitionDuration |
1148 | + } |
1149 | + onRunningChanged: { |
1150 | + if (running === true) |
1151 | + { |
1152 | + swipeBackground.direction = ""; |
1153 | + swipeBackground.primed = false; |
1154 | + } |
1155 | + } |
1156 | + } |
1157 | + |
1158 | + // Move the listitem half way across to reveal the delete button |
1159 | + NumberAnimation { |
1160 | + id: queueListItemPrepareRemoveAnimation |
1161 | + target: queueListItem |
1162 | + property: "x" |
1163 | + to: swipeBackground.state == "swipingRight" ? queueListItem.width / 2 : 0 - (queueListItem.width / 2) |
1164 | + duration: queueListView.transitionDuration |
1165 | + onRunningChanged: { |
1166 | + if (running === true) |
1167 | + { |
1168 | + swipeBackground.direction = swipeBackground.state; |
1169 | + swipeBackground.primed = true; |
1170 | + } |
1171 | + } |
1172 | + } |
1173 | + |
1174 | + ParallelAnimation { |
1175 | + id: queueListItemRemoveAnimation |
1176 | + running: false |
1177 | + NumberAnimation { // 'slide' up |
1178 | + target: queueListItem |
1179 | + property: "height" |
1180 | + to: 0 |
1181 | + duration: queueListView.transitionDuration |
1182 | + } |
1183 | + NumberAnimation { // 'slide' in direction of removal |
1184 | + target: queueListItem |
1185 | + property: "x" |
1186 | + to: swipeBackground.direction === "swipingLeft" ? 0 - queueListItem.width : queueListItem.width |
1187 | + duration: queueListView.transitionDuration |
1188 | + } |
1189 | + onRunningChanged: { |
1190 | + if (running === false) |
1191 | + { |
1192 | + // Remove the item |
1193 | + if (index === player.currentIndex) |
1194 | + { |
1195 | + if (queueListView.count > 1) |
1196 | + { |
1197 | + // Next song and only play if currently playing |
1198 | + player.nextSong(player.isPlaying); |
1199 | + } |
1200 | + else |
1201 | + { |
1202 | + player.stop(); |
1203 | + } |
1204 | + } |
1205 | + |
1206 | + if (index < player.currentIndex) { |
1207 | + player.currentIndex -= 1; |
1208 | + } |
1209 | + |
1210 | + // Remove item from queue and clear caches |
1211 | + trackQueue.model.remove(index); |
1212 | + } |
1213 | + } |
1214 | + } |
1215 | + } |
1216 | + |
1217 | + Rectangle { |
1218 | + anchors { |
1219 | + left: parent.left |
1220 | + top: parent.top |
1221 | + } |
1222 | + height: parent.height |
1223 | + color: styleMusic.common.white |
1224 | + opacity: index === player.currentIndex ? 1 : 0 |
1225 | + width: units.gu(1) |
1226 | + visible: opacity !== 0 |
1227 | + |
1228 | + Behavior on opacity { |
1229 | + UbuntuNumberAnimation { |
1230 | + duration: UbuntuAnimation.SlowDuration |
1231 | + } |
1232 | + } |
1233 | + } |
1234 | + |
1235 | + MusicRow { |
1236 | + id: musicRow |
1237 | + anchors.leftMargin: units.gu(2) |
1238 | + covers: [{author: model.author, album: model.album}] |
1239 | + column: Column { |
1240 | + spacing: units.gu(1) |
1241 | + Label { |
1242 | + id: nowPlayingArtist |
1243 | + color: styleMusic.nowPlaying.labelSecondaryColor |
1244 | + fontSize: 'small' |
1245 | + objectName: "nowplayingartist" |
1246 | + text: model.author |
1247 | + } |
1248 | + |
1249 | + Label { |
1250 | + id: nowPlayingTitle |
1251 | + color: styleMusic.common.white |
1252 | + fontSize: 'medium' |
1253 | + objectName: "nowplayingtitle" |
1254 | + text: model.title |
1255 | + } |
1256 | + |
1257 | + Label { |
1258 | + id: nowPlayingAlbum |
1259 | + color: styleMusic.nowPlaying.labelSecondaryColor |
1260 | + fontSize: 'x-small' |
1261 | + objectName: "nowplayingalbum" |
1262 | + text: model.album |
1263 | + } |
1264 | + } |
1265 | + |
1266 | + NumberAnimation { |
1267 | + id: trackContainerReorderAnimation |
1268 | + target: musicRow |
1269 | + property: "anchors.leftMargin" |
1270 | + duration: queueListView.transitionDuration |
1271 | + to: units.gu(4) |
1272 | + } |
1273 | + |
1274 | + NumberAnimation { |
1275 | + id: trackContainerResetAnimation |
1276 | + target: musicRow |
1277 | + property: "anchors.leftMargin" |
1278 | + duration: queueListView.transitionDuration |
1279 | + to: units.gu(0.5) |
1280 | + } |
1281 | + } |
1282 | + |
1283 | + Expander { |
1284 | + id: expandable |
1285 | + anchors { |
1286 | + fill: parent |
1287 | + } |
1288 | + buttonEnabled: !swipeBackground.primed |
1289 | + listItem: queueListItem |
1290 | + model: trackQueue.model.get(index) |
1291 | + row: Row { |
1292 | + AddToPlaylist { |
1293 | + } |
1294 | + } |
1295 | + Behavior on actualListItemHeight { |
1296 | + NumberAnimation { |
1297 | + target: expandable; |
1298 | + property: "actualListItemHeight"; |
1299 | + duration: queueListView.transitionDuration; |
1300 | + } |
1301 | + } |
1302 | + } |
1303 | + } |
1304 | +} |
1305 | |
1306 | === modified file 'music-app.qml' |
1307 | --- music-app.qml 2014-07-13 21:11:11 +0000 |
1308 | +++ music-app.qml 2014-07-14 17:57:04 +0000 |
1309 | @@ -466,6 +466,8 @@ |
1310 | |
1311 | // Show the Now Playing page and make sure the track is visible |
1312 | tabs.pushNowPlaying(); |
1313 | + |
1314 | + nowPlaying.ensureVisibleIndex = -1; |
1315 | nowPlaying.ensureVisibleIndex = index; |
1316 | |
1317 | musicToolbar.showToolbar(); |
1318 | @@ -478,18 +480,19 @@ |
1319 | } |
1320 | |
1321 | function trackQueueClick(index) { |
1322 | - if (player.currentIndex === index) { |
1323 | - player.toggle(); |
1324 | - } |
1325 | - else { |
1326 | - player.playSong(trackQueue.model.get(index).filename, index); |
1327 | - } |
1328 | - |
1329 | // Show the Now Playing page and make sure the track is visible |
1330 | tabs.pushNowPlaying(); |
1331 | - nowPlaying.ensureVisibleIndex = index; |
1332 | + |
1333 | + nowPlaying.queueSelected = false; // swtich to now playing |
1334 | |
1335 | musicToolbar.showToolbar(); |
1336 | + |
1337 | + if (player.currentIndex !== index) { |
1338 | + player.playSong(trackQueue.model.get(index).filename, index); |
1339 | + } |
1340 | + else { |
1341 | + player.toggle(); |
1342 | + } |
1343 | } |
1344 | |
1345 | function playRandomSong(shuffle) |
Blocking as this needs design/behaviour input first.