feat: add persisting of settings

This commit is contained in:
Fritz Heiden 2025-03-19 17:06:15 +01:00
parent 7a871f9fa4
commit 83153871b2
4 changed files with 55 additions and 10 deletions

View File

@ -31,11 +31,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.res.painterResource
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.tvcontroller.services.BluetoothService
import com.example.tvcontroller.services.DeviceService
import com.example.tvcontroller.ui.AppViewModel
class MainActivity : ComponentActivity() {
private lateinit var bluetoothService: BluetoothService
private lateinit var deviceService: DeviceService
private val appViewModel by viewModels<AppViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
@ -43,10 +45,15 @@ class MainActivity : ComponentActivity() {
bluetoothService = BluetoothService(this.applicationContext)
bluetoothService.onBluetoothStateChanged { state -> appViewModel.setBluetoothEnabled(state == BluetoothAdapter.STATE_ON) }
appViewModel.setBluetoothEnabled(bluetoothService.isBluetoothEnabled())
deviceService = DeviceService(this.applicationContext)
enableEdgeToEdge()
setContent {
TVControllerTheme {
TvControllerApp(appViewModel = appViewModel, bluetoothService = bluetoothService)
TvControllerApp(
appViewModel = appViewModel,
bluetoothService = bluetoothService,
deviceService = deviceService
)
}
}
}
@ -56,7 +63,8 @@ class MainActivity : ComponentActivity() {
fun TvControllerApp(
navController: NavHostController = rememberNavController(),
appViewModel: AppViewModel = viewModel(),
bluetoothService: BluetoothService? = null
bluetoothService: BluetoothService? = null,
deviceService: DeviceService
) {
val backStackEntry by navController.currentBackStackEntryAsState()
val currentScreen = Screen.valueOf(backStackEntry?.destination?.route ?: Screen.Camera.name)
@ -113,7 +121,7 @@ fun TvControllerApp(
RemoteScreen()
}
composable(route = Screen.Settings.name) {
SettingsScreen(appViewModel = appViewModel)
SettingsScreen(appViewModel = appViewModel, deviceService = deviceService)
}
}
}

View File

@ -16,11 +16,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.tvcontroller.services.DeviceService
import com.example.tvcontroller.ui.AppViewModel
@Composable
fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
val viewModel = viewModel<SettingsViewModel>()
fun SettingsScreen(deviceService: DeviceService, appViewModel: AppViewModel) {
val viewModel =
viewModel<SettingsViewModel>(factory = SettingsViewModel.provideFactory(deviceService))
Column(
modifier = Modifier

View File

@ -4,12 +4,13 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.example.tvcontroller.services.DeviceService
import kotlinx.coroutines.launch
class SettingsViewModel : ViewModel() {
var serverAddress by mutableStateOf(DeviceService.getServerAddress())
class SettingsViewModel(private val deviceService: DeviceService) : ViewModel() {
var serverAddress by mutableStateOf(deviceService.getServerAddress())
private set
var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL)
private set
@ -19,8 +20,8 @@ class SettingsViewModel : ViewModel() {
fun connect() {
//Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode")
viewModelScope.launch {
DeviceService.setServerAddress(serverAddress)
DeviceService.createIntegration(deviceName, registrationCode)
deviceService.setServerAddress(serverAddress)
deviceService.createIntegration(deviceName, registrationCode)
}
}
@ -35,4 +36,15 @@ class SettingsViewModel : ViewModel() {
fun onRegistrationCodeChanged(code: String) {
registrationCode = code
}
companion object {
fun provideFactory(
deviceService: DeviceService,
) = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SettingsViewModel(deviceService) as T
}
}
}
}

View File

@ -1,5 +1,7 @@
package com.example.tvcontroller.services
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.util.Log
import io.ktor.client.engine.cio.*
import io.ktor.client.*
@ -11,10 +13,16 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpMethod
import org.json.JSONObject
object DeviceService {
private const val SHARED_PREFERENCES_NAME = "devices";
class DeviceService(private val context: Context) {
private var client = HttpClient(CIO)
private var serverAddress: String = ""
init {
loadPreferences()
}
suspend fun createIntegration(name: String, code: String) {
Log.i("DeviceService", "Creating integration for $name with code $code at $serverAddress")
val json = JSONObject()
@ -29,6 +37,7 @@ object DeviceService {
}
}
savePreferences()
val body: String = response.body()
Log.i("DeviceService", "Response: ${response.status.value} $body")
} catch (e: Exception) {
@ -36,6 +45,20 @@ object DeviceService {
}
}
private fun loadPreferences() {
val sharedPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
serverAddress = sharedPreferences.getString("server_address", "")!!
}
private fun savePreferences() {
val sharedPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.apply {
putString("server_address", serverAddress)
apply()
}
}
fun setServerAddress(url: String) {
serverAddress = url
}