feat: add logic to create integration using code
This commit is contained in:
parent
035393578f
commit
7a871f9fa4
@ -50,6 +50,8 @@ dependencies {
|
||||
implementation(libs.androidx.ui.tooling.preview)
|
||||
implementation(libs.androidx.material3)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.ktor.client.core)
|
||||
implementation(libs.ktor.client.cio)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
package com.example.tvcontroller
|
||||
|
||||
import android.util.Log
|
||||
|
||||
object DeviceService {
|
||||
fun createIntegration(name: String, code: String) {
|
||||
Log.i("DeviceService", "Creating integration for $name with code $code")
|
||||
}
|
||||
}
|
||||
@ -14,10 +14,8 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@ -31,8 +29,8 @@ import com.example.tvcontroller.ui.theme.TVControllerTheme
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.example.tvcontroller.services.BluetoothService
|
||||
import com.example.tvcontroller.ui.AppViewModel
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.example.tvcontroller
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@ -13,10 +12,6 @@ import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -25,13 +20,7 @@ import com.example.tvcontroller.ui.AppViewModel
|
||||
|
||||
@Composable
|
||||
fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
||||
var serverUrl by remember { mutableStateOf("") }
|
||||
var deviceName by remember { mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL) }
|
||||
var registrationCode by remember { mutableStateOf("") }
|
||||
|
||||
fun connect() {
|
||||
Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode")
|
||||
}
|
||||
val viewModel = viewModel<SettingsViewModel>()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@ -54,23 +43,23 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
||||
)
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = serverUrl,
|
||||
onValueChange = { serverUrl = it },
|
||||
label = { Text(stringResource(id = R.string.server_url_label)) }
|
||||
value = viewModel.serverAddress,
|
||||
onValueChange = viewModel::onServerAddressChanged,
|
||||
label = { Text(stringResource(id = R.string.server_address_label)) }
|
||||
)
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = deviceName,
|
||||
onValueChange = { deviceName = it },
|
||||
value = viewModel.deviceName,
|
||||
onValueChange = viewModel::onDeviceNameChanged,
|
||||
label = { Text(stringResource(id = R.string.device_name_label)) }
|
||||
)
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = registrationCode,
|
||||
onValueChange = { registrationCode = it },
|
||||
value = viewModel.registrationCode,
|
||||
onValueChange = viewModel::onRegistrationCodeChanged,
|
||||
label = { Text(stringResource(id = R.string.registration_code_label)) }
|
||||
)
|
||||
OutlinedButton(onClick = { connect() }, modifier = Modifier.fillMaxWidth()) {
|
||||
OutlinedButton(onClick = { viewModel.connect() }, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
stringResource(id = R.string.connect_button_label)
|
||||
)
|
||||
@ -81,9 +70,15 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
if (appViewModel.isBluetoothEnabled()) {
|
||||
Text(text = "Controller settings: Bluetooth is enabled.", style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
text = "Controller settings: Bluetooth is enabled.",
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
} else {
|
||||
Text(text = "Bluetooth is disabled. Please enable it in settings.", style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
text = "Bluetooth is disabled. Please enable it in settings.",
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package com.example.tvcontroller
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.tvcontroller.services.DeviceService
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SettingsViewModel : ViewModel() {
|
||||
var serverAddress by mutableStateOf(DeviceService.getServerAddress())
|
||||
private set
|
||||
var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL)
|
||||
private set
|
||||
var registrationCode by mutableStateOf("")
|
||||
private set
|
||||
|
||||
fun connect() {
|
||||
//Log.i("SettingsScreen", "Save settings: $serverUrl, $deviceName, $registrationCode")
|
||||
viewModelScope.launch {
|
||||
DeviceService.setServerAddress(serverAddress)
|
||||
DeviceService.createIntegration(deviceName, registrationCode)
|
||||
}
|
||||
}
|
||||
|
||||
fun onServerAddressChanged(url: String) {
|
||||
serverAddress = url
|
||||
}
|
||||
|
||||
fun onDeviceNameChanged(name: String) {
|
||||
deviceName = name
|
||||
}
|
||||
|
||||
fun onRegistrationCodeChanged(code: String) {
|
||||
registrationCode = code
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,11 @@
|
||||
package com.example.tvcontroller
|
||||
package com.example.tvcontroller.services
|
||||
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.IntentFilter
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.core.app.ComponentActivity
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
|
||||
class BluetoothService(private val context: Context) {
|
||||
@ -0,0 +1,46 @@
|
||||
package com.example.tvcontroller.services
|
||||
|
||||
import android.util.Log
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.headers
|
||||
import io.ktor.client.request.request
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.HttpResponse
|
||||
import io.ktor.http.HttpMethod
|
||||
import org.json.JSONObject
|
||||
|
||||
object DeviceService {
|
||||
private var client = HttpClient(CIO)
|
||||
private var serverAddress: String = ""
|
||||
|
||||
suspend fun createIntegration(name: String, code: String) {
|
||||
Log.i("DeviceService", "Creating integration for $name with code $code at $serverAddress")
|
||||
val json = JSONObject()
|
||||
json.put("name", name)
|
||||
json.put("code", code)
|
||||
try {
|
||||
val response: HttpResponse = client.request("http://$serverAddress/api/integrations") {
|
||||
method = HttpMethod.Post
|
||||
setBody(json.toString())
|
||||
headers {
|
||||
append("Content-Type", "application/json")
|
||||
}
|
||||
}
|
||||
|
||||
val body: String = response.body()
|
||||
Log.i("DeviceService", "Response: ${response.status.value} $body")
|
||||
} catch (e: Exception) {
|
||||
Log.e("DeviceService", "Error creating integration", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun setServerAddress(url: String) {
|
||||
serverAddress = url
|
||||
}
|
||||
|
||||
fun getServerAddress(): String {
|
||||
return serverAddress
|
||||
}
|
||||
}
|
||||
@ -3,5 +3,5 @@ package com.example.tvcontroller.ui
|
||||
import com.example.tvcontroller.Screen
|
||||
|
||||
data class AppUiState(
|
||||
val currentScreen: Screen = Screen.Camera,
|
||||
val currentScreen: Screen = Screen.Settings,
|
||||
)
|
||||
@ -1,16 +1,7 @@
|
||||
package com.example.tvcontroller.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.example.tvcontroller.BluetoothService
|
||||
import com.example.tvcontroller.Screen
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
class AppViewModel() : ViewModel() {
|
||||
private var isBluetoothEnabled = mutableStateOf(false)
|
||||
|
||||
@ -10,4 +10,5 @@
|
||||
<string name="connection_state_disconnected">disconnected</string>
|
||||
<string name="save_button_label">Save</string>
|
||||
<string name="connect_button_label">Connect</string>
|
||||
<string name="server_address_label">Server address</string>
|
||||
</resources>
|
||||
@ -20,4 +20,4 @@ kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
@ -5,6 +5,7 @@ coreKtx = "1.10.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
ktor = "3.1.0"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
activityCompose = "1.8.0"
|
||||
composeBom = "2024.04.01"
|
||||
@ -26,6 +27,8 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin
|
||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
|
||||
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user