@@ -3,6 +3,14 @@ package com.malopieds.innertune.ui.player
3
3
import android.annotation.SuppressLint
4
4
import android.text.format.Formatter
5
5
import android.widget.Toast
6
+ import androidx.compose.animation.AnimatedVisibility
7
+ import androidx.compose.animation.animateContentSize
8
+ import androidx.compose.animation.expandVertically
9
+ import androidx.compose.animation.fadeIn
10
+ import androidx.compose.animation.fadeOut
11
+ import androidx.compose.animation.shrinkVertically
12
+ import androidx.compose.animation.slideInVertically
13
+ import androidx.compose.animation.slideOutVertically
6
14
import androidx.compose.foundation.ExperimentalFoundationApi
7
15
import androidx.compose.foundation.background
8
16
import androidx.compose.foundation.clickable
@@ -120,6 +128,9 @@ fun Queue(
120
128
121
129
val selectedSongs: MutableList <MediaMetadata > = mutableStateListOf()
122
130
val selectedItems: MutableList <Timeline .Window > = mutableStateListOf()
131
+ var selection by remember {
132
+ mutableStateOf(false )
133
+ }
123
134
124
135
var showDetailsDialog by rememberSaveable {
125
136
mutableStateOf(false )
@@ -278,6 +289,15 @@ fun Queue(
278
289
.reorderable(reorderableState)
279
290
.nestedScroll(state.preUpPostDownNestedScrollConnection),
280
291
) {
292
+ item {
293
+ Spacer (
294
+ modifier =
295
+ Modifier
296
+ .animateContentSize()
297
+ .height(if (selection) 64 .dp else 0 .dp),
298
+ )
299
+ }
300
+
281
301
itemsIndexed(
282
302
items = mutableQueueWindows,
283
303
key = { _, item -> item.uid.hashCode() },
@@ -308,40 +328,9 @@ fun Queue(
308
328
// state = dismissState,
309
329
// = {
310
330
) {
311
- Row (
312
- horizontalArrangement = Arrangement .Center ,
313
- ) {
314
- IconButton (
315
- modifier =
316
- Modifier
317
- .align(Alignment .CenterVertically ),
318
- onClick = {
319
- if (window.mediaItem.metadata!! in selectedSongs) {
320
- selectedSongs.remove(window.mediaItem.metadata!! )
321
- selectedItems.remove(currentItem)
322
- } else {
323
- selectedSongs.add(window.mediaItem.metadata!! )
324
- selectedItems.add(currentItem)
325
- }
326
- },
327
- ) {
328
- Icon (
329
- painter =
330
- painterResource(
331
- if (window.mediaItem.metadata!! in
332
- selectedSongs
333
- ) {
334
- R .drawable.check_box
335
- } else {
336
- R .drawable.uncheck_box
337
- },
338
- ),
339
- contentDescription = null ,
340
- tint = LocalContentColor .current,
341
- )
342
- }
343
331
MediaMetadataListItem (
344
332
mediaMetadata = window.mediaItem.metadata!! ,
333
+ isSelected = selection && window.mediaItem.metadata!! in selectedSongs,
345
334
isActive = index == currentWindowIndex,
346
335
isPlaying = isPlaying,
347
336
trailingContent = {
@@ -362,7 +351,15 @@ fun Queue(
362
351
.fillMaxWidth()
363
352
.combinedClickable(
364
353
onClick = {
365
- if (selectedSongs.isEmpty()) {
354
+ if (selection) {
355
+ if (window.mediaItem.metadata!! in selectedSongs) {
356
+ selectedSongs.remove(window.mediaItem.metadata!! )
357
+ selectedItems.remove(currentItem)
358
+ } else {
359
+ selectedSongs.add(window.mediaItem.metadata!! )
360
+ selectedItems.add(currentItem)
361
+ }
362
+ } else {
366
363
if (index == currentWindowIndex) {
367
364
playerConnection.player.togglePlayPause()
368
365
} else {
@@ -371,14 +368,6 @@ fun Queue(
371
368
)
372
369
playerConnection.player.playWhenReady = true
373
370
}
374
- } else {
375
- if (window.mediaItem.metadata!! in selectedSongs) {
376
- selectedSongs.remove(window.mediaItem.metadata!! )
377
- selectedItems.remove(currentItem)
378
- } else {
379
- selectedSongs.add(window.mediaItem.metadata!! )
380
- selectedItems.add(currentItem)
381
- }
382
371
}
383
372
},
384
373
onLongClick = {
@@ -398,13 +387,12 @@ fun Queue(
398
387
),
399
388
// .detectReorderAfterLongPress(reorderableState)
400
389
)
401
- }
402
390
}
403
391
}
404
392
}
405
393
}
406
394
407
- Box (
395
+ Column (
408
396
modifier =
409
397
Modifier
410
398
.background(
@@ -431,19 +419,80 @@ fun Queue(
431
419
modifier = Modifier .weight(1f ),
432
420
)
433
421
434
- if (selectedSongs.isNotEmpty()) {
422
+ AnimatedVisibility (
423
+ visible = ! selection,
424
+ enter = fadeIn() + slideInVertically { it },
425
+ exit = fadeOut() + slideOutVertically { it },
426
+ ) {
435
427
IconButton (
436
428
onClick = {
437
- selectedSongs.clear()
438
- selectedItems.clear()
429
+ selection = true
439
430
},
440
431
) {
441
432
Icon (
442
- painter = painterResource(R .drawable.deselect ),
433
+ painter = painterResource(R .drawable.select_all ),
443
434
contentDescription = null ,
444
- tint = LocalContentColor .current,
445
435
)
446
436
}
437
+ }
438
+
439
+ Column (
440
+ verticalArrangement = Arrangement .spacedBy(4 .dp),
441
+ horizontalAlignment = Alignment .End ,
442
+ ) {
443
+ Text (
444
+ text = pluralStringResource(R .plurals.n_song, queueWindows.size, queueWindows.size),
445
+ style = MaterialTheme .typography.bodyMedium,
446
+ )
447
+
448
+ Text (
449
+ text = makeTimeString(queueLength * 1000L ),
450
+ style = MaterialTheme .typography.bodyMedium,
451
+ )
452
+ }
453
+ }
454
+
455
+ AnimatedVisibility (
456
+ visible = selection,
457
+ enter = fadeIn() + expandVertically(),
458
+ exit = fadeOut() + shrinkVertically(),
459
+ ) {
460
+ Row (
461
+ modifier = Modifier
462
+ .height(64 .dp)
463
+ .padding(start = 16 .dp),
464
+ verticalAlignment = Alignment .CenterVertically ,
465
+ ) {
466
+ val count = selectedSongs.size
467
+ Text (text = " $count elements selected" , modifier = Modifier .weight(1f ))
468
+ IconButton (
469
+ onClick = {
470
+ if (count == mutableQueueWindows.size) {
471
+ selectedSongs.clear()
472
+ selectedItems.clear()
473
+ } else {
474
+ queueWindows
475
+ .filter { it.mediaItem.metadata!! !in selectedSongs }
476
+ .forEach {
477
+ selectedSongs.add(it.mediaItem.metadata!! )
478
+ selectedItems.add(it)
479
+ }
480
+ }
481
+ },
482
+ ) {
483
+ Icon (
484
+ painter =
485
+ painterResource(
486
+ if (count == mutableQueueWindows.size) {
487
+ R .drawable.deselect
488
+ } else {
489
+ R .drawable.select_all
490
+ },
491
+ ),
492
+ contentDescription = null ,
493
+ )
494
+ }
495
+
447
496
IconButton (
448
497
onClick = {
449
498
menuState.show {
@@ -465,37 +514,16 @@ fun Queue(
465
514
tint = LocalContentColor .current,
466
515
)
467
516
}
468
- } else {
517
+
469
518
IconButton (
470
- onClick = {
471
- queueWindows.forEach {
472
- selectedSongs.add(it.mediaItem.metadata!! )
473
- selectedItems.add(it)
474
- }
475
- },
519
+ onClick = { selection = false },
476
520
) {
477
521
Icon (
478
- painter = painterResource(R .drawable.select_all ),
522
+ painter = painterResource(R .drawable.close ),
479
523
contentDescription = null ,
480
- tint = LocalContentColor .current,
481
524
)
482
525
}
483
526
}
484
-
485
- Column (
486
- verticalArrangement = Arrangement .spacedBy(4 .dp),
487
- horizontalAlignment = Alignment .End ,
488
- ) {
489
- Text (
490
- text = pluralStringResource(R .plurals.n_song, queueWindows.size, queueWindows.size),
491
- style = MaterialTheme .typography.bodyMedium,
492
- )
493
-
494
- Text (
495
- text = makeTimeString(queueLength * 1000L ),
496
- style = MaterialTheme .typography.bodyMedium,
497
- )
498
- }
499
527
}
500
528
}
501
529
0 commit comments