Skip to content

Conversation

@phodal
Copy link
Member

@phodal phodal commented Nov 30, 2025

Summary

Enhance IdeaBottomToolbar to align with mpp-ui/BottomToolbar by adding proper icons, slash command support, and ModelSelector component.

Changes

New Components

  • IdeaModelSelector.kt - Jewel-based dropdown for selecting LLM configurations
  • IdeaModelConfigDialog.kt - Dialog for configuring LLM models with:
    • Provider selector (OpenAI, Anthropic, DeepSeek, Ollama, etc.)
    • Model name selector with dropdown for known models
    • API key input with visibility toggle
    • Base URL for custom endpoints
    • Advanced settings (temperature, max tokens)

Icons Added to IdeaComposeIcons.kt

  • Send - paper plane icon for send button
  • Folder - folder icon for workspace indicator
  • AlternateEmail - @ symbol icon for agent trigger
  • ArrowDropDown - dropdown arrow
  • Check - checkmark for selection
  • Visibility / VisibilityOff - eye icons for password toggle
  • ExpandMore / ExpandLess - chevron icons for collapsible sections

IdeaBottomToolbar.kt Updates

  • Replace emoji/text with proper Jewel Icon components
  • Add onSlashClick callback for / command trigger button
  • Add ModelSelector integration with availableConfigs, currentConfigName, onConfigSelect, onConfigureClick parameters

ViewModel Updates

  • IdeaAgentViewModel.kt: Add setActiveConfig(configName) method to switch active LLM configuration

Caller Updates

  • IdeaAgentApp.kt:
    • Add model selector state management
    • Add ModelConfigDialog display
    • Add onSlashClick handler

Feature Comparison

Feature mpp-ui BottomToolbar IdeaBottomToolbar (after)
Workspace
Token info
@ button (icon)
/ button
Settings (icon)
Send (icon)
Stop (icon)
ModelSelector
ModelConfigDialog

Testing

  • ./gradlew :mpp-idea:compileKotlin passes

Pull Request opened by Augment Code with guidance from the PR author

Summary by CodeRabbit

  • New Features

    • Model selector dropdown with saved configurations and a Configure dialog for creating/editing model settings.
    • Slash-command trigger button to insert/activate slash commands.
  • UI Improvements

    • New icons (send, folder, @, dropdown, check, visibility) and replaced many text labels with icon buttons.
    • Refined layout, badges, and visual styling for toolbar, token/workspace indicators, and action buttons.

✏️ Tip: You can customize this high-level summary in your review settings.

… command support

- Add Send, Folder, AlternateEmail, ArrowDropDown icons to IdeaComposeIcons
- Replace emoji/text with proper Jewel Icon components in IdeaBottomToolbar
- Add onSlashClick callback for / command trigger button
- Update IdeaInputSection and IdeaAgentApp to support slash commands
- Align toolbar features with mpp-ui BottomToolbar (except ModelSelector)
@coderabbitai
Copy link

coderabbitai bot commented Nov 30, 2025

Walkthrough

Adds UI and wiring for model configuration and a slash-command trigger: new model selector component and config dialog, icons, toolbar/input callbacks for "/" insertion, and a ViewModel method to set the active config. Visual/icon changes replace prior text badges with Icon components.

Changes

Cohort / File(s) Summary
Icon library
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt
Added multiple new public ImageVector icons: Send, Folder, AlternateEmail, ArrowDropDown, Check, Visibility, VisibilityOff.
Toolbar & input wiring
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaInputSection.kt
Added onSlashClick: () -> Unit = {} to composables, introduced model-selector props, replaced textual action badges with Icon components, added clipping/rounded badges, wired slash button to insert "/" via text state and call the callback.
Model selector UI
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt
New IdeaModelSelector composable with dropdown of saved NamedModelConfig items, selection handling, and "Configure Model..." action.
Model config dialog & helpers
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt
New IdeaModelConfigDialog composable plus helper composables (form field, provider selector, model name selector). Handles provider, model, API key, base URL, temperature, max-tokens and emits onSave/onDismiss.
Toolwindow wiring & ViewModel
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt
IdeaAgentApp: compute/passthrough of availableConfigs/currentConfigName; show IdeaModelConfigDialog and pass callbacks to input area. IdeaAgentViewModel: added setActiveConfig(configName: String) (note: duplicate definitions present in the file).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BottomToolbar
    participant InputSection
    participant TextFieldState
    participant IdeaAgentViewModel
    participant ConfigManager
    participant ModelConfigDialog

    User->>BottomToolbar: Clicks model selector / slash / configure
    BottomToolbar->>InputSection: onSlashClick / onConfigClick / onConfigSelect
    InputSection->>TextFieldState: edit { append("/") }  %% slash path
    InputSection->>IdeaAgentViewModel: onConfigSelect(name)
    IdeaAgentViewModel->>ConfigManager: setActive(configName)
    ConfigManager-->>IdeaAgentViewModel: reload config / result
    IdeaAgentViewModel-->>InputSection: emit updated config state
    BottomToolbar->>ModelConfigDialog: onConfigureClick -> show dialog
    ModelConfigDialog->>IdeaAgentViewModel: onSave(name, config)
    IdeaAgentViewModel->>ConfigManager: persist and setActive
    ConfigManager-->>IdeaAgentViewModel: success / error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

  • Areas to double-check:
    • Duplicate setActiveConfig definitions in IdeaAgentViewModel.kt (merge/remove duplicate).
    • Correct propagation of the new model-related parameters through all composable call sites.
    • Icon path correctness and visual sizing/tint usage across toolbar items.
    • Dialog validation and save-name derivation logic in IdeaModelConfigDialog.kt.
    • Focus/Popup behavior and accessibility in IdeaModelSelector.

