now able to add server from the UI

This commit is contained in:
Gary Wang 2021-11-16 23:46:39 +08:00
parent 9e98340fd2
commit 1d2ded1eee
6 changed files with 178 additions and 62 deletions

View File

@ -1,6 +0,0 @@
TODO:
- [ ] Add server
- [ ] Music playback
- [ ] Download music to local folder
- [ ] Back key to navigate folder up

23
README.org Normal file
View File

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

View File

@ -36,33 +36,13 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
_currentFolder.postValue(folder)
}
private val _drawerFolders: MutableLiveData<List<Folder>> = MutableLiveData(
listOf(
Folder("Test/"),
Folder("Folder/"),
)
)
private val _drawerFolders: MutableLiveData<List<Folder>> = MutableLiveData(listOf())
val drawerFolders: LiveData<List<Folder>> = _drawerFolders
private val _folders: MutableLiveData<List<Folder>> = MutableLiveData(
listOf(
Folder("Test/Converted-Modules/")
)
)
private val _folders: MutableLiveData<List<Folder>> = MutableLiveData(listOf())
val folders: LiveData<List<Folder>> = _folders
private val _songs: MutableLiveData<List<Song>> = MutableLiveData(
listOf(
Song(
filePath = "Test/Rick Astley - Never Gonna Give You Up.mp3",
url = "http://localhost/rickroll.mp3"
),
Song(
filePath = "Test/哇 好东西一堆.xm",
url = "http://localhost/rickroll.mp3"
)
)
)
private val _songs: MutableLiveData<List<Song>> = MutableLiveData(listOf())
val songs: LiveData<List<Song>> = _songs
fun fetchServer(srv: Server) {

View File

@ -26,6 +26,9 @@ interface ServerDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(server: Server)
@Delete
suspend fun delete(server: Server)
@Query("DELETE FROM server_table")
suspend fun deleteAll()
}

View File

@ -66,6 +66,10 @@ fun NavGraph(
AddServerScreen(
onCloseActionTriggered = {
navController.navigateUp()
},
onSubmitServerTriggered = { srv ->
viewModel.addServer(srv)
navController.navigateUp()
}
)
}

View File

@ -2,24 +2,119 @@ package net.blumia.pcmdroid.ui.screen.addserver
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.rounded.AddCircle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.blumia.pcmdroid.model.Server
@Composable
fun StepEnterApiUrl(
urlStr: String = "",
onUrlStrChange: (String) -> Unit = {},
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
modifier = Modifier.size(50.dp),
imageVector = Icons.Filled.AddCircle,
contentDescription = null,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
text = "Add Server",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h5,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp),
text = "Add Private Cloud Music server",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.subtitle2,
)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Uri,
),
value = urlStr,
onValueChange = onUrlStrChange,
label = { Text("Server API Url") },
)
}
}
@Composable
fun StepOtherDetail(
nameStr: String = "",
onNameStrChange: (String) -> Unit = {},
baseFolderNameStr: String = "",
onBaseFolderNameStrChange: (String) -> Unit = {},
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = nameStr,
onValueChange = onNameStrChange,
label = { Text("Server name") },
)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = baseFolderNameStr,
onValueChange = onBaseFolderNameStrChange,
label = { Text("Base folder name") },
)
}
}
@Preview(showBackground = true)
@Composable
fun AddServerScreen(
onCloseActionTriggered: () -> Unit = {},
onSubmitServerTriggered: (Server) -> Unit = {},
) {
var stepState by remember { mutableStateOf(0) }
val finalStep = 1
fun onNextStepButtonTriggered() {
if (stepState < 1) {
stepState++
}
}
fun onPreviousStepButtonTriggered() {
if (stepState > 0) {
stepState--
}
}
Scaffold(
topBar = {
TopAppBar(
@ -40,52 +135,69 @@ fun AddServerScreen(
.padding(20.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
modifier = Modifier.size(50.dp),
imageVector = Icons.Filled.AddCircle,
contentDescription = null,
)
Text(
var urlStr by rememberSaveable { mutableStateOf("") }
var nameStr by rememberSaveable { mutableStateOf("") }
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
text = "Add Server",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.h5,
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp),
text = "Add Private Cloud Music server",
textAlign = TextAlign.Center,
style = MaterialTheme.typography.subtitle2,
)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = "",
onValueChange = {},
label = { Text("Server API Url") },
)
Spacer(modifier = Modifier.weight(1f))
.weight(1f)
) {
when (stepState) {
0 -> {
StepEnterApiUrl(
urlStr,
onUrlStrChange = { value ->
urlStr = value
},
)
}
1 -> {
StepOtherDetail(
nameStr,
onNameStrChange = { value ->
nameStr = value
},
baseFolderNameStr,
onBaseFolderNameStrChange = { value ->
baseFolderNameStr = value
},
)
}
}
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
TextButton(
onClick = { /*TODO*/ },
enabled = false
onClick = ::onPreviousStepButtonTriggered,
enabled = stepState != 0,
) {
Text("Back")
}
Button(
onClick = { /*TODO*/ },
onClick = {
if (stepState != finalStep) {
onNextStepButtonTriggered()
} else {
val srv = Server(
url = urlStr,
name = nameStr,
baseFolderName = baseFolderNameStr,
)
onSubmitServerTriggered(srv)
}
},
shape = RoundedCornerShape(50)
) {
Text(
text = "Next",
text = if (stepState != finalStep) "Next" else "Done",
modifier = Modifier.padding(horizontal = 5.dp)
)
}