now able to edit and delete server

This commit is contained in:
Gary Wang 2021-11-22 00:01:21 +08:00
parent 8ab2f03a1b
commit 9c9bdb9435
9 changed files with 189 additions and 11 deletions

View File

@ -5,7 +5,10 @@ import android.util.Log
import androidx.lifecycle.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import net.blumia.pcmdroid.model.Folder
import net.blumia.pcmdroid.model.Server
import net.blumia.pcmdroid.model.Song
@ -46,6 +49,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
val songs: LiveData<List<Song>> = _songs
fun fetchServer(srv: Server) {
setCurrentServer(srv)
viewModelScope.launch(context = Dispatchers.IO) {
val formBody = FormBody.Builder()
@ -53,6 +57,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
.build()
val request = Request.Builder()
// .url("http://localhost/")
.url(srv.url)
.post(formBody)
.build()
@ -65,7 +70,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
}
val pair = parseFromJsonString(response.body!!.string())
_drawerFolders.postValue(pair.first)
setCurrentServer(srv)
// setCurrentServer(srv)
Log.d("vvv", drawerFolders.value.toString())
}
} catch (e: java.io.IOException) {
@ -107,6 +112,24 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
}
}
}
fun getServerById(id: Long): Server {
return runBlocking {
repository.serverById(id).first()
}
}
fun editServer(srv: Server) {
runBlocking {
repository.update(srv)
}
}
fun deleteServer(srv: Server) {
runBlocking {
repository.delete(srv)
}
}
}
class MainViewModelFactory(private val repository: ServerRepository) : ViewModelProvider.Factory {

View File

@ -1,20 +1,30 @@
package net.blumia.pcmdroid.model
import androidx.lifecycle.LiveData
import androidx.room.*
import kotlinx.coroutines.flow.Flow
@Entity(tableName = "server_table")
data class Server (
@PrimaryKey @ColumnInfo(name = "url")
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "serverId")
val serverId: Long? = null,
@ColumnInfo(name = "url")
val url: String,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "shortName")
val shortName: String,
@ColumnInfo(name = "baseFolderName")
val baseFolderName: String,
) {
fun displayName(): String {
return name
}
fun shortDisplayName(): String {
return if (shortName.isNotEmpty()) shortName else name
}
}
@Dao
@ -23,9 +33,15 @@ interface ServerDao {
@Query("SELECT * FROM server_table") // ORDER BY wtf ASC
fun getServers(): Flow<List<Server>>
@Query("SELECT * FROM server_table WHERE serverId=:id")
fun getServerById(id: Long): Flow<Server>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(server: Server)
@Update
suspend fun update(server: Server)
@Delete
suspend fun delete(server: Server)

View File

@ -21,4 +21,22 @@ class ServerRepository(private val serverDao: ServerDao) {
suspend fun insert(server: Server) {
serverDao.insert(server)
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun update(server: Server) {
serverDao.update(server)
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun delete(server: Server) {
serverDao.delete(server)
}
@Suppress("RedundantSuspendModifier")
@WorkerThread
fun serverById(id: Long): Flow<Server> {
return serverDao.getServerById(id)
}
}

View File

@ -1,23 +1,29 @@
package net.blumia.pcmdroid.ui
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.lifecycle.MutableLiveData
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import net.blumia.pcmdroid.MainViewModel
import net.blumia.pcmdroid.model.Folder
import net.blumia.pcmdroid.model.Server
import net.blumia.pcmdroid.model.Song
import net.blumia.pcmdroid.ui.screen.addserver.AddServerScreen
import net.blumia.pcmdroid.ui.screen.editserver.EditServerScreen
import net.blumia.pcmdroid.ui.screen.main.MainPlayer
import net.blumia.pcmdroid.ui.screen.settings.SettingsScreen
object MainDestinations {
const val MAIN_ROUTE = "main"
const val ADD_SERVER_ROUTE = "add_server"
const val EDIT_SERVER_ROUTE = "edit_server"
const val SETTINGS_ROUTE = "settings"
}
@ -56,9 +62,15 @@ fun NavGraph(
onFolderItemClicked = { folder ->
viewModel.fetchFolder(folder)
},
onEditServerActionTriggered = { server ->
navController.navigate( "${MainDestinations.EDIT_SERVER_ROUTE}?id=${server.serverId}")
},
onDeleteServerActionTriggered = { server ->
viewModel.deleteServer(server)
},
settingsActionTriggered = {
navController.navigate(MainDestinations.SETTINGS_ROUTE)
}
},
)
}
@ -81,5 +93,23 @@ fun NavGraph(
}
)
}
composable(
"${MainDestinations.EDIT_SERVER_ROUTE}?id={id}",
arguments = listOf(navArgument("id") { type = NavType.LongType })
) {
val srv = viewModel.getServerById(it.arguments?.getLong("id")!!)
EditServerScreen(
server = srv,
onCloseActionTriggered = {
navController.navigateUp()
},
onSaveButtonTriggered = { server ->
viewModel.editServer(server)
navController.navigateUp()
},
)
}
}
}

View File

