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.ui.tooling.preview)
|
||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
|
implementation(libs.ktor.client.core)
|
||||||
|
implementation(libs.ktor.client.cio)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
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.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -31,8 +29,8 @@ import com.example.tvcontroller.ui.theme.TVControllerTheme
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.example.tvcontroller.services.BluetoothService
|
||||||
import com.example.tvcontroller.ui.AppViewModel
|
import com.example.tvcontroller.ui.AppViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.example.tvcontroller
|
package com.example.tvcontroller
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@ -13,10 +12,6 @@ import androidx.compose.material3.OutlinedButton
|
|||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.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
|
||||||
@ -25,13 +20,7 @@ import com.example.tvcontroller.ui.AppViewModel
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
||||||
var serverUrl by remember { mutableStateOf("") }
|
val viewModel = viewModel<SettingsViewModel>()
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -54,23 +43,23 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
|||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = serverUrl,
|
value = viewModel.serverAddress,
|
||||||
onValueChange = { serverUrl = it },
|
onValueChange = viewModel::onServerAddressChanged,
|
||||||
label = { Text(stringResource(id = R.string.server_url_label)) }
|
label = { Text(stringResource(id = R.string.server_address_label)) }
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = deviceName,
|
value = viewModel.deviceName,
|
||||||
onValueChange = { deviceName = it },
|
onValueChange = viewModel::onDeviceNameChanged,
|
||||||
label = { Text(stringResource(id = R.string.device_name_label)) }
|
label = { Text(stringResource(id = R.string.device_name_label)) }
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = registrationCode,
|
value = viewModel.registrationCode,
|
||||||
onValueChange = { registrationCode = it },
|
onValueChange = viewModel::onRegistrationCodeChanged,
|
||||||
label = { Text(stringResource(id = R.string.registration_code_label)) }
|
label = { Text(stringResource(id = R.string.registration_code_label)) }
|
||||||
)
|
)
|
||||||
OutlinedButton(onClick = { connect() }, modifier = Modifier.fillMaxWidth()) {
|
OutlinedButton(onClick = { viewModel.connect() }, modifier = Modifier.fillMaxWidth()) {
|
||||||
Text(
|
Text(
|
||||||
stringResource(id = R.string.connect_button_label)
|
stringResource(id = R.string.connect_button_label)
|
||||||
)
|
)
|
||||||
@ -81,9 +70,15 @@ fun SettingsScreen(appViewModel: AppViewModel = viewModel()) {
|
|||||||
style = MaterialTheme.typography.headlineSmall
|
style = MaterialTheme.typography.headlineSmall
|
||||||
)
|
)
|
||||||
if (appViewModel.isBluetoothEnabled()) {
|
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 {
|
} 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.BluetoothAdapter
|
||||||
import android.bluetooth.BluetoothManager
|
import android.bluetooth.BluetoothManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.app.Activity
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.core.app.ComponentActivity
|
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
|
|
||||||
class BluetoothService(private val context: Context) {
|
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
|
import com.example.tvcontroller.Screen
|
||||||
|
|
||||||
data class AppUiState(
|
data class AppUiState(
|
||||||
val currentScreen: Screen = Screen.Camera,
|
val currentScreen: Screen = Screen.Settings,
|
||||||
)
|
)
|
||||||
@ -1,16 +1,7 @@
|
|||||||
package com.example.tvcontroller.ui
|
package com.example.tvcontroller.ui
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.lifecycle.ViewModel
|
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() {
|
class AppViewModel() : ViewModel() {
|
||||||
private var isBluetoothEnabled = mutableStateOf(false)
|
private var isBluetoothEnabled = mutableStateOf(false)
|
||||||
|
|||||||
@ -10,4 +10,5 @@
|
|||||||
<string name="connection_state_disconnected">disconnected</string>
|
<string name="connection_state_disconnected">disconnected</string>
|
||||||
<string name="save_button_label">Save</string>
|
<string name="save_button_label">Save</string>
|
||||||
<string name="connect_button_label">Connect</string>
|
<string name="connect_button_label">Connect</string>
|
||||||
|
<string name="server_address_label">Server address</string>
|
||||||
</resources>
|
</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
|
# 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,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# 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"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.1.5"
|
junitVersion = "1.1.5"
|
||||||
espressoCore = "3.5.1"
|
espressoCore = "3.5.1"
|
||||||
|
ktor = "3.1.0"
|
||||||
lifecycleRuntimeKtx = "2.6.1"
|
lifecycleRuntimeKtx = "2.6.1"
|
||||||
activityCompose = "1.8.0"
|
activityCompose = "1.8.0"
|
||||||
composeBom = "2024.04.01"
|
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-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
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]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user