now able to edit and delete server
This commit is contained in:
		@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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()
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@ -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?",
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@ -46,7 +46,7 @@ fun SidebarContent(
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                    label = {
 | 
			
		||||
                        Text(server.displayName())
 | 
			
		||||
                        Text(server.shortDisplayName())
 | 
			
		||||
                    },
 | 
			
		||||
                    selected = server.url == currentServerApiUrl,
 | 
			
		||||
                    onClick = {
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user