diff --git a/app/src/androidTest/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheetInstrumentedTest.kt b/app/src/androidTest/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheetInstrumentedTest.kt index 85fb0d129..111f1c11c 100644 --- a/app/src/androidTest/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheetInstrumentedTest.kt +++ b/app/src/androidTest/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheetInstrumentedTest.kt @@ -9,13 +9,18 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasScrollAction import androidx.compose.ui.test.hasScrollToIndexAction import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onAllNodesWithContentDescription +import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollToIndex import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipe import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.yugahashimoto.andcode.R import com.yugahashimoto.andcode.core.api.OpenCodeModel import com.yugahashimoto.andcode.core.api.OpenCodeProvider +import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -38,6 +43,8 @@ class ModelAndRuntimePickerSheetInstrumentedTest { selectedProviderId = testProvider.id, selectedModelId = null, onSelectModel = { _, _ -> }, + favoriteModelKeys = emptySet(), + onToggleFavorite = { _, _ -> }, onDismiss = { dismissed = true }, ) } @@ -53,6 +60,35 @@ class ModelAndRuntimePickerSheetInstrumentedTest { composeRule.runOnIdle { assertFalse(dismissed) } } + @Test + fun tappingStarTogglesFavoriteWithoutSelectingModel() { + val toggled = mutableListOf>() + val selected = mutableListOf>() + + composeRule.setContent { + ModelAndRuntimePickerSheet( + runtimeTargets = emptyList(), + selectedRuntimeId = null, + onSelectRuntime = {}, + providers = listOf(testProvider), + selectedProviderId = testProvider.id, + selectedModelId = null, + onSelectModel = { providerId, modelId -> selected += providerId to modelId }, + favoriteModelKeys = emptySet(), + onToggleFavorite = { providerId, modelId -> toggled += providerId to modelId }, + onDismiss = {}, + ) + } + + val star = composeRule.activity.getString(R.string.cd_favorite) + composeRule.onAllNodesWithContentDescription(star)[0].performClick() + + composeRule.runOnIdle { + assertEquals(1, toggled.size) + assertTrue(selected.isEmpty()) + } + } + private companion object { val testProvider = OpenCodeProvider( diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheet.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheet.kt index 72772d6f2..75cb069be 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheet.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/chat/ModelAndRuntimePickerSheet.kt @@ -74,10 +74,12 @@ fun ModelAndRuntimePickerSheet( selectedProviderId: String?, selectedModelId: String?, onSelectModel: (String, String) -> Unit, - favoriteModelKeys: Set = emptySet(), + // Required, with no default: every row draws a star. A caller that forgot these used to get an + // empty set and a no-op, so its stars rendered but did nothing when tapped. + favoriteModelKeys: Set, + onToggleFavorite: (String, String) -> Unit, recentModelKeys: List = emptyList(), hiddenModelKeys: Set = emptySet(), - onToggleFavorite: (String, String) -> Unit = { _, _ -> }, showLocalSuffix: Boolean = true, onConnectProvider: (() -> Unit)? = null, onDismiss: () -> Unit, diff --git a/app/src/main/java/com/yugahashimoto/andcode/feature/settings/VoiceSettingsScreen.kt b/app/src/main/java/com/yugahashimoto/andcode/feature/settings/VoiceSettingsScreen.kt index 66d6f50e7..1f54e94ca 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/feature/settings/VoiceSettingsScreen.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/feature/settings/VoiceSettingsScreen.kt @@ -105,6 +105,7 @@ fun VoiceSettingsScreen( workspaces: List = emptyList(), assistantProviderId: String? = null, assistantModelId: String? = null, + favoriteModelKeys: Set = emptySet(), assistantWorkspacePath: String = "", onTtsChange: (Boolean) -> Unit, onTtsProviderChange: (String) -> Unit = {}, @@ -129,6 +130,7 @@ fun VoiceSettingsScreen( onWakeWordModelRemove: () -> Unit = {}, onAssistantRuntimeChange: (String) -> Unit = {}, onAssistantModelChange: (String, String) -> Unit = { _, _ -> }, + onToggleFavoriteModel: (String, String) -> Unit = { _, _ -> }, onAssistantWorkspaceChange: (String) -> Unit = {}, onBack: () -> Unit, ) { @@ -302,9 +304,11 @@ fun VoiceSettingsScreen( assistantRuntimeId = assistantRuntimeId, assistantProviderId = assistantProviderId, assistantModelId = assistantModelId, + favoriteModelKeys = favoriteModelKeys, assistantWorkspacePath = assistantWorkspacePath, onRuntimeChange = onAssistantRuntimeChange, onModelChange = onAssistantModelChange, + onToggleFavoriteModel = onToggleFavoriteModel, onWorkspaceChange = onAssistantWorkspaceChange, ) } @@ -587,9 +591,11 @@ private fun AssistantTargetSection( assistantRuntimeId: String?, assistantProviderId: String?, assistantModelId: String?, + favoriteModelKeys: Set, assistantWorkspacePath: String, onRuntimeChange: (String) -> Unit, onModelChange: (String, String) -> Unit, + onToggleFavoriteModel: (String, String) -> Unit, onWorkspaceChange: (String) -> Unit, ) { var showPicker by remember { mutableStateOf(false) } @@ -648,6 +654,8 @@ private fun AssistantTargetSection( providers = targetProviders, selectedProviderId = assistantProviderId, selectedModelId = assistantModelId, + favoriteModelKeys = favoriteModelKeys, + onToggleFavorite = onToggleFavoriteModel, showLocalSuffix = false, onSelectModel = { providerId, modelId -> onModelChange(providerId, modelId) diff --git a/app/src/main/java/com/yugahashimoto/andcode/ui/navigation/SettingsNavGraph.kt b/app/src/main/java/com/yugahashimoto/andcode/ui/navigation/SettingsNavGraph.kt index f43ddcb97..a09d40019 100644 --- a/app/src/main/java/com/yugahashimoto/andcode/ui/navigation/SettingsNavGraph.kt +++ b/app/src/main/java/com/yugahashimoto/andcode/ui/navigation/SettingsNavGraph.kt @@ -268,6 +268,8 @@ fun NavGraphBuilder.settingsNavGraph( onAssistantModelChange = { providerId, modelId -> settingsViewModel.setAssistantModel(providerId, modelId) }, + favoriteModelKeys = settingsState.favoriteModelKeys, + onToggleFavoriteModel = settingsViewModel::toggleFavoriteModel, onAssistantWorkspaceChange = { path -> settingsViewModel.setAssistantWorkspacePath(path) },