diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/AuthenticatedNavigation.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/AuthenticatedNavigation.kt index 3d03c75..beb6bac 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/AuthenticatedNavigation.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/AuthenticatedNavigation.kt @@ -239,7 +239,7 @@ fun AuthenticatedNavigation( profile.id, selection.deviceName, ) - DeviceType.INFRARED -> "${Routes.INFRARED_HUB}/${Uri.encode(profile.id.value)}" + DeviceType.INFRARED -> Routes.infraredHub(profile.id.value, selection.deviceName.value) } }, selectionForRoute = { route -> profile.selectionForRoute(route) }, @@ -367,9 +367,12 @@ private fun AuthenticatedNavHost( ) sceneExecutionDestination(onBack = navController::popBackStack) composable( - route = "${Routes.INFRARED_HUB}/{profileId}", - arguments = listOf(navArgument("profileId") { type = NavType.StringType }), - ) { + route = Routes.INFRARED_HUB, + arguments = listOf( + navArgument("profileId") { type = NavType.StringType }, + navArgument("deviceName") { type = NavType.StringType }, + ), + ) { entry -> InfraredHubRoute( onBack = { onClearDeviceSelection() @@ -381,7 +384,8 @@ private fun AuthenticatedNavHost( ) }, onOpenSettings = { - navController.navigate("${Routes.INFRARED_SETTINGS}/${Uri.encode(profile.id.value)}") + val deviceName = entry.arguments?.getString("deviceName").orEmpty() + navController.navigate(Routes.infraredSettings(profile.id.value, deviceName)) }, onSessionInvalid = onLogout, ) @@ -399,8 +403,11 @@ private fun AuthenticatedNavHost( ) } composable( - route = "${Routes.INFRARED_SETTINGS}/{profileId}", - arguments = listOf(navArgument("profileId") { type = NavType.StringType }), + route = Routes.INFRARED_SETTINGS, + arguments = listOf( + navArgument("profileId") { type = NavType.StringType }, + navArgument("deviceName") { type = NavType.StringType }, + ), ) { InfraredControlRoute( onBack = navController::popBackStack, @@ -473,9 +480,9 @@ private fun ProviderProfile.selectionForRoute(route: String?): DeviceSelection? deviceName = DeviceName(parts.drop(3).joinToString("/").decodeRoutePart()), type = DeviceType.TEMPERATURE_HUMIDITY, ) - parts.size >= 2 && parts[0] == Routes.INFRARED_HUB -> DeviceSelection( + parts.size >= 3 && parts[0] == "infrared_hub" -> DeviceSelection( profileId = id, - deviceName = DeviceName("红外遥控器"), + deviceName = DeviceName(parts[2].decodeRoutePart()), type = DeviceType.INFRARED, ) else -> null diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/Routes.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/Routes.kt index c7b2adb..ea9bf10 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/Routes.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/navigation/Routes.kt @@ -1,5 +1,7 @@ package com.flagship.abox.manager.ui.navigation +import android.net.Uri + object Routes { const val STARTUP = "startup" const val PROVIDER_SELECTION = "provider_selection" @@ -7,7 +9,13 @@ object Routes { const val AUTHENTICATED = "authenticated" const val SETTINGS = "settings" - const val INFRARED_HUB = "infrared_hub" + const val INFRARED_HUB = "infrared_hub/{profileId}/{deviceName}" const val INFRARED_PANEL = "infrared_panel" - const val INFRARED_SETTINGS = "infrared_settings" + const val INFRARED_SETTINGS = "infrared_settings/{profileId}/{deviceName}" + + fun infraredHub(profileId: String, deviceName: String): String = + "infrared_hub/${Uri.encode(profileId)}/${Uri.encode(deviceName)}" + + fun infraredSettings(profileId: String, deviceName: String): String = + "infrared_settings/${Uri.encode(profileId)}/${Uri.encode(deviceName)}" } diff --git a/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/hub/InfraredHubViewModel.kt b/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/hub/InfraredHubViewModel.kt index 9e69efd..5952514 100644 --- a/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/hub/InfraredHubViewModel.kt +++ b/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/hub/InfraredHubViewModel.kt @@ -49,6 +49,9 @@ class InfraredHubViewModel @Inject constructor( val profileId: ProviderProfileId? = rawProfileId?.takeIf { it.isNotBlank() }?.let { ProviderProfileId(it) } private val messageFlow = MutableStateFlow(null) + private val routeDeviceName: DeviceName? = savedStateHandle.get("deviceName") + ?.takeIf { it.isNotBlank() } + ?.let(::DeviceName) private data class HubSnapshot( val providerProfile: ProviderProfile? = null, @@ -68,7 +71,12 @@ class InfraredHubViewModel @Inject constructor( when (devResult) { is DomainResult.Failure -> flowOf(HubSnapshot(providerProfile = active, configError = devResult.error)) is DomainResult.Success -> { - val deviceName = devResult.value ?: DEFAULT_DEVICE_NAME + val deviceName = routeDeviceName ?: devResult.value ?: return@flatMapLatest flowOf( + HubSnapshot( + providerProfile = active, + configError = DomainError.InvalidRequest(detail = "No infrared device configured"), + ), + ) combine( virtualRemoteRepository.observeRemotes(profileId, deviceName), virtualRemoteRepository.observeSlotQuota(profileId, deviceName), diff --git a/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/ui/InfraredControlViewModel.kt b/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/ui/InfraredControlViewModel.kt index 2d494ac..30ba248 100644 --- a/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/ui/InfraredControlViewModel.kt +++ b/android/feature/infrared/src/main/kotlin/com/flagship/abox/manager/infrared/ui/InfraredControlViewModel.kt @@ -40,6 +40,9 @@ class InfraredControlViewModel @Inject constructor( private val deviceNameInputFlow = MutableStateFlow(null) private val messageFlow = MutableStateFlow(null) + private val routeDeviceName: DeviceName? = savedStateHandle.get("deviceName") + ?.takeIf { it.isNotBlank() } + ?.let(::DeviceName) private data class ServerState( val providerProfile: com.flagship.abox.manager.domain.ProviderProfile? = null, @@ -65,7 +68,12 @@ class InfraredControlViewModel @Inject constructor( ), ) is DomainResult.Success -> { - val deviceName = deviceResult.value ?: DEFAULT_DEVICE_NAME + val deviceName = routeDeviceName ?: deviceResult.value ?: return@flatMapLatest flowOf( + ServerState( + providerProfile = active, + configError = DomainError.InvalidRequest(detail = "No infrared device configured"), + ), + ) combine( virtualRemoteRepository.observeRemotes(profileId, deviceName), virtualRemoteRepository.observeSlotQuota(profileId, deviceName),