* refactor(ui): extract SkillsStep to components package
Move the 252-LOC SkillsStep composable out of ProfilesScreen.kt into
ui/profiles/components/SkillsStep.kt. Body is verbatim (behavior-preserving);
only package + imports changed. Parent now imports and calls it directly.
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
Note: sibling screens resolve Modifier.weight() without an explicit import;
matching that convention (no spurious weight import) to avoid the
internal RowColumnParentData.weight shadowing error.
* refactor(ui): extract ProfileBuilderView cluster to components package
Move the Profile Builder wizard (ProfileBuilderView + validateProfileName +
IdentityStep/ModelStep/McpStep/AddMcpDialog/ReviewStep) out of ProfilesScreen.kt
into ui/profiles/components/ProfileBuilderView.kt. Body is verbatim
(behavior-preserving); only package + imports changed.
Notable wiring required:
- validateProfileName kept as internal fun: it is also used by the parent's
clone dialog, so both the screen and the builder share it via import.
- ProfilesUiState/ProfilesViewModel imported from the ui.profiles package.
- SkillsStep call resolves to the already-extracted sibling file (same package).
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
* refactor(ui): extract MoaConfigDialog cluster to components package
Move the Mixture-of-Agents config dialog (MoaConfigDialog + MoaConfigEditor +
MoaSlotPicker + MoaPickerTarget sealed class) out of ModelScreen.kt into
ui/model/components/MoaConfigDialog.kt. Body is verbatim (behavior-preserving);
only package + imports + entry visibility changed.
- Entry MoaConfigDialog is internal (called by ModelScreen root); the editor,
slot picker, and sealed class stay private to the new file.
- The @Composable annotation preceding the declaration is moved with the
cluster (earlier attempt left it orphaned, causing a duplicate-annotation
compile error at the next declaration).
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
* refactor(ui): extract PlatformCard + TelegramOnboardingDialog clusters
Move two self-contained clusters out of ChannelsScreen.kt:
- PlatformCard.kt: StateStyle (private data class) + platformStateStyle +
StateBadge + PlatformCard. Entry PlatformCard is internal (called by
ChannelsScreen root); StateStyle/StateBadge/platformStateStyle stay private.
- TelegramOnboardingDialog.kt: TelegramOnboardingDialog. Entry internal.
Wiring required:
- ConfigureForm kept in ChannelsScreen as internal (shared by PlatformCard
and the screen root) and imported into PlatformCard.kt.
- ChannelsUiState/OnboardingPhase imported from the ui.channels package.
- formatTimestamp left in the screen (used by ConfigureForm).
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
* refactor(ui): extract SkillsScreen sub-composables to components package
Split the 914-line SkillsScreen.kt into the screen root plus 4 cohesive
component files under ui/skills/components/:
- SourceBadge.kt: shared SourceBadge (internal, used by both tabs)
- InstalledSkillsTab.kt: InstalledSkillsView + SkillCard + SkillPreviewDialog
- HubSkillsTab.kt: HubBrowseView + HubSkillCard
- SkillEditorDialog.kt: SkillEditorDialog
Wiring required:
- CATEGORY_ALL promoted private -> internal in SkillsScreen (shared by the
screen root and InstalledSkillsView) and imported where needed.
- SkillFilter / SkillsUiState imported from the ui.skills package.
- HubBrowseView now reads isHubSearching/hubResults/hubSearchError off its
SkillsUiState param (fields, not locals) - no behavior change.
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
* refactor(ui): extract SettingsScreen + SystemScreen sub-composables
SettingsScreen.kt (1238 -> ~340): move self-contained sections into
ui/settings/components/ - ConnectionSection (+TestResultCard/SaveIndicator/
TestConnectionButton), BehaviorSection, AppearanceSection (+ChatSection/
NavBarSection), AboutSection, ProfileEditorDialog (+DeleteProfileConfirmDialog).
Shared leaves SectionCard/InfoRow kept in the screen as internal and imported
by the extracted files.
SystemScreen.kt (1755 -> 1619): move CredentialEntryRow + HookCard into
ui/system/components/ (both internal). formatBytes/formatDuration helpers stay
in the screen (used by the root and remaining content).
Verified: ktlintCheck PASS, compileDebugKotlin PASS (local SDK).
* fix(#485): use LocalHermesStatusColors for PlatformCard state colors
Map platform connection-status badges to semantic LocalHermesStatusColors
slots (success/warning/error) + add neutral slot for not_configured/disabled.
Removes hardcoded hex (Color(0xFF...)) and MaterialTheme.colorScheme usage
flagged by Sourcery; neutral defaults to StatusGrey so existing theme
providers are untouched.