feat(ui): complete ABox app experience redesign #10
+5
-2
@@ -25,8 +25,11 @@ class AddVirtualRemoteKey(
|
||||
val buttonId = "CUSTOM_" + UUID.randomUUID().toString().take(8).uppercase()
|
||||
val assignedSlot = if (remote.transmissionMode == TransmissionMode.STATIC_SLOTS) {
|
||||
// Find next available slot
|
||||
val bindings = (repository.getKeyBindings(remoteId) as? DomainResult.Success)?.value.orEmpty()
|
||||
val usedSlots = bindings.mapNotNull { it.assignedSlot?.toIntOrNull() }.toSet()
|
||||
val quota = when (val result = repository.slotQuota(profileId, remote.deviceName)) {
|
||||
is DomainResult.Success -> result.value
|
||||
is DomainResult.Failure -> return result
|
||||
}
|
||||
val usedSlots = quota.assignedStaticSlots
|
||||
val nextSlot = (1..99).firstOrNull { it !in usedSlots }
|
||||
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "槽位配额已满,无法分配静态槽位"))
|
||||
nextSlot.toString()
|
||||
|
||||
+7
-3
@@ -26,9 +26,13 @@ class LearnVirtualRemoteKey(
|
||||
?: return DomainResult.Failure(DomainError.InvalidRequest(detail = "Button not found"))
|
||||
|
||||
val targetSlot = binding.assignedSlot ?: run {
|
||||
val allBindings = (repository.getKeyBindings(remoteId) as? DomainResult.Success)?.value.orEmpty()
|
||||
val usedSlots = allBindings.mapNotNull { it.assignedSlot?.toIntOrNull() }.toSet()
|
||||
val nextSlot = (1..99).firstOrNull { it !in usedSlots } ?: 1
|
||||
val quota = when (val result = repository.slotQuota(profileId, remote.deviceName)) {
|
||||
is DomainResult.Success -> result.value
|
||||
is DomainResult.Failure -> return result
|
||||
}
|
||||
val nextSlot = quota.availableStaticSlots.firstOrNull() ?: return DomainResult.Failure(
|
||||
DomainError.InvalidRequest(detail = "槽位配额已满,无法分配静态槽位"),
|
||||
)
|
||||
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.ProviderProfileId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
||||
interface VirtualRemoteRepository {
|
||||
fun observeRemotes(
|
||||
@@ -25,6 +26,11 @@ interface VirtualRemoteRepository {
|
||||
deviceName: DeviceName,
|
||||
): Flow<DomainResult<SlotQuotaSummary>>
|
||||
|
||||
suspend fun slotQuota(
|
||||
profileId: ProviderProfileId,
|
||||
deviceName: DeviceName,
|
||||
): DomainResult<SlotQuotaSummary> = observeSlotQuota(profileId, deviceName).first()
|
||||
|
||||
suspend fun getRemote(
|
||||
profileId: ProviderProfileId,
|
||||
remoteId: VirtualRemoteId,
|
||||
|
||||
+42
@@ -116,4 +116,46 @@ class VirtualRemoteUseCaseTest {
|
||||
val fetched = (repository.getRemote(profileId, remoteId) as DomainResult.Success<VirtualRemote?>).value
|
||||
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