diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlComponents.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlComponents.kt new file mode 100644 index 0000000..593cd2b --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlComponents.kt @@ -0,0 +1,92 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.flagship.abox.manager.designsystem.ABoxButton + +@Composable +internal fun DevicePageScaffold( + title: String, + description: String, + onBackClick: () -> Unit, + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, +) { + Column( + modifier = modifier.padding(32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = title, + style = MaterialTheme.typography.headlineLarge, + textAlign = TextAlign.Center, + ) + Text( + text = description, + modifier = Modifier.padding(top = 12.dp, bottom = 24.dp), + style = MaterialTheme.typography.bodyLarge, + textAlign = TextAlign.Center, + ) + content() + OutlinedButton( + onClick = onBackClick, + modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp), + ) { + Text("返回设备列表") + } + } +} + +@Composable +internal fun PrimaryActionButton( + text: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + ABoxButton( + onClick = onClick, + modifier = modifier.fillMaxWidth(), + ) { + Text(text) + } +} + +@Composable +internal fun TwoColumnActions( + leftText: String, + rightText: String, + onLeftClick: () -> Unit, + onRightClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + PrimaryActionButton( + text = leftText, + onClick = onLeftClick, + modifier = Modifier.weight(1f), + ) + PrimaryActionButton( + text = rightText, + onClick = onRightClick, + modifier = Modifier.weight(1f), + ) + } +} diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlRoutes.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlRoutes.kt new file mode 100644 index 0000000..71b5a56 --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlRoutes.kt @@ -0,0 +1,29 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.compose.composable + +const val DEVICE_LIST_ROUTE = "device_list" +private const val SOCKET_ROUTE = "device_socket" +private const val TH_ROUTE = "device_temperature_humidity" +private const val INFRARED_ROUTE = "device_infrared" + +fun NavGraphBuilder.deviceControlGraph(navController: NavHostController) { + composable(DEVICE_LIST_ROUTE) { + DeviceListScreen( + onSocketClick = { navController.navigate(SOCKET_ROUTE) }, + onTemperatureHumidityClick = { navController.navigate(TH_ROUTE) }, + onInfraredClick = { navController.navigate(INFRARED_ROUTE) }, + ) + } + composable(SOCKET_ROUTE) { + SocketControlScreen(onBackClick = navController::popBackStack) + } + composable(TH_ROUTE) { + TemperatureHumidityScreen(onBackClick = navController::popBackStack) + } + composable(INFRARED_ROUTE) { + InfraredControlScreen(onBackClick = navController::popBackStack) + } +} diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceListScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceListScreen.kt new file mode 100644 index 0000000..a710c94 --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceListScreen.kt @@ -0,0 +1,80 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.flagship.abox.manager.designsystem.ABoxButton + +@Composable +fun DeviceListScreen( + onSocketClick: () -> Unit, + onTemperatureHumidityClick: () -> Unit, + onInfraredClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .fillMaxSize() + .padding(32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = "设备列表", + style = MaterialTheme.typography.headlineLarge, + textAlign = TextAlign.Center, + ) + Text( + text = "选择需要控制或查看状态的 ABox 终端设备。", + modifier = Modifier.padding(top = 12.dp, bottom = 32.dp), + style = MaterialTheme.typography.bodyLarge, + textAlign = TextAlign.Center, + ) + DeviceEntryButton( + text = "智能插座", + description = "查看插座状态,执行打开或关闭操作。", + onClick = onSocketClick, + ) + DeviceEntryButton( + text = "温湿度传感器", + description = "查询当前温度与湿度读数。", + onClick = onTemperatureHumidityClick, + ) + DeviceEntryButton( + text = "红外遥控器", + description = "发送红外按键,或进入红外学习流程。", + onClick = onInfraredClick, + ) + } +} + +@Composable +private fun DeviceEntryButton( + text: String, + description: String, + onClick: () -> Unit, +) { + ABoxButton( + onClick = onClick, + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + ) { + Column( + modifier = Modifier.padding(vertical = 8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text(text = text, style = MaterialTheme.typography.titleMedium) + Text(text = description, style = MaterialTheme.typography.bodySmall) + } + } +} diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/InfraredControlScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/InfraredControlScreen.kt new file mode 100644 index 0000000..8d06d7f --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/InfraredControlScreen.kt @@ -0,0 +1,75 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +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.text.style.TextAlign +import androidx.compose.ui.unit.dp + +@Composable +fun InfraredControlScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + var deviceName by remember { mutableStateOf("红外遥控器") } + var key by remember { mutableStateOf("") } + var statusText by remember { mutableStateOf("输入设备名称和按键 KEY 后执行红外操作") } + + DevicePageScaffold( + title = "红外遥控器", + description = "发送红外按键或学习新按键。后续可接入 InfraredGateway。", + onBackClick = onBackClick, + modifier = modifier.fillMaxSize(), + ) { + OutlinedTextField( + value = deviceName, + onValueChange = { deviceName = it }, + modifier = Modifier.fillMaxWidth(), + label = { Text("红外设备名称") }, + singleLine = true, + ) + OutlinedTextField( + value = key, + onValueChange = { key = it }, + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), + label = { Text("按键 KEY,例如 POWER") }, + singleLine = true, + ) + TwoColumnActions( + leftText = "发送", + rightText = "学习", + onLeftClick = { + statusText = if (key.isBlank()) { + "请先输入按键 KEY。" + } else { + "已请求发送 $key(待接入真实红外发送)" + } + }, + onRightClick = { + statusText = if (key.isBlank()) { + "请先输入按键 KEY。" + } else { + "已请求学习 $key(待接入真实红外学习)" + } + }, + modifier = Modifier.padding(top = 24.dp), + ) + Text( + text = statusText, + modifier = Modifier.padding(top = 20.dp), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + ) + } +} diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/SocketControlScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/SocketControlScreen.kt new file mode 100644 index 0000000..b5e966f --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/SocketControlScreen.kt @@ -0,0 +1,60 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +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.text.style.TextAlign +import androidx.compose.ui.unit.dp + +@Composable +fun SocketControlScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + var statusText by remember { mutableStateOf("当前状态:未知") } + + DevicePageScaffold( + title = "智能插座", + description = "Kotlin Compose 版插座控制页面。后续可接入 SocketGateway。", + onBackClick = onBackClick, + modifier = modifier.fillMaxSize(), + ) { + Text( + text = statusText, + modifier = Modifier.padding(bottom = 24.dp), + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center, + ) + PrimaryActionButton( + text = "刷新状态", + onClick = { + statusText = "当前状态:等待接入真实状态查询" + }, + ) + TwoColumnActions( + leftText = "打开", + rightText = "关闭", + onLeftClick = { + statusText = "当前状态:已请求打开(待接入真实控制)" + }, + onRightClick = { + statusText = "当前状态:已请求关闭(待接入真实控制)" + }, + modifier = Modifier.padding(top = 16.dp), + ) + Text( + text = "建议后续调用 SocketGateway.getStatus / setPower,而不是直接调用 ABSDK。", + modifier = Modifier.padding(top = 20.dp), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + ) + } +} diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/TemperatureHumidityScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/TemperatureHumidityScreen.kt new file mode 100644 index 0000000..18508db --- /dev/null +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/TemperatureHumidityScreen.kt @@ -0,0 +1,57 @@ +package com.flagship.abox.manager.ui.devicecontrol + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +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.text.style.TextAlign +import androidx.compose.ui.unit.dp + +@Composable +fun TemperatureHumidityScreen( + onBackClick: () -> Unit, + modifier: Modifier = Modifier, +) { + var temperature by remember { mutableStateOf("-- ℃") } + var humidity by remember { mutableStateOf("-- %") } + var statusText by remember { mutableStateOf("点击按钮查询当前温湿度") } + + DevicePageScaffold( + title = "温湿度状态", + description = "显示温度与湿度读数。后续可接入 TemperatureHumidityGateway。", + onBackClick = onBackClick, + modifier = modifier.fillMaxSize(), + ) { + Text( + text = "温度:$temperature", + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center, + ) + Text( + text = "湿度:$humidity", + modifier = Modifier.padding(top = 12.dp, bottom = 24.dp), + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center, + ) + PrimaryActionButton( + text = "刷新温湿度", + onClick = { + temperature = "待接入" + humidity = "待接入" + statusText = "已触发刷新动作,等待接入真实 ABSDK bridge。" + }, + ) + Text( + text = statusText, + modifier = Modifier.padding(top = 20.dp), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + ) + } +} diff --git a/docs/device-control-compose-ui-change-log.md b/docs/device-control-compose-ui-change-log.md new file mode 100644 index 0000000..bfefaec --- /dev/null +++ b/docs/device-control-compose-ui-change-log.md @@ -0,0 +1,344 @@ +# Device Control Compose UI Change Log + +Branch: `feature/device-control-compose-ui` + +## Summary + +This branch adds a Kotlin Jetpack Compose implementation for the device-control UI owned by this feature area. + +The implementation introduces a new device-control entry point and a group of Compose screens for the three device types required by the current project scope: + +- Socket device control +- Temperature/humidity status display +- Infrared remote control actions + +The existing placeholder/foundation app flow is preserved. The new device-control flow is added as an additional navigation path instead of replacing the existing screens. + +## Modified Files + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/ABoxManagerApp.kt` + +Changes: + +- Added an entry button on the foundation screen for the Kotlin device-control UI. +- Registered the new device-control navigation graph in the existing `NavHost`. +- Preserved the existing foundation and placeholder routes. + +Purpose: + +- Allows teammates to open the newly added device-control screens from the current Compose app shell. + +## Added Files + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlRoutes.kt` + +Adds navigation routes and a small navigation graph for the device-control feature. + +Routes included: + +- Device list +- Socket control +- Temperature/humidity status +- Infrared control + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceListScreen.kt` + +Adds the top-level device list screen. + +The screen contains entries for: + +- Smart socket +- Temperature/humidity sensor +- Infrared remote controller + +Each entry navigates to its corresponding Compose screen. + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlComponents.kt` + +Adds shared UI components used by the device-control screens. + +Included components: + +- Shared device page scaffold +- Primary action button wrapper +- Two-column action button row + +Purpose: + +- Keeps repeated screen layout and action button patterns consistent across device screens. + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/SocketControlScreen.kt` + +Adds a Compose screen for socket control. + +Current scope: + +- Displays socket status text. +- Provides actions for refreshing status, turning on, and turning off. +- Uses local Compose state as a placeholder. + +Future integration point: + +- Replace placeholder state handling with `SocketGateway.getStatus(...)` and `SocketGateway.setPower(...)` through a ViewModel. + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/TemperatureHumidityScreen.kt` + +Adds a Compose screen for temperature/humidity display. + +Current scope: + +- Displays temperature and humidity values. +- Provides a refresh action. +- Uses local Compose state as a placeholder. + +Future integration point: + +- Replace placeholder state handling with `TemperatureHumidityGateway.getReading(...)` through a ViewModel. + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/InfraredControlScreen.kt` + +Adds a Compose screen for infrared remote operations. + +Current scope: + +- Allows entering an infrared device name. +- Allows entering an infrared key name. +- Provides send and learn actions. +- Uses local Compose state as a placeholder. + +Future integration point: + +- Replace placeholder state handling with `InfraredGateway.sendKey(...)` and `InfraredGateway.learnKey(...)` through a ViewModel. + +## Architecture Notes + +This branch follows the current repository direction: + +- Kotlin instead of Java +- Jetpack Compose instead of XML layouts +- Single-Activity UI instead of multiple Activities +- Navigation Compose instead of `Intent`-based Activity navigation +- Existing design-system wrappers where practical + +This branch intentionally does not copy the previous Java/XML experiment module into the team repository. + +## ABSDK Integration Notes + +The UI screens added in this branch do not call ABSDK directly. + +The repository already contains domain abstractions and an ABSDK bridge: + +- `SocketGateway` +- `TemperatureHumidityGateway` +- `InfraredGateway` +- `AbsdkBridge` +- `VendorAbsdkClient` + +Recommended next step: + +- Add ViewModels for the device-control screens. +- Inject/use the gateway interfaces from the domain layer. +- Expose screen UI state from ViewModels to the Compose screens. + +## Scope Intentionally Not Included + +This branch does not include: + +- Direct ABSDK calls from Compose UI +- New Java Activity classes +- XML layout files +- A separate Android module copied from the experiment project +- Full session/login integration for device gateway calls +- Persistent infrared key storage + +These should be added in later branches or follow-up commits after team architecture review. + +## Files Intended for Commit + +The intended commit scope is limited to: + +```text +android/app/src/main/kotlin/com/flagship/abox/manager/ui/ABoxManagerApp.kt +android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/ +docs/device-control-compose-ui-change-log.md +``` + +`settings.gradle.kts` is intentionally not part of this feature commit unless the team decides the local toolchain resolver change is required. + +--- + +# 设备控制 Compose UI 修改说明(中文) + +分支:`feature/device-control-compose-ui` + +## 概要 + +本分支新增了一套 Kotlin Jetpack Compose 版本的设备控制 UI,用于承载当前负责的设备列表与三类终端设备页面。 + +本次新增的设备范围包括: + +- 智能插座控制 +- 温湿度状态显示 +- 红外遥控器操作 + +本分支没有替换原有的 foundation / placeholder 页面,而是在现有 Compose 应用壳中新增了一个设备控制入口。因此,原有占位流程仍然保留,设备控制流程是额外新增的导航路径。 + +## 修改文件 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/ABoxManagerApp.kt` + +修改内容: + +- 在 foundation 页面增加了一个进入 Kotlin 版设备控制 UI 的按钮。 +- 在现有 `NavHost` 中注册了设备控制导航图。 +- 保留了原有 foundation route 和 placeholder route。 + +作用: + +- 方便团队成员从当前 Compose 应用入口进入新增加的设备控制页面。 + +## 新增文件 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlRoutes.kt` + +新增设备控制相关的 Compose Navigation 路由与导航图。 + +包含的页面路由: + +- 设备列表 +- 智能插座控制 +- 温湿度状态 +- 红外遥控器控制 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceListScreen.kt` + +新增设备列表页面。 + +页面包含三个设备入口: + +- 智能插座 +- 温湿度传感器 +- 红外遥控器 + +每个入口会跳转到对应的 Compose 设备页面。 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/DeviceControlComponents.kt` + +新增设备控制页面共用 UI 组件。 + +包含: + +- 通用设备页面脚手架 +- 主要操作按钮封装 +- 双按钮横向操作区 + +作用: + +- 减少各设备页面中的重复布局代码。 +- 让插座、温湿度、红外页面保持相似的视觉结构。 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/SocketControlScreen.kt` + +新增智能插座控制页面。 + +当前实现范围: + +- 显示插座状态文本。 +- 提供刷新状态、打开、关闭三个操作入口。 +- 当前使用本地 Compose state 作为占位状态。 + +后续接入点: + +- 通过 ViewModel 接入 `SocketGateway.getStatus(...)`。 +- 通过 ViewModel 接入 `SocketGateway.setPower(...)`。 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/TemperatureHumidityScreen.kt` + +新增温湿度状态页面。 + +当前实现范围: + +- 显示温度值。 +- 显示湿度值。 +- 提供刷新温湿度按钮。 +- 当前使用本地 Compose state 作为占位状态。 + +后续接入点: + +- 通过 ViewModel 接入 `TemperatureHumidityGateway.getReading(...)`。 + +### `android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/InfraredControlScreen.kt` + +新增红外遥控器页面。 + +当前实现范围: + +- 输入红外设备名称。 +- 输入红外按键 KEY。 +- 提供发送红外按键操作。 +- 提供学习红外按键操作。 +- 当前使用本地 Compose state 作为占位状态。 + +后续接入点: + +- 通过 ViewModel 接入 `InfraredGateway.sendKey(...)`。 +- 通过 ViewModel 接入 `InfraredGateway.learnKey(...)`。 + +## 架构说明 + +本分支遵循当前小组仓库的技术方向: + +- 使用 Kotlin,而不是 Java。 +- 使用 Jetpack Compose,而不是 XML layout。 +- 使用单 Activity 架构,而不是多个 Activity 跳转。 +- 使用 Navigation Compose,而不是 `Intent` 页面跳转。 +- 尽量复用已有 design system 中的组件封装。 + +本分支没有把之前个人实验项目中的 Java/XML 模块直接复制进团队仓库。 + +## ABSDK 接入说明 + +本次新增的 Compose UI 页面没有直接调用 ABSDK。 + +当前仓库中已经存在较正式的 domain 抽象和 ABSDK bridge: + +- `SocketGateway` +- `TemperatureHumidityGateway` +- `InfraredGateway` +- `AbsdkBridge` +- `VendorAbsdkClient` + +因此后续真实设备控制逻辑建议通过 ViewModel 调用 domain gateway,而不是在 Compose UI 中直接调用 ABSDK。 + +推荐后续工作: + +- 为插座页面新增 ViewModel。 +- 为温湿度页面新增 ViewModel。 +- 为红外页面新增 ViewModel。 +- 在 ViewModel 中调用对应 gateway。 +- 将调用结果转换为 Compose UI state。 + +## 本分支未包含的内容 + +本分支暂不包含: + +- Compose UI 中直接调用 ABSDK。 +- 新增 Java Activity。 +- 新增 XML layout。 +- 从个人实验项目复制独立 Android 模块。 +- 完整登录/session 与设备 gateway 的联动。 +- 红外学习按键的持久化存储。 + +这些内容建议在团队确认架构之后,作为后续 branch 或后续 commit 继续实现。 + +## 预期提交范围 + +本次提交范围应限制在: + +```text +android/app/src/main/kotlin/com/flagship/abox/manager/ui/ABoxManagerApp.kt +android/app/src/main/kotlin/com/flagship/abox/manager/ui/devicecontrol/ +docs/device-control-compose-ui-change-log.md +``` + +`settings.gradle.kts` 当前不属于本次设备控制 UI 功能提交范围,除非团队明确认为本地 toolchain resolver 配置也需要进入 PR。