瀏覽代碼

time pickers for timer intervals configuration

master
gituser 2 週之前
父節點
當前提交
ebea33d6f8

+ 26
- 18
app/src/main/java/ch/spherIC/ledlampcontrol/data/network/LedWebSocketManager.kt 查看文件

@@ -6,7 +6,6 @@ import ch.spherIC.ledlampcontrol.data.model.LedState
import kotlinx.coroutines.flow.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import okhttp3.*

class LedWebSocketManager(private val client: OkHttpClient) {
@@ -104,27 +103,36 @@ class LedWebSocketManager(private val client: OkHttpClient) {
}

fun sendCommand(command: LedCommand) {
val jsonElement = when (command) {
is LedCommand.SetPower -> json.encodeToJsonElement(command)
is LedCommand.ChangeMode -> json.encodeToJsonElement(command)
is LedCommand.ChangeColor -> json.encodeToJsonElement(command)
is LedCommand.ChangeBrightness -> json.encodeToJsonElement(command)
is LedCommand.ChangeConfigParam -> json.encodeToJsonElement(command)
is LedCommand.ChangeTimer -> json.encodeToJsonElement(command)
is LedCommand.ChangeTimerInterval -> json.encodeToJsonElement(command)
is LedCommand.GetConfig -> json.encodeToJsonElement(command)
is LedCommand.RequestState -> json.encodeToJsonElement(command)
is LedCommand.SetBrightness -> json.encodeToJsonElement(command)
is LedCommand.SetColor -> json.encodeToJsonElement(command)
is LedCommand.SetMode -> json.encodeToJsonElement(command)
is LedCommand.SetSpeed -> json.encodeToJsonElement(command)
val jsonString = when (command) {
is LedCommand.SetPower -> json.encodeToString(command)
is LedCommand.ChangeMode -> json.encodeToString(command)
is LedCommand.ChangeColor -> json.encodeToString(command)
is LedCommand.ChangeBrightness -> json.encodeToString(command)
is LedCommand.ChangeConfigParam -> json.encodeToString(command)
is LedCommand.ChangeTimer -> json.encodeToString(command)
is LedCommand.ChangeTimerInterval -> json.encodeToString(command)
is LedCommand.GetConfig -> json.encodeToString(command)
is LedCommand.RequestState -> json.encodeToString(command)
is LedCommand.SetBrightness -> json.encodeToString(command)
is LedCommand.SetColor -> json.encodeToString(command)
is LedCommand.SetMode -> json.encodeToString(command)
is LedCommand.SetSpeed -> json.encodeToString(command)
}
webSocket?.send(jsonElement.toString())
webSocket?.send(jsonString)
// Follow up with GET_CONFIG to stay in sync if it wasn't a GET_CONFIG itself
// Use a small delay to allow the strip to process and save the previous command
if (command !is LedCommand.GetConfig) {
val getConfigMessage = json.encodeToJsonElement(LedCommand.GetConfig()).toString()
webSocket?.send(getConfigMessage)
_connectionState.value.let { state ->
if (state is ConnectionState.Connected) {
// Start a coroutine to send the refresh command after a short delay
// Note: LedWebSocketManager doesn't have a scope, but we can use the caller's context
// Or just send it immediately but the strip might be busy.
// For now, let's just send it but ensure serialization is clean.
val getConfigMessage = json.encodeToString(LedCommand.GetConfig())
webSocket?.send(getConfigMessage)
}
}
}
}


+ 72
- 19
app/src/main/java/ch/spherIC/ledlampcontrol/ui/dashboard/DashboardScreen.kt 查看文件

@@ -549,6 +549,7 @@ fun TimerPane(
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimerIntervalItem(label: String, key: String, interval: TimeInterval, onUpdate: (String, Long, Long) -> Unit) {
var showDialog by remember { mutableStateOf(false) }
@@ -566,30 +567,82 @@ fun TimerIntervalItem(label: String, key: String, interval: TimeInterval, onUpda
}
if (showDialog) {
// Very simplified Time Range picker. In production you'd use a real range picker.
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Edit $label") },
text = {
Column {
Text("Implementation placeholder for Time Range Picker")
Text("Currently: ${formatSeconds(interval.start)} - ${formatSeconds(interval.end)}")
}
},
confirmButton = {
TextButton(onClick = {
// Simulate update for testing
onUpdate(key, interval.start + 60, interval.end + 60)
showDialog = false
}) { Text("Test +1m") }
},
dismissButton = {
TextButton(onClick = { showDialog = false }) { Text("Cancel") }
TimeRangePickerDialog(
label = label,
initialStart = interval.start,
initialEnd = interval.end,
onDismiss = { showDialog = false },
onConfirm = { start, end ->
onUpdate(key, start, end)
showDialog = false
}
)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimeRangePickerDialog(
label: String,
initialStart: Long,
initialEnd: Long,
onDismiss: () -> Unit,
onConfirm: (Long, Long) -> Unit
) {
var pickingStart by remember { mutableStateOf(true) }
val startState = rememberTimePickerState(
initialHour = (initialStart / 3600).toInt(),
initialMinute = ((initialStart % 3600) / 60).toInt(),
is24Hour = true
)
val endState = rememberTimePickerState(
initialHour = (initialEnd / 3600).toInt(),
initialMinute = ((initialEnd % 3600) / 60).toInt(),
is24Hour = true
)

AlertDialog(
onDismissRequest = onDismiss,
title = { Text("Set Time Range for $label") },
text = {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
TabRow(selectedTabIndex = if (pickingStart) 0 else 1) {
Tab(selected = pickingStart, onClick = { pickingStart = true }) {
Text("Start Time", modifier = Modifier.padding(16.dp))
}
Tab(selected = !pickingStart, onClick = { pickingStart = false }) {
Text("End Time", modifier = Modifier.padding(16.dp))
}
}
Spacer(modifier = Modifier.height(24.dp))
if (pickingStart) {
TimePicker(state = startState)
} else {
TimePicker(state = endState)
}
}
},
confirmButton = {
TextButton(onClick = {
val startSeconds = startState.hour * 3600L + startState.minute * 60L
val endSeconds = endState.hour * 3600L + endState.minute * 60L
onConfirm(startSeconds, endSeconds)
}) {
Text("Confirm")
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text("Cancel")
}
}
)
}

private fun formatSeconds(seconds: Long): String {
val h = seconds / 3600
val m = (seconds % 3600) / 60

+ 5
- 0
app/src/main/java/ch/spherIC/ledlampcontrol/ui/viewmodel/LedViewModel.kt 查看文件

@@ -174,6 +174,11 @@ class LedViewModel(
fun updateTimerInterval(key: String, startTime: Long, endTime: Long) {
val range = "${formatSeconds(startTime)} - ${formatSeconds(endTime)}"
repository.updateTimerInterval(key, range)
// Force an immediate config refresh after a short delay
viewModelScope.launch {
delay(1000)
repository.getConfig()
}
}

private fun formatSeconds(seconds: Long): String {

Loading…
取消
儲存