now able to edit and delete server
This commit is contained in:
parent
8ab2f03a1b
commit
9c9bdb9435
|
@ -5,7 +5,10 @@ import android.util.Log
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import net.blumia.pcmdroid.model.Folder
|
import net.blumia.pcmdroid.model.Folder
|
||||||
import net.blumia.pcmdroid.model.Server
|
import net.blumia.pcmdroid.model.Server
|
||||||
import net.blumia.pcmdroid.model.Song
|
import net.blumia.pcmdroid.model.Song
|
||||||
|
@ -46,6 +49,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
|
||||||
val songs: LiveData<List<Song>> = _songs
|
val songs: LiveData<List<Song>> = _songs
|
||||||
|
|
||||||
fun fetchServer(srv: Server) {
|
fun fetchServer(srv: Server) {
|
||||||
|
setCurrentServer(srv)
|
||||||
viewModelScope.launch(context = Dispatchers.IO) {
|
viewModelScope.launch(context = Dispatchers.IO) {
|
||||||
|
|
||||||
val formBody = FormBody.Builder()
|
val formBody = FormBody.Builder()
|
||||||
|
@ -53,6 +57,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
// .url("http://localhost/")
|
||||||
.url(srv.url)
|
.url(srv.url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.build()
|
.build()
|
||||||
|
@ -65,7 +70,7 @@ class MainViewModel(private val repository: ServerRepository) : ViewModel() {
|
||||||
}
|
}
|
||||||
val pair = parseFromJsonString(response.body!!.string())
|
val pair = parseFromJsonString(response.body!!.string())
|
||||||
_drawerFolders.postValue(pair.first)
|
_drawerFolders.postValue(pair.first)
|
||||||
setCurrentServer(srv)
|
// setCurrentServer(srv)
|
||||||
Log.d("vvv", drawerFolders.value.toString())
|
Log.d("vvv", drawerFolders.value.toString())
|
||||||
}
|
}
|
||||||
} catch (e: java.io.IOException) {
|
} 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 {
|
class MainViewModelFactory(private val repository: ServerRepository) : ViewModelProvider.Factory {
|
||||||
|
|
|
@ -1,20 +1,30 @@
|
||||||
package net.blumia.pcmdroid.model
|
package net.blumia.pcmdroid.model
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Entity(tableName = "server_table")
|
@Entity(tableName = "server_table")
|
||||||
data class Server (
|
data class Server (
|
||||||
@PrimaryKey @ColumnInfo(name = "url")
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ColumnInfo(name = "serverId")
|
||||||
|
val serverId: Long? = null,
|
||||||
|
@ColumnInfo(name = "url")
|
||||||
val url: String,
|
val url: String,
|
||||||
@ColumnInfo(name = "name")
|
@ColumnInfo(name = "name")
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@ColumnInfo(name = "shortName")
|
||||||
|
val shortName: String,
|
||||||
@ColumnInfo(name = "baseFolderName")
|
@ColumnInfo(name = "baseFolderName")
|
||||||
val baseFolderName: String,
|
val baseFolderName: String,
|
||||||
) {
|
) {
|
||||||
fun displayName(): String {
|
fun displayName(): String {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shortDisplayName(): String {
|
||||||
|
return if (shortName.isNotEmpty()) shortName else name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -23,9 +33,15 @@ interface ServerDao {
|
||||||
@Query("SELECT * FROM server_table") // ORDER BY wtf ASC
|
@Query("SELECT * FROM server_table") // ORDER BY wtf ASC
|
||||||
fun getServers(): Flow<List<Server>>
|
fun getServers(): Flow<List<Server>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM server_table WHERE serverId=:id")
|
||||||
|
fun getServerById(id: Long): Flow<Server>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||||
suspend fun insert(server: Server)
|
suspend fun insert(server: Server)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(server: Server)
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
suspend fun delete(server: Server)
|
suspend fun delete(server: Server)
|
||||||
|
|
||||||
|
|
|
@ -21,4 +21,22 @@ class ServerRepository(private val serverDao: ServerDao) {
|
||||||
suspend fun insert(server: Server) {
|
suspend fun insert(server: Server) {
|
||||||
serverDao.insert(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)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,23 +1,29 @@
|
||||||
package net.blumia.pcmdroid.ui
|
package net.blumia.pcmdroid.ui
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.navigation.NavType
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import androidx.navigation.navArgument
|
||||||
import net.blumia.pcmdroid.MainViewModel
|
import net.blumia.pcmdroid.MainViewModel
|
||||||
import net.blumia.pcmdroid.model.Folder
|
import net.blumia.pcmdroid.model.Folder
|
||||||
import net.blumia.pcmdroid.model.Server
|
import net.blumia.pcmdroid.model.Server
|
||||||
import net.blumia.pcmdroid.model.Song
|
import net.blumia.pcmdroid.model.Song
|
||||||
import net.blumia.pcmdroid.ui.screen.addserver.AddServerScreen
|
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.main.MainPlayer
|
||||||
import net.blumia.pcmdroid.ui.screen.settings.SettingsScreen
|
import net.blumia.pcmdroid.ui.screen.settings.SettingsScreen
|
||||||
|
|
||||||
object MainDestinations {
|
object MainDestinations {
|
||||||
const val MAIN_ROUTE = "main"
|
const val MAIN_ROUTE = "main"
|
||||||
const val ADD_SERVER_ROUTE = "add_server"
|
const val ADD_SERVER_ROUTE = "add_server"
|
||||||
|
const val EDIT_SERVER_ROUTE = "edit_server"
|
||||||
const val SETTINGS_ROUTE = "settings"
|
const val SETTINGS_ROUTE = "settings"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +62,15 @@ fun NavGraph(
|
||||||
onFolderItemClicked = { folder ->
|
onFolderItemClicked = { folder ->
|
||||||
viewModel.fetchFolder(folder)
|
viewModel.fetchFolder(folder)
|
||||||
},
|
},
|
||||||
|
onEditServerActionTriggered = { server ->
|
||||||
|
navController.navigate( "${MainDestinations.EDIT_SERVER_ROUTE}?id=${server.serverId}")
|
||||||
|
},
|
||||||
|
onDeleteServerActionTriggered = { server ->
|
||||||
|
viewModel.deleteServer(server)
|
||||||
|
},
|
||||||
settingsActionTriggered = {
|
settingsActionTriggered = {
|
||||||
navController.navigate(MainDestinations.SETTINGS_ROUTE)
|
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()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -67,6 +67,8 @@ fun StepEnterApiUrl(
|
||||||
fun StepOtherDetail(
|
fun StepOtherDetail(
|
||||||
nameStr: String = "",
|
nameStr: String = "",
|
||||||
onNameStrChange: (String) -> Unit = {},
|
onNameStrChange: (String) -> Unit = {},
|
||||||
|
shortNameStr: String = "",
|
||||||
|
onShortNameStrChange: (String) -> Unit = {},
|
||||||
baseFolderNameStr: String = "",
|
baseFolderNameStr: String = "",
|
||||||
onBaseFolderNameStrChange: (String) -> Unit = {},
|
onBaseFolderNameStrChange: (String) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
@ -74,6 +76,15 @@ fun StepOtherDetail(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 10.dp),
|
||||||
|
value = shortNameStr,
|
||||||
|
onValueChange = onShortNameStrChange,
|
||||||
|
label = { Text("Server short name") },
|
||||||
|
)
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -137,6 +148,7 @@ fun AddServerScreen(
|
||||||
) {
|
) {
|
||||||
var urlStr by rememberSaveable { mutableStateOf("") }
|
var urlStr by rememberSaveable { mutableStateOf("") }
|
||||||
var nameStr by rememberSaveable { mutableStateOf("") }
|
var nameStr by rememberSaveable { mutableStateOf("") }
|
||||||
|
var shortNameStr by rememberSaveable { mutableStateOf("") }
|
||||||
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
|
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
|
@ -160,6 +172,10 @@ fun AddServerScreen(
|
||||||
onNameStrChange = { value ->
|
onNameStrChange = { value ->
|
||||||
nameStr = value
|
nameStr = value
|
||||||
},
|
},
|
||||||
|
shortNameStr,
|
||||||
|
onShortNameStrChange = { value ->
|
||||||
|
shortNameStr = value
|
||||||
|
},
|
||||||
baseFolderNameStr,
|
baseFolderNameStr,
|
||||||
onBaseFolderNameStrChange = { value ->
|
onBaseFolderNameStrChange = { value ->
|
||||||
baseFolderNameStr = value
|
baseFolderNameStr = value
|
||||||
|
@ -189,6 +205,7 @@ fun AddServerScreen(
|
||||||
val srv = Server(
|
val srv = Server(
|
||||||
url = urlStr,
|
url = urlStr,
|
||||||
name = nameStr,
|
name = nameStr,
|
||||||
|
shortName = shortNameStr,
|
||||||
baseFolderName = baseFolderNameStr,
|
baseFolderName = baseFolderNameStr,
|
||||||
)
|
)
|
||||||
onSubmitServerTriggered(srv)
|
onSubmitServerTriggered(srv)
|
||||||
|
|
|
@ -19,11 +19,13 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import net.blumia.pcmdroid.model.Server
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EditServerScreen(
|
fun EditServerScreen(
|
||||||
|
server: Server,
|
||||||
onCloseActionTriggered: () -> Unit = {},
|
onCloseActionTriggered: () -> Unit = {},
|
||||||
|
onSaveButtonTriggered: (Server) -> Unit = {},
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
@ -68,9 +70,19 @@ fun EditServerScreen(
|
||||||
style = MaterialTheme.typography.subtitle2,
|
style = MaterialTheme.typography.subtitle2,
|
||||||
)
|
)
|
||||||
|
|
||||||
var nameStr by rememberSaveable { mutableStateOf("") }
|
var shortNameStr by rememberSaveable { mutableStateOf(server.shortName) }
|
||||||
var urlStr by rememberSaveable { mutableStateOf("") }
|
var nameStr by rememberSaveable { mutableStateOf(server.name) }
|
||||||
var baseFolderNameStr by rememberSaveable { mutableStateOf("") }
|
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(
|
OutlinedTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -101,6 +113,38 @@ fun EditServerScreen(
|
||||||
onValueChange = { value -> baseFolderNameStr = value},
|
onValueChange = { value -> baseFolderNameStr = value},
|
||||||
label = { Text("Base folder name") },
|
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",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
|
@ -82,6 +82,8 @@ fun MainPlayer(
|
||||||
addServerActionTriggered: () -> Unit = {},
|
addServerActionTriggered: () -> Unit = {},
|
||||||
onServerItemIconClicked: (Server) -> Unit = {},
|
onServerItemIconClicked: (Server) -> Unit = {},
|
||||||
onFolderItemClicked: (Folder) -> Unit = {},
|
onFolderItemClicked: (Folder) -> Unit = {},
|
||||||
|
onEditServerActionTriggered: (Server) -> Unit = {},
|
||||||
|
onDeleteServerActionTriggered: (Server) -> Unit = {},
|
||||||
settingsActionTriggered: () -> Unit = {},
|
settingsActionTriggered: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val bottomDrawerState = rememberBottomDrawerState(initialValue = BottomDrawerValue.Closed)
|
val bottomDrawerState = rememberBottomDrawerState(initialValue = BottomDrawerValue.Closed)
|
||||||
|
@ -91,7 +93,21 @@ fun MainPlayer(
|
||||||
gesturesEnabled = bottomDrawerState.isOpen,
|
gesturesEnabled = bottomDrawerState.isOpen,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
if (currentServer != null) {
|
if (currentServer != null) {
|
||||||
ServerSummaryDrawer(currentServer)
|
ServerSummaryDrawer(
|
||||||
|
server = currentServer,
|
||||||
|
onEditActionTriggered = {
|
||||||
|
onEditServerActionTriggered(currentServer)
|
||||||
|
bottomDrawerScope.launch {
|
||||||
|
bottomDrawerState.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDeleteActionTriggered = {
|
||||||
|
onDeleteServerActionTriggered(currentServer)
|
||||||
|
bottomDrawerScope.launch {
|
||||||
|
bottomDrawerState.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Text(
|
Text(
|
||||||
"TODO: play control and playlist?",
|
"TODO: play control and playlist?",
|
||||||
|
|
|
@ -39,11 +39,10 @@ fun RowScope.ActionIcon(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ServerSummaryDrawer(
|
fun ServerSummaryDrawer(
|
||||||
server: Server = Server("http://localhost/", "Demo server", "pcm"),
|
server: Server,
|
||||||
onShareActionTriggered: (Server) -> Unit = {},
|
onShareActionTriggered: (Server) -> Unit = {},
|
||||||
onEditActionTriggered: (Server) -> Unit = {},
|
onEditActionTriggered: (Server) -> Unit = {},
|
||||||
onDeleteActionTriggered: (Server) -> Unit = {},
|
onDeleteActionTriggered: (Server) -> Unit = {},
|
||||||
|
@ -115,3 +114,18 @@ fun ServerSummaryDrawer(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
fun ServerSummaryDrawerPreview()
|
||||||
|
{
|
||||||
|
ServerSummaryDrawer(
|
||||||
|
Server(
|
||||||
|
-1,
|
||||||
|
"http://localhost/",
|
||||||
|
"Demo server",
|
||||||
|
"Demo",
|
||||||
|
"pcm"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ fun SidebarContent(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
label = {
|
label = {
|
||||||
Text(server.displayName())
|
Text(server.shortDisplayName())
|
||||||
},
|
},
|
||||||
selected = server.url == currentServerApiUrl,
|
selected = server.url == currentServerApiUrl,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user