fix: isolate infrared slots by hardware

This commit is contained in:
2026-08-26 19:42:16 +08:00
parent 171d1daa50
commit b537cd1824
4 changed files with 60 additions and 5 deletions
@@ -25,8 +25,11 @@ class AddVirtualRemoteKey(
val buttonId = "CUSTOM_" + UUID.randomUUID().toString().take(8).uppercase() val buttonId = "CUSTOM_" + UUID.randomUUID().toString().take(8).uppercase()
val assignedSlot = if (remote.transmissionMode == TransmissionMode.STATIC_SLOTS) { val assignedSlot = if (remote.transmissionMode == TransmissionMode.STATIC_SLOTS) {
// Find next available slot // Find next available slot
val bindings = (repository.getKeyBindings(remoteId) as? DomainResult.Success)?.value.orEmpty() val quota = when (val result = repository.slotQuota(profileId, remote.deviceName)) {
val usedSlots = bindings.mapNotNull { it.assignedSlot?.toIntOrNull() }.toSet() is DomainResult.Success -> result.value
is DomainResult.Failure -> return result
}
val usedSlots = quota.assignedStaticSlots
val nextSlot = (1..99).firstOrNull { it !in usedSlots } val nextSlot = (1..99).firstOrNull { it !in usedSlots }
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "槽位配额已满,无法分配静态槽位")) ?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "槽位配额已满,无法分配静态槽位"))
nextSlot.toString() nextSlot.toString()
@@ -26,9 +26,13 @@ class LearnVirtualRemoteKey(
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "Button not found")) ?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "Button not found"))
val targetSlot = binding.assignedSlot ?: run { val targetSlot = binding.assignedSlot ?: run {
val allBindings = (repository.getKeyBindings(remoteId) as? DomainResult.Success)?.value.orEmpty() val quota = when (val result = repository.slotQuota(profileId, remote.deviceName)) {
val usedSlots = allBindings.mapNotNull { it.assignedSlot?.toIntOrNull() }.toSet() is DomainResult.Success -> result.value
val nextSlot = (1..99).firstOrNull { it !in usedSlots } ?: 1 is DomainResult.Failure -> return result
}
val nextSlot = quota.availableStaticSlots.firstOrNull() ?: return DomainResult.Failure(
DomainError.InvalidRequest(detail = "槽位配额已满,无法分配静态槽位"),
)
nextSlot.toString() nextSlot.toString()
} }
@@ -4,6 +4,7 @@ import com.flagship.abox.manager.domain.DeviceName
import com.flagship.abox.manager.domain.DomainResult import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.ProviderProfileId import com.flagship.abox.manager.domain.ProviderProfileId
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
interface VirtualRemoteRepository { interface VirtualRemoteRepository {
fun observeRemotes( fun observeRemotes(
@@ -25,6 +26,11 @@ interface VirtualRemoteRepository {
deviceName: DeviceName, deviceName: DeviceName,
): Flow<DomainResult<SlotQuotaSummary>> ): Flow<DomainResult<SlotQuotaSummary>>
suspend fun slotQuota(
profileId: ProviderProfileId,
deviceName: DeviceName,
): DomainResult<SlotQuotaSummary> = observeSlotQuota(profileId, deviceName).first()
suspend fun getRemote( suspend fun getRemote(
profileId: ProviderProfileId, profileId: ProviderProfileId,
remoteId: VirtualRemoteId, remoteId: VirtualRemoteId,
@@ -116,4 +116,46 @@ class VirtualRemoteUseCaseTest {
val fetched = (repository.getRemote(profileId, remoteId) as DomainResult.Success<VirtualRemote?>).value val fetched = (repository.getRemote(profileId, remoteId) as DomainResult.Success<VirtualRemote?>).value
assertEquals(null, fetched) assertEquals(null, fetched)
} }
@Test
fun staticKeyAllocationUsesSlotsAcrossRemotesOnTheSameHardware() = runTest {
val firstRemote = VirtualRemote(
id = VirtualRemoteId("remote-one"),
profileId = profileId,
deviceName = deviceName,
displayName = "First",
type = RemoteDeviceType.TV,
transmissionMode = TransmissionMode.STATIC_SLOTS,
createdAtEpochMillis = 1L,
updatedAtEpochMillis = 1L,
)
repository.createRemote(
firstRemote,
listOf(
RemoteKeyBinding(
id = "binding-one",
remoteId = firstRemote.id,
profileId = profileId,
buttonId = "POWER",
displayName = "Power",
assignedSlot = "1",
),
),
)
val secondRemote = VirtualRemote(
id = VirtualRemoteId("remote-two"),
profileId = profileId,
deviceName = deviceName,
displayName = "Second",
type = RemoteDeviceType.TV,
transmissionMode = TransmissionMode.STATIC_SLOTS,
createdAtEpochMillis = 2L,
updatedAtEpochMillis = 2L,
)
repository.createRemote(secondRemote, emptyList())
val result = AddVirtualRemoteKey(repository)(profileId, secondRemote.id, "Volume")
assertEquals("2", (result as DomainResult.Success).value.assignedSlot)
}
} }