feat(profiles): add local on-device profile hiding and filtering

This commit is contained in:
M57 committed 2026-08-30 20:51:06 +03:00
1 parent 5c8ab7ed6c
commit cdcecb9734
11 files changed
+240 -10

No files matched your search

@@ -1,5 +1,6 @@
package com.m57.hermescontrol.ui.bots
import com.m57.hermescontrol.data.local.AuthManager
import com.m57.hermescontrol.data.model.ActiveProfileResponse
import com.m57.hermescontrol.data.model.BotAvatarMeta
import com.m57.hermescontrol.data.model.BotRosterMeta
@@ -45,6 +46,8 @@ class BotsViewModelTest {
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
mockkObject(AuthManager)
every { AuthManager.getHiddenProfiles() } returns emptyList()
mockkObject(ApiClient)
mockApi = mockk(relaxed = true)
every { ApiClient.hermesApi } returns mockApi
@@ -57,6 +60,7 @@ class BotsViewModelTest {
@After
fun tearDown() {
unmockkObject(AuthManager)
unmockkObject(ApiClient)
unmockkObject(HermesWsClient)
Dispatchers.resetMain()
@@ -56,6 +56,7 @@ class ProfilesViewModelTest {
private var storedPinnedModels: MutableList<PinnedModel> = mutableListOf()
private var storedSelectedProfile: String? = null
private var storedProfileToken: String? = null
private var storedHiddenProfiles: MutableList<String> = mutableListOf()
private fun stubProfilesLoad() {
coEvery { mockApi.getProfiles() } returns
@@ -88,6 +89,15 @@ class ProfilesViewModelTest {
every { AuthManager.setProfileToken(any(), any()) } answers {
storedProfileToken = secondArg<String?>()
}
every { AuthManager.getHiddenProfiles() } answers { storedHiddenProfiles.toList() }
every { AuthManager.hideProfile(any()) } answers {
val name = firstArg<String>()
if (!storedHiddenProfiles.contains(name)) storedHiddenProfiles.add(name)
}
every { AuthManager.unhideProfile(any()) } answers {
val name = firstArg<String>()
storedHiddenProfiles.remove(name)
}
mockkObject(HermesWsClient)
every { HermesWsClient.disconnect() } returns Unit
@@ -345,4 +355,39 @@ class ProfilesViewModelTest {
assertTrue(vm.uiState.value.toastMessage!!.contains("Failed to clone profile"))
assertFalse(vm.uiState.value.isLoading)
}
@Test
fun `hideProfile and unhideProfile update local hidden state and display filtering`() {
coEvery { mockApi.getProfiles() } returns
Response.success(
ProfilesResponse(
listOf(
ProfileInfo(name = "default", is_default = true),
ProfileInfo(name = "secret-bot"),
),
),
)
val vm = createViewModel()
vm.loadProfiles()
testDispatcher.scheduler.advanceUntilIdle()
assertEquals(2, vm.uiState.value.displayProfiles.size)
assertFalse(vm.uiState.value.hasHiddenProfiles)
vm.hideProfile("secret-bot")
assertEquals(listOf("secret-bot"), storedHiddenProfiles)
assertTrue(vm.uiState.value.hasHiddenProfiles)
assertEquals(listOf("default"), vm.uiState.value.displayProfiles.map { it.name })
// Toggle show hidden
vm.toggleShowHidden()
assertTrue(vm.uiState.value.showHidden)
assertEquals(listOf("default", "secret-bot"), vm.uiState.value.displayProfiles.map { it.name })
// Unhide
vm.unhideProfile("secret-bot")
assertTrue(storedHiddenProfiles.isEmpty())
assertFalse(vm.uiState.value.hasHiddenProfiles)
}
}