Skip to content

Commit

Permalink
Update the "Add to playlist" dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
MGaetan89 committed Apr 8, 2024
1 parent 9415056 commit 2db5b47
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,153 +8,197 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import ch.srgssr.pillarbox.demo.shared.data.DemoItem
import ch.srgssr.pillarbox.demo.shared.data.Playlist
import ch.srgssr.pillarbox.demo.ui.theme.PillarboxTheme
import ch.srgssr.pillarbox.demo.ui.theme.paddings

/**
* Media item library dialog
* A dialog allowing the user to add items to the current playlist.
*
* @param mediaItemLibrary the multiple choice list
* @param onItemSelected when dialog is validated
* @param onDismissRequest when dialog is dismissed
* @param items The items to display.
* @param modifier The [Modifier] to apply to the root of the layout.
* @param onAddClick The action to perform when the "Add" button is clicked.
* @param onDismissRequest The action to perform when the dialog is dimissed/"Cancel" is clicked.
*/
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun MediaItemLibraryDialog(
mediaItemLibrary: List<DemoItem>,
onItemSelected: (List<DemoItem>) -> Unit,
onDismissRequest: () -> Unit
items: List<DemoItem>,
modifier: Modifier = Modifier,
onAddClick: (items: List<DemoItem>) -> Unit,
onDismissRequest: () -> Unit,
) {
val selectedItems = remember {
mutableStateListOf<DemoItem>()
}
Dialog(onDismissRequest = onDismissRequest) {

BasicAlertDialog(
onDismissRequest = onDismissRequest,
modifier = modifier,
) {
Surface(
shadowElevation = 4.dp,
shape = RoundedCornerShape(6.dp)
modifier = Modifier
.wrapContentWidth()
.wrapContentHeight(),
shape = AlertDialogDefaults.shape,
color = AlertDialogDefaults.containerColor,
tonalElevation = AlertDialogDefaults.TonalElevation,
) {
DialogContent(
selectedItems = selectedItems,
listDemoItem = mediaItemLibrary,
modifier = Modifier
.fillMaxHeight(0.9f)
.padding(MaterialTheme.paddings.baseline),
onAddClick = {
onItemSelected(selectedItems)
},
onCancelClick = onDismissRequest,
onItemToggleClick = { item: DemoItem, select: Boolean ->
if (select) {
selectedItems.add(item)
} else {
selectedItems.remove(item)
Column {
Text(
text = "Add to the playlist",
modifier = Modifier.padding(MaterialTheme.paddings.baseline),
color = AlertDialogDefaults.titleContentColor,
style = MaterialTheme.typography.headlineSmall,
)

ItemList(
items = items,
selectedItems = selectedItems,
modifier = Modifier.weight(1f),
onItemClick = { item, checked ->
if (checked) {
selectedItems.add(item)
} else {
selectedItems.remove(item)
}
}
}
)
)

ButtonsRow(
modifier = Modifier
.fillMaxWidth()
.padding(MaterialTheme.paddings.small),
onAddClick = {
onAddClick(selectedItems)
onDismissRequest()
},
onCancelClick = onDismissRequest,
)
}
}
}
}

@Composable
private fun DialogContent(
listDemoItem: List<DemoItem>,
private fun ItemList(
items: List<DemoItem>,
selectedItems: List<DemoItem>,
onItemToggleClick: (DemoItem, Boolean) -> Unit,
onCancelClick: () -> Unit,
onAddClick: () -> Unit,
modifier: Modifier = Modifier,
onItemClick: (item: DemoItem, checked: Boolean) -> Unit,
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(MaterialTheme.paddings.small)
) {
Text(
text = "Add to the playlist",
style = MaterialTheme.typography.headlineMedium
)
HorizontalDivider()
LazyColumn(
modifier = Modifier
.weight(0.5f)
.padding(horizontal = MaterialTheme.paddings.small),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.paddings.baseline)
) {
items(listDemoItem) {
val selected = selectedItems.contains(it)
SelectableDemoItem(
modifier = Modifier
.fillMaxWidth()
.clickable {
onItemToggleClick(it, !selected)
},
demoItem = it, selected = selectedItems.contains(it)
)
}
}
HorizontalDivider()
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = onCancelClick) {
Text(text = "Cancel", overflow = TextOverflow.Ellipsis)
LazyColumn(modifier = modifier) {
items(items) { item ->
val checked by remember(item) {
derivedStateOf {
item in selectedItems
}
}
Button(onClick = onAddClick) {
Text(text = "Add", overflow = TextOverflow.Ellipsis)

Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onItemClick(item, !checked) }
.padding(
horizontal = MaterialTheme.paddings.baseline,
vertical = MaterialTheme.paddings.small,
),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.paddings.baseline),
verticalAlignment = Alignment.CenterVertically,
) {
Checkbox(
checked = checked,
onCheckedChange = null,
)

Text(
text = item.title,
color = AlertDialogDefaults.textContentColor,
)
}
}
}
}

@Composable
private fun SelectableDemoItem(modifier: Modifier, demoItem: DemoItem, selected: Boolean) {
private fun ButtonsRow(
modifier: Modifier = Modifier,
onAddClick: () -> Unit,
onCancelClick: () -> Unit,
) {
Row(
modifier,
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.paddings.mini),
verticalAlignment = Alignment.CenterVertically
modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween,
) {
RadioButton(selected = selected, onClick = null)
Text(text = demoItem.title, style = MaterialTheme.typography.bodyLarge)
TextButton(onClick = onCancelClick) {
Text("Cancel")
}

TextButton(onClick = onAddClick) {
Text(text = "Add")
}
}
}

@Preview
@Composable
private fun MediaItemLibraryPreview() {
val list = Playlist.All.items
val selectedItems = listOf(list[0], list[3])
private fun MediaItemLibraryDialogPreview() {
val items = Playlist.All.items

PillarboxTheme {
DialogContent(
modifier = Modifier
.fillMaxHeight(0.9f)
.padding(MaterialTheme.paddings.baseline),
listDemoItem = list,
selectedItems = selectedItems,
onItemToggleClick = { _, _ -> },
onCancelClick = { },
onAddClick = { }
MediaItemLibraryDialog(
items = items,
onAddClick = {},
onDismissRequest = {},
)
}
}

@Preview
@Composable
private fun ItemListPreview() {
val items = Playlist.All.items.take(10)

PillarboxTheme {
ItemList(
items = items,
selectedItems = listOf(items[0], items[3], items[4], items[8]),
onItemClick = { _, _ -> },
)
}
}

@Preview
@Composable
private fun ButtonsRowPrewiew() {
PillarboxTheme {
ButtonsRow(
modifier = Modifier.fillMaxWidth(),
onAddClick = {},
onCancelClick = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,15 @@ fun PlaylistView(
Playlist.All
}
if (addItemDialogState) {
MediaItemLibraryDialog(mediaItemLibrary = mediaItemLibrary.items, onItemSelected = { selectedItems ->
player.addMediaItems(selectedItems.map { it.toMediaItem() })
addItemDialogState = false
}) {
addItemDialogState = false
}
MediaItemLibraryDialog(
items = mediaItemLibrary.items,
onAddClick = { selectedItems ->
player.addMediaItems(selectedItems.map { it.toMediaItem() })
},
onDismissRequest = {
addItemDialogState = false
},
)
}

PlaylistView(
Expand Down

0 comments on commit 2db5b47

Please sign in to comment.