fix: isolate infrared slots by hardware
This commit is contained in:
+5
-2
@@ -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()
|
||||||
|
|||||||
+7
-3
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -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,
|
||||||
|
|||||||
+42
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user