@ -67,6 +67,8 @@ fun StepEnterApiUrl(
fun StepOtherDetail(
nameStr: String = "",
onNameStrChange: (String) -> Unit = {},
shortNameStr: String = "",
onShortNameStrChange: (String) -> Unit = {},
baseFolderNameStr: String = "",
onBaseFolderNameStrChange: (String) -> Unit = {},
) {
@ -74,6 +76,15 @@ fun StepOtherDetail(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = shortNameStr,
onValueChange = onShortNameStrChange,
label = { Text("Server short name") },
)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
@ -137,6 +148,7 @@ fun AddServerScreen(
) {
var urlStr by rememberSaveable { mutableStateOf("") }
var nameStr by rememberSaveable { mutableStateOf("") }
var shortNameStr by rememberSaveable { mutableStateOf("") }
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
Column(
@ -160,6 +172,10 @@ fun AddServerScreen(
onNameStrChange = { value ->
nameStr = value
},
shortNameStr,
onShortNameStrChange = { value ->
shortNameStr = value
},
baseFolderNameStr,
onBaseFolderNameStrChange = { value ->
baseFolderNameStr = value
@ -189,6 +205,7 @@ fun AddServerScreen(
val srv = Server(
url = urlStr,
name = nameStr,
shortName = shortNameStr,
baseFolderName = baseFolderNameStr,
)
onSubmitServerTriggered(srv)

View File

@ -19,11 +19,13 @@ 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
@Preview(showBackground = true)
@Composable
fun EditServerScreen(
server: Server,
onCloseActionTriggered: () -> Unit = {},
onSaveButtonTriggered: (Server) -> Unit = {},
)
{
Scaffold(
@ -68,9 +70,19 @@ fun EditServerScreen(
style = MaterialTheme.typography.subtitle2,
)
var nameStr by rememberSaveable { mutableStateOf("") }
var urlStr by rememberSaveable { mutableStateOf("") }
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
var shortNameStr by rememberSaveable { mutableStateOf(server.shortName) }
var nameStr by rememberSaveable { mutableStateOf(server.name) }
var urlStr by rememberSaveable { mutableStateOf(server.url) }
var baseFolderNameStr by rememberSaveable { mutableStateOf(server.baseFolderName) }
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = shortNameStr,
onValueChange = { value -> shortNameStr = value},
label = { Text("Server Short Name") },
)
OutlinedTextField(
modifier = Modifier
@ -101,6 +113,38 @@ fun EditServerScreen(
onValueChange = { value -> baseFolderNameStr = value},
label = { Text("Base folder name") },
)
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
onSaveButtonTriggered(
Server(
serverId = server.serverId,
name = nameStr,
shortName = shortNameStr,
url = urlStr,
baseFolderName = baseFolderNameStr,
)
)
},
) {
Text("Save")
}
}
}
}
@Preview(showBackground = true)
@Composable
fun EditServerScreenPreview()
{
EditServerScreen(
Server(
-1,
"http://localhost/api.cgi",
"Demo server",
"Demo",
"demo",
)
)
}

View File

@ -82,6 +82,8 @@ fun MainPlayer(
addServerActionTriggered: () -> Unit = {},
onServerItemIconClicked: (Server) -> Unit = {},
onFolderItemClicked: (Folder) -> Unit = {},
onEditServerActionTriggered: (Server) -> Unit = {},
onDeleteServerActionTriggered: (Server) -> Unit = {},
settingsActionTriggered: () -> Unit = {},
) {
val bottomDrawerState = rememberBottomDrawerState(initialValue = BottomDrawerValue.Closed)
@ -91,7 +93,21 @@ fun MainPlayer(
gesturesEnabled = bottomDrawerState.isOpen,
drawerContent = {
if (currentServer != null) {
ServerSummaryDrawer(currentServer)
ServerSummaryDrawer(
server = currentServer,
onEditActionTriggered = {
onEditServerActionTriggered(currentServer)
bottomDrawerScope.launch {
bottomDrawerState.close()
}
},
onDeleteActionTriggered = {
onDeleteServerActionTriggered(currentServer)
bottomDrawerScope.launch {
bottomDrawerState.close()
}
},
)
} else {
Text(
"TODO: play control and playlist?",

View File

@ -39,11 +39,10 @@ fun RowScope.ActionIcon(
}
}
@Preview(showBackground = true)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ServerSummaryDrawer(
server: Server = Server("http://localhost/", "Demo server", "pcm"),
server: Server,
onShareActionTriggered: (Server) -> Unit = {},
onEditActionTriggered: (Server) -> Unit = {},
onDeleteActionTriggered: (Server) -> Unit = {},
@ -114,4 +113,19 @@ fun ServerSummaryDrawer(
},
)
}
}
@Preview(showBackground = true)
@Composable
fun ServerSummaryDrawerPreview()
{
ServerSummaryDrawer(
Server(
-1,
"http://localhost/",
"Demo server",
"Demo",
"pcm"
)
)
}

View File

@ -46,7 +46,7 @@ fun SidebarContent(
)
},
label = {
Text(server.displayName())
Text(server.shortDisplayName())
},
selected = server.url == currentServerApiUrl,
onClick = {