Possibly related PRs

Poem

🐰 A little slash hopped into place,
Models gathered, each in its space.
Icons gleam and dropdowns sing,
A curious rabbit gives it a spring—
"Configure, select, then off we race!" 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: enhancing IdeaBottomToolbar with icons, slash command support, and model selector integration.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/idea-bottom-toolbar-icons

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

- Add IdeaModelSelector for switching between LLM configurations
- Add IdeaModelConfigDialog for configuring LLM models with provider, model name, API key, base URL, and advanced settings
- Add new icons to IdeaComposeIcons: Check, Visibility, VisibilityOff, ExpandMore, ExpandLess
- Integrate ModelSelector into IdeaBottomToolbar
- Update IdeaAgentApp with model selector state management
- Add setActiveConfig method to IdeaAgentViewModel
- Remove duplicate ExpandMore/ExpandLess icons from IdeaComposeIcons
@phodal phodal changed the title feat(mpp-idea): enhance IdeaBottomToolbar with proper icons and slash command support feat(mpp-idea): enhance IdeaBottomToolbar with icons, slash command, and ModelSelector Nov 30, 2025
@phodal
Copy link
Member Author

phodal commented Nov 30, 2025

augment review

@phodal phodal merged commit fccb6db into master Nov 30, 2025
2 of 3 checks passed
Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Comment augment review to trigger a new review at any time.

},
onSlashClick = {
// Insert / at current cursor position to trigger slash commands
devInInput?.appendText("/")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pressing the slash button inserts "/" here, but IdeaInputSection also appends "/" in its onSlashClick handler (see editor/IdeaInputSection.kt:130), leading to duplicate insertion; consider handling the insertion in one place.

🤖 Was this useful? React with 👍 or 👎

horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
TextField(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

showApiKey is toggled but not applied to the API key field, so the key is always visible; consider masking/unmasking the TextField based on showApiKey.

🤖 Was this useful? React with 👍 or 👎

val name = configName.ifEmpty { "${provider.name.lowercase()}-${modelName}" }
onSave(name, config)
},
enabled = modelNameState.text.isNotEmpty() && apiKeyState.text.isNotEmpty()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Save is disabled when the API key is empty, but some providers (e.g., local/Ollama) may not require a key; consider enabling save when the selected provider doesn’t need credentials.

🤖 Was this useful? React with 👍 or 👎

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (2)

18-18: Unused import.

ModelConfig is imported but not used in this file—only NamedModelConfig is used.

-import cc.unitmesh.llm.ModelConfig

81-90: Consider adding a max height constraint to the dropdown.

The dropdown Box uses verticalScroll but has no heightIn(max = ...) constraint. With many saved configurations, the popup could extend beyond screen bounds.

 Box(
     modifier = Modifier
         .widthIn(min = 200.dp, max = 300.dp)
+        .heightIn(max = 300.dp)
         .clip(RoundedCornerShape(8.dp))
         .background(JewelTheme.globalColors.panelBackground)
         .padding(4.dp)
 ) {
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (1)

146-158: Consider using an icon for the slash button for visual consistency.

The @ trigger uses an Icon component (AlternateEmail), but the / trigger uses a Text component. For visual consistency across trigger buttons, consider using an icon or styled badge for the slash command trigger as well.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt (4)

237-267: Save handler: numeric parsing silently normalizes invalid input

temperatureState and maxTokensState are parsed with toDoubleOrNull() / toIntOrNull() and then defaulted to 0.0 and 128000 (Lines 255–256). This is safe but can be surprising if the user types an invalid value and you quietly normalize it.

Consider either:

  • Validating and preventing save when parsing fails, or
  • Clamping to a valid range (e.g., temperature 0.0–2.0) and surfacing the correction in the UI.

This would make misconfigurations easier to catch and debug.


99-117: Base URL behavior across providers may retain stale values

You:

  • Auto-fill baseUrlState with http://localhost:11434 when selecting LLMProviderType.OLLAMA and the base URL is empty (Lines 105–113).
  • Compute needsBaseUrl from a provider list to conditionally show the Base URL field (Lines 172–177).
  • Always persist baseUrl = baseUrlState.text.toString() into ModelConfig regardless of needsBaseUrl (Line 257).

This means a base URL entered (or auto-set) for one provider can remain hidden but still be passed along after switching to a provider that does not conceptually need it, depending on how ModelConfig is consumed.

Consider:

  • Clearing baseUrlState when switching to providers that don’t need a base URL, or
  • Ignoring baseUrl downstream for providers where needsBaseUrl == false.

That will avoid surprising overrides based on stale configuration.

Also applies to: 172-186


295-364: Provider dropdown implementation looks solid; consider future filtering

IdeaProviderSelector cleanly:

  • Uses an OutlinedButton with a trailing dropdown icon.
  • Renders all LLMProviderType.entries in a scrollable popup.
  • Marks the active provider with a check icon (Lines 349–355).

If the list of providers grows, you might later want to:

  • Filter out experimental/unsupported providers here, or
  • Add basic grouping or search.

For now, the implementation looks good.


370-446: Model selector UX is good; optional enhancement for long model lists

IdeaModelNameSelector gives a solid experience:

  • Free-form TextField plus dropdown trigger.
  • Popup with scrollable list and a check icon for the current model (Lines 431–437).

If availableModels can become large, consider:

  • Filtering the list based on the current modelNameState.text, or
  • Highlighting matches to the typed prefix.

This would keep the dropdown usable with many models.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0066c0e and f2fc9cb.

📒 Files selected for processing (6)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (7 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt (1 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (1 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (8 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt (1 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

Use expect/actual for platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)

Files:

  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt
🧬 Code graph analysis (2)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (1)
  • IdeaModelSelector (33-130)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt (1)
mpp-web/src/services/ConfigService.ts (1)
  • ModelConfig (6-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build (223)
  • GitHub Check: Build (241)
🔇 Additional comments (10)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaComposeIcons.kt (1)

515-755: LGTM! Well-structured icon additions.

The new icons (Send, Folder, AlternateEmail, ArrowDropDown, Check, Visibility, VisibilityOff) follow the established pattern consistently: lazy initialization, 24x24 viewport, and SolidColor(Color.Black) fill. This maintains consistency with existing icons in the file.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt (1)

433-446: LGTM! Consistent implementation.

The setActiveConfig method follows the established pattern used by saveModelConfig: coroutine launch, config operation, reload on success, and error handling via renderer.renderError. Clean and consistent.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (1)

33-130: Good structure for the model selector component.

The component properly handles empty state, selection indication, and configure action. The use of remember with appropriate keys for currentConfig and displayText ensures efficient recomposition.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (2)

28-45: Well-designed API expansion.

The new parameters (onSlashClick, model configuration props) have sensible defaults maintaining backward compatibility. The KDoc accurately reflects the updated layout.


125-131: Good integration of the model selector.

The IdeaModelSelector is properly wired with all required props passed through from the toolbar's parameters.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (4)

66-72: Good use of remember for derived state.

Using remember(configWrapper) ensures availableConfigs and currentConfigName are only recomputed when the config wrapper changes, avoiding unnecessary recalculations during recomposition.


187-201: Clean dialog integration.

The model configuration dialog is properly gated by showConfigDialog state. The save flow correctly creates a NamedModelConfig, saves it as active, and dismisses the dialog.


308-311: LGTM! Slash command trigger follows the established pattern.

The implementation mirrors the onAtClick handler by appending the trigger character to the editor input.


217-231: Well-structured parameter additions.

The new parameters have appropriate defaults and are properly forwarded to IdeaBottomToolbar. The KDoc is updated to reflect the model selector feature.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt (1)

273-289: Form field wrapper is clean and consistent

IdeaConfigFormField nicely standardizes label styling and spacing across fields, improving consistency and reducing boilerplate.

No changes needed here.

Comment on lines +146 to +170
// API Key
IdeaConfigFormField(label = "API Key") {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
TextField(
state = apiKeyState,
placeholder = { Text("Enter API key") },
modifier = Modifier.weight(1f)
)
IconButton(
onClick = { showApiKey = !showApiKey },
modifier = Modifier.size(32.dp)
) {
Icon(
imageVector = if (showApiKey) IdeaComposeIcons.VisibilityOff else IdeaComposeIcons.Visibility,
contentDescription = if (showApiKey) "Hide" else "Show",
tint = JewelTheme.globalColors.text.normal,
modifier = Modifier.size(18.dp)
)
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

org.jetbrains.jewel.ui.component.TextField password masking show hide toggle

💡 Result:

Short answer: use a boolean state to switch visualTransformation between PasswordVisualTransformation() and VisualTransformation.None and put an IconButton in the TextField's trailingIcon (or trailing) slot to toggle it. This works with Jewel's TextField because it follows Compose TextField APIs.

Example (Kotlin Compose / Jewel-style):
var text by remember { mutableStateOf("") }
var visible by remember { mutableStateOf(false) }

TextField(
    value = text,
    onValueChange = { text = it },
    label = { Text("Password") },
    visualTransformation = if (visible) VisualTransformation.None else PasswordVisualTransformation(),
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
    trailingIcon = {
        IconButton(onClick = { visible = !visible }) {
            Icon(
                imageVector = if (visible) Icons.Default.VisibilityOff else Icons.Default.Visibility,
                contentDescription = if (visible) "Hide password" else "Show password"
            )
        }
    }
)

References:

  • TextField API (trailingIcon, visualTransformation). [1]
  • Android guide: show/hide password toggle (example & UX). [2]
  • PasswordVisualTransformation docs. [3]

Sources:
[1] kotlinlang.org Compose TextField docs.
[2] developer.android.com "Show or hide password based on a user toggle".
[3] developer.android.com PasswordVisualTransformation API.


🏁 Script executed:

cat -n mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt | head -200

Repository: phodal/auto-dev-sketch

Length of output: 10361


🏁 Script executed:

head -33 mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt | grep -E "import|PasswordVisualTransformation"

Repository: phodal/auto-dev-sketch

Length of output: 1428


🏁 Script executed:

rg "PasswordVisualTransformation|visualTransformation" --type kt

Repository: phodal/auto-dev-sketch

Length of output: 92


🏁 Script executed:

rg "TextField.*password|TextField.*secret|password.*TextField|secret.*TextField" --type kt -i -A 3

Repository: phodal/auto-dev-sketch

Length of output: 92


🏁 Script executed:

rg "PasswordVisualTransformation|visualTransformation" -A 3 -B 1

Repository: phodal/auto-dev-sketch

Length of output: 4902


🏁 Script executed:

rg "showPassword|hidePassword|maskPassword" -A 3 -B 1

Repository: phodal/auto-dev-sketch

Length of output: 48


🏁 Script executed:

find . -name "*.kt" -type f | xargs grep -l "TextField" | head -5

Repository: phodal/auto-dev-sketch

Length of output: 496


🏁 Script executed:

sed -n '1,50p' mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelConfigDialog.kt | head -40

Repository: phodal/auto-dev-sketch

Length of output: 1657


🏁 Script executed:

sed -n '100,150p' mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelConfigDialog.kt

Repository: phodal/auto-dev-sketch

Length of output: 2536


🏁 Script executed:

grep -n "API Key\|API key\|apiKey" mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelConfigDialog.kt -A 15 | head -35

Repository: phodal/auto-dev-sketch

Length of output: 2129


Wire showApiKey toggle to apply password masking via visualTransformation

The showApiKey boolean toggles the icon between Visibility and VisibilityOff (lines 159–167), but the TextField always renders as plain text. The toggle has no effect on actual field visibility/masking.

Add the missing visualTransformation parameter to the TextField:

visualTransformation = if (showApiKey) VisualTransformation.None else PasswordVisualTransformation(),

Also add the missing imports:

import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation

A correct implementation of this pattern already exists in mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelConfigDialog.kt (line 251).

🤖 Prompt for AI Agents
In
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelConfigDialog.kt
around lines 146 to 170, the showApiKey toggle only changes the icon but does
not mask/unmask the TextField; wire the toggle into the TextField by adding
visualTransformation = if (showApiKey) VisualTransformation.None else
PasswordVisualTransformation(), and add the required imports
androidx.compose.ui.text.input.PasswordVisualTransformation and
androidx.compose.ui.text.input.VisualTransformation so the field actually
switches between masked and plain text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants