refactor: align infrared feature with provider login architecture and remove legacy temporary login flow

This commit is contained in:
2026-08-25 11:41:06 +08:00
parent 1fdc9bd376
commit ee42d59879
6 changed files with 1 additions and 188 deletions
@@ -1,26 +0,0 @@
package com.flagship.abox.manager.ui
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.flagship.abox.manager.MainActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ABoxManagerAppTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@Test
fun opensInfraredControlScreenFromFoundationScreen() {
composeTestRule.onNodeWithText("Infrared Control").performClick()
composeTestRule.onNodeWithTag("infrared_mode_label").assertIsDisplayed()
composeTestRule.onNodeWithTag("infrared_device_name_input").assertIsDisplayed()
}
}
@@ -1,4 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application android:usesCleartextTraffic="true" />
</manifest>
@@ -1,41 +0,0 @@
package com.flagship.abox.manager.di
import com.flagship.abox.manager.domain.DeviceName
import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.InfraredCode
import com.flagship.abox.manager.domain.InfraredCodeDownloadResult
import com.flagship.abox.manager.domain.InfraredGateway
import com.flagship.abox.manager.domain.ProviderProfileId
import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeMode
import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeModeStore
class DebugRoutingInfraredGateway(
private val modeStore: InfraredRuntimeModeStore,
private val fakeGateway: InfraredGateway,
private val realGateway: InfraredGateway,
) : InfraredGateway {
private suspend fun delegate(): InfraredGateway {
return when (modeStore.currentMode()) {
InfraredRuntimeMode.REAL_ABSDK -> realGateway
InfraredRuntimeMode.FAKE -> fakeGateway
}
}
override suspend fun sendKey(
profileId: ProviderProfileId,
deviceName: DeviceName,
key: String,
): DomainResult<Unit> = delegate().sendKey(profileId, deviceName, key)
override suspend fun learnKey(
profileId: ProviderProfileId,
deviceName: DeviceName,
key: String,
): DomainResult<Unit> = delegate().learnKey(profileId, deviceName, key)
override suspend fun downloadCodes(
profileId: ProviderProfileId,
codes: List<InfraredCode>,
): DomainResult<List<InfraredCodeDownloadResult>> = delegate().downloadCodes(profileId, codes)
}
@@ -1,47 +0,0 @@
package com.flagship.abox.manager.di
import com.flagship.abox.manager.domain.DeviceName
import com.flagship.abox.manager.domain.DomainError
import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.InfraredCode
import com.flagship.abox.manager.domain.InfraredCodeDownloadResult
import com.flagship.abox.manager.domain.InfraredGateway
import com.flagship.abox.manager.domain.ProviderProfileId
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object InfraredReleaseModule {
@Provides
@Singleton
fun provideInfraredGateway(): InfraredGateway = object : InfraredGateway {
override suspend fun sendKey(
profileId: ProviderProfileId,
deviceName: DeviceName,
key: String,
): DomainResult<Unit> = disabledFailure()
override suspend fun learnKey(
profileId: ProviderProfileId,
deviceName: DeviceName,
key: String,
): DomainResult<Unit> = disabledFailure()
override suspend fun downloadCodes(
profileId: ProviderProfileId,
codes: List<InfraredCode>,
): DomainResult<List<InfraredCodeDownloadResult>> = disabledFailure()
private fun <T> disabledFailure(): DomainResult<T> = DomainResult.Failure(
DomainError.OperationFailed(
externalCode = "REAL_ABSDK_DISABLED",
detail = "Infrared hardware transport is disabled in release builds",
),
)
}
}
@@ -1,70 +0,0 @@
package com.flagship.abox.manager.di
import com.flagship.abox.manager.domain.DeviceName
import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.InfraredCode
import com.flagship.abox.manager.domain.ProviderProfileId
import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeMode
import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeModeStore
import com.flagship.abox.manager.testing.fakes.FakeInfraredGateway
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
private class TestModeStore : InfraredRuntimeModeStore {
private val modeFlow = MutableStateFlow(InfraredRuntimeMode.FAKE)
override val mode: Flow<InfraredRuntimeMode> = modeFlow
override suspend fun currentMode(): InfraredRuntimeMode = modeFlow.value
override suspend fun setMode(mode: InfraredRuntimeMode): DomainResult<Unit> {
modeFlow.value = mode
return DomainResult.Success(Unit)
}
}
class DebugRoutingInfraredGatewayTest {
private val modeStore = TestModeStore()
private val fake = FakeInfraredGateway()
private val real = FakeInfraredGateway()
private val router = DebugRoutingInfraredGateway(modeStore, fake, real)
private val profile = ProviderProfileId("profile1")
private val device = DeviceName("ir-1")
@Test
fun delegatesToFakeByDefault() = runTest {
val result = router.sendKey(profile, device, "key1")
assertTrue(result is DomainResult.Success)
assertEquals(1, fake.sentKeys.size)
assertTrue(real.sentKeys.isEmpty())
router.learnKey(profile, device, "key2")
assertEquals(1, fake.learnedKeys.size)
assertTrue(real.learnedKeys.isEmpty())
router.downloadCodes(profile, listOf(InfraredCode(device, "k", "code")))
assertEquals(1, fake.downloadCalls.size)
assertTrue(real.downloadCalls.isEmpty())
}
@Test
fun delegatesToRealWhenModeIsRealAbsdk() = runTest {
modeStore.setMode(InfraredRuntimeMode.REAL_ABSDK)
val result = router.sendKey(profile, device, "key1")
assertTrue(result is DomainResult.Success)
assertTrue(fake.sentKeys.isEmpty())
assertEquals(1, real.sentKeys.size)
router.learnKey(profile, device, "key2")
assertTrue(fake.learnedKeys.isEmpty())
assertEquals(1, real.learnedKeys.size)
router.downloadCodes(profile, listOf(InfraredCode(device, "k", "code")))
assertTrue(fake.downloadCalls.isEmpty())
assertEquals(1, real.downloadCalls.size)
}
}
+1
View File
@@ -17,6 +17,7 @@ espresso = "3.6.1"
[libraries] [libraries]
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" } androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" } androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" }
androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" }