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

View File

@ -4,12 +4,13 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.tvcontroller.services.DeviceService import com.example.tvcontroller.services.DeviceService
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class SettingsViewModel : ViewModel() { class SettingsViewModel(private val deviceService: DeviceService) : ViewModel() {
var serverAddress by mutableStateOf(DeviceService.getServerAddress()) var serverAddress by mutableStateOf(deviceService.getServerAddress())
private set private set
var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL) var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL)
private set private set
@ -19,8 +20,8 @@ class SettingsViewModel : ViewModel() {
fun connect() { fun connect() {
//Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode") //Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode")
viewModelScope.launch { viewModelScope.launch {
DeviceService.setServerAddress(serverAddress) deviceService.setServerAddress(serverAddress)
DeviceService.createIntegration(deviceName, registrationCode) deviceService.createIntegration(deviceName, registrationCode)
} }
} }
@ -35,4 +36,15 @@ class SettingsViewModel : ViewModel() {
fun onRegistrationCodeChanged(code: String) { fun onRegistrationCodeChanged(code: String) {
registrationCode = code 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 package com.example.tvcontroller.services
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.util.Log import android.util.Log
import io.ktor.client.engine.cio.* import io.ktor.client.engine.cio.*
import io.ktor.client.* import io.ktor.client.*
@ -11,10 +13,16 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.HttpMethod import io.ktor.http.HttpMethod
import org.json.JSONObject 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 client = HttpClient(CIO)
private var serverAddress: String = "" private var serverAddress: String = ""
init {
loadPreferences()
}
suspend fun createIntegration(name: String, code: String) { suspend fun createIntegration(name: String, code: String) {
Log.i("DeviceService", "Creating integration for $name with code $code at $serverAddress") Log.i("DeviceService", "Creating integration for $name with code $code at $serverAddress")
val json = JSONObject() val json = JSONObject()
@ -29,6 +37,7 @@ object DeviceService {
} }
} }
savePreferences()
val body: String = response.body() val body: String = response.body()
Log.i("DeviceService", "Response: ${response.status.value} $body") Log.i("DeviceService", "Response: ${response.status.value} $body")
} catch (e: Exception) { } 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) { fun setServerAddress(url: String) {
serverAddress = url serverAddress = url
} }