prepare server summary bottom drawer

This commit is contained in:
Gary Wang 2021-11-20 00:12:02 +08:00
parent 1d2ded1eee
commit bea1235502
6 changed files with 283 additions and 116 deletions

View File

@ -1,23 +1,25 @@
TODO TODO
* TODO Add server * Basic functionality
- [x] Create ** TODO Manage servers [1/3]
- [ ] Delete
- [X] Create
- [ ] Update - [ ] Update
- [ ] Delete
* TODO Music playback ** TODO Music playback [0/3]
- [ ] Regular playback - [ ] Regular playback
- [ ] Playlist - [ ] Playlist
- [ ] Media session - [ ] Media session
* TODO Download music to local folder ** TODO Download music to local folder [0/2]
- [ ] Select and remember selected folder - [ ] Select and remember selected folder
- [ ] Download music - [ ] Download music
* TODO Misc. ** TODO Misc. [0/1]
- [ ] Back key to navigate folder up - [ ] Back key to navigate folder up

View File

@ -69,99 +69,6 @@ fun NowPlaying() {
} }
} }
@Preview(showBackground = true)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DrawerContent(
currentServer: Server? = null,
servers: List<Server> = listOf(),
drawerFolders: List<Folder> = listOf(),
addServerActionTriggered: () -> Unit = {},
onServerItemIconClicked: (Server) -> Unit = {},
onDrawerFolderItemClicked: (Folder) -> Unit = {},
settingsActionTriggered: () -> Unit = {},
) {
val currentServerApiUrl = currentServer?.url
Row(modifier = Modifier.fillMaxSize()) {
NavigationRail {
servers.forEachIndexed { index, server ->
NavigationRailItem(
icon = {
Icon(
Icons.Filled.LibraryMusic, server.name
)
},
label = {
Text(server.displayName())
},
selected = server.url == currentServerApiUrl,
onClick = {
onServerItemIconClicked(server)
}
)
}
NavigationRailItem(
icon = { Icon(Icons.Filled.AddCircle, null) },
label = { Text(stringResource(id = R.string.add)) },
selected = false,
onClick = addServerActionTriggered,
)
Spacer(modifier = Modifier.weight(1f))
NavigationRailItem(
icon = { Icon(Icons.Filled.Settings, null) },
label = { Text(stringResource(id = R.string.settings)) },
selected = false,
onClick = settingsActionTriggered,
)
}
Column(
modifier = Modifier
.weight(1f)
) {
ListItem(
text = {
Text(
text = currentServer?.displayName() ?: "No server selected",
style = MaterialTheme.typography.subtitle1
)
},
trailing = {
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Filled.MoreVert, contentDescription = "Menu")
}
}
)
Divider()
Column(
modifier = Modifier
.weight(1f, fill = true)
.verticalScroll(rememberScrollState())
) {
drawerFolders.forEach { folder ->
ListItem(
modifier = Modifier.clickable{
onDrawerFolderItemClicked(folder)
},
text = {
Text(
text = folder.displayName(),
style = MaterialTheme.typography.subtitle1
)
}
)
}
}
}
}
}
@Preview(showBackground = true) @Preview(showBackground = true)
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
@ -177,30 +84,33 @@ fun MainPlayer(
onFolderItemClicked: (Folder) -> Unit = {}, onFolderItemClicked: (Folder) -> Unit = {},
settingsActionTriggered: () -> Unit = {}, settingsActionTriggered: () -> Unit = {},
) { ) {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) val bottomDrawerState = rememberBottomDrawerState(initialValue = BottomDrawerValue.Closed)
val drawerScope = rememberCoroutineScope() val bottomDrawerScope = rememberCoroutineScope()
ModalDrawer( BottomDrawer(
drawerState = drawerState, drawerState = bottomDrawerState,
gesturesEnabled = bottomDrawerState.isOpen,
drawerContent = { drawerContent = {
DrawerContent( if (currentServer != null) {
currentServer = currentServer, ServerSummaryDrawer(currentServer)
servers = servers, } else {
drawerFolders = drawerFolders, Text(
addServerActionTriggered = addServerActionTriggered, "TODO: play control and playlist?",
onServerItemIconClicked = onServerItemIconClicked, modifier = Modifier.fillMaxWidth().padding(16.dp),
onDrawerFolderItemClicked = onFolderItemClicked, )
settingsActionTriggered = settingsActionTriggered, }
) },
}
) { ) {
val scaffoldState = rememberScaffoldState()
val scaffoldScope = rememberCoroutineScope()
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( TopAppBar(
title = { Text(stringResource(id = R.string.app_name)) }, title = { Text(stringResource(id = R.string.app_name)) },
navigationIcon = { navigationIcon = {
IconButton(onClick = { IconButton(onClick = {
drawerScope.launch { scaffoldScope.launch {
drawerState.open() scaffoldState.drawerState.open()
} }
}) { }) {
Icon(imageVector = Icons.Filled.Menu, contentDescription = "Open drawer") Icon(imageVector = Icons.Filled.Menu, contentDescription = "Open drawer")
@ -212,6 +122,22 @@ fun MainPlayer(
} }
} }
) )
},
drawerContent = {
SidebarContent(
currentServer = currentServer,
servers = servers,
drawerFolders = drawerFolders,
addServerActionTriggered = addServerActionTriggered,
onServerItemIconClicked = onServerItemIconClicked,
onServerMenuIconClicked = {
bottomDrawerScope.launch {
bottomDrawerState.open()
}
},
onDrawerFolderItemClicked = onFolderItemClicked,
settingsActionTriggered = settingsActionTriggered,
)
} }
) { ) {
Column( Column(

View File

@ -0,0 +1,117 @@
package net.blumia.pcmdroid.ui.screen.main
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.blumia.pcmdroid.R
import net.blumia.pcmdroid.model.Server
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun RowScope.ActionIcon(
imageVector: ImageVector = Icons.Filled.Share,
contentDescription: String = "Share",
onActionTriggered: () -> Unit = {},
) {
Surface(
modifier = Modifier.weight(1f),
onClick = onActionTriggered,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(imageVector = imageVector, contentDescription = contentDescription)
Text(contentDescription)
}
}
}
@Preview(showBackground = true)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ServerSummaryDrawer(
server: Server = Server("http://localhost/", "Demo server", "pcm"),
onShareActionTriggered: (Server) -> Unit = {},
onEditActionTriggered: (Server) -> Unit = {},
onDeleteActionTriggered: (Server) -> Unit = {},
) {
Column(
modifier = Modifier.padding(vertical = 16.dp)
) {
Column(
modifier = Modifier.padding(horizontal = 16.dp)
) {
Icon(
modifier = Modifier.size(50.dp),
imageVector = Icons.Filled.LibraryMusic,
contentDescription = null,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
text = server.displayName(),
// textAlign = TextAlign.Center,
style = MaterialTheme.typography.h5,
)
}
// Row(
// modifier = Modifier.fillMaxWidth(),
// ) {
// ActionIcon(
// imageVector = Icons.Filled.Share,
// contentDescription = "Share",
// )
// ActionIcon(
// imageVector = Icons.Filled.Edit,
// contentDescription = "Edit",
// )
// }
ListItem(
modifier = Modifier.clickable {
onShareActionTriggered(server)
},
icon = {
Icon(Icons.Filled.Share, null)
},
text = {
Text(stringResource(id = R.string.share_this_server))
},
)
ListItem(
modifier = Modifier.clickable {
onEditActionTriggered(server)
},
icon = {
Icon(Icons.Filled.Edit, null)
},
text = {
Text(stringResource(id = R.string.edit_server_info))
},
)
ListItem(
modifier = Modifier.clickable {
onDeleteActionTriggered(server)
},
icon = {
Icon(Icons.Filled.Delete, null)
},
text = {
Text(stringResource(id = R.string.delete_server))
},
)
}
}

View File

@ -0,0 +1,116 @@
package net.blumia.pcmdroid.ui.screen.main
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.LibraryMusic
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import net.blumia.pcmdroid.R
import net.blumia.pcmdroid.model.Folder
import net.blumia.pcmdroid.model.Server
@Preview(showBackground = true)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SidebarContent(
currentServer: Server? = null,
servers: List<Server> = listOf(),
drawerFolders: List<Folder> = listOf(),
addServerActionTriggered: () -> Unit = {},
onServerItemIconClicked: (Server) -> Unit = {},
onServerMenuIconClicked: () -> Unit = {},
onDrawerFolderItemClicked: (Folder) -> Unit = {},
settingsActionTriggered: () -> Unit = {},
) {
val currentServerApiUrl = currentServer?.url
Row(modifier = Modifier.fillMaxSize()) {
NavigationRail {
servers.forEachIndexed { index, server ->
NavigationRailItem(
icon = {
Icon(
Icons.Filled.LibraryMusic, server.name
)
},
label = {
Text(server.displayName())
},
selected = server.url == currentServerApiUrl,
onClick = {
onServerItemIconClicked(server)
}
)
}
NavigationRailItem(
icon = { Icon(Icons.Filled.AddCircle, null) },
label = { Text(stringResource(id = R.string.add)) },
selected = false,
onClick = addServerActionTriggered,
)
Spacer(modifier = Modifier.weight(1f))
NavigationRailItem(
icon = { Icon(Icons.Filled.Settings, null) },
label = { Text(stringResource(id = R.string.settings)) },
selected = false,
onClick = settingsActionTriggered,
)
}
Column(
modifier = Modifier
.weight(1f)
) {
ListItem(
text = {
Text(
text = currentServer?.displayName() ?: "No server selected",
style = MaterialTheme.typography.subtitle1
)
},
trailing = {
IconButton(onClick = onServerMenuIconClicked) {
Icon(imageVector = Icons.Filled.MoreVert, contentDescription = "Menu")
}
}
)
Divider()
Column(
modifier = Modifier
.weight(1f, fill = true)
.verticalScroll(rememberScrollState())
) {
drawerFolders.forEach { folder ->
ListItem(
modifier = Modifier.clickable{
onDrawerFolderItemClicked(folder)
},
text = {
Text(
text = folder.displayName(),
style = MaterialTheme.typography.subtitle1
)
}
)
}
}
}
}
}

View File

@ -2,4 +2,7 @@
<string name="app_name">私有云音乐</string> <string name="app_name">私有云音乐</string>
<string name="settings">设置</string> <string name="settings">设置</string>
<string name="add">添加</string> <string name="add">添加</string>
<string name="share_this_server">分享此服务器</string>
<string name="delete_server">删除服务器</string>
<string name="edit_server_info">编辑服务器信息</string>
</resources> </resources>

View File

@ -2,4 +2,7 @@
<string name="app_name">Private Cloud Music</string> <string name="app_name">Private Cloud Music</string>
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="add">Add</string> <string name="add">Add</string>
<string name="share_this_server">Share This Server</string>
<string name="delete_server">Delete Server</string>
<string name="edit_server_info">Edit Server Information</string>
</resources> </resources>