From 04f8d61b9286f5c9bffb3e37599758ec503b8be3 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 14:28:13 +0530 Subject: [PATCH 01/13] feat: fix scrims --- .../mockzilla/desktop/ui/DesktopAppRoot.kt | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt index 7f1953d4b..6dea0447b 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt @@ -10,6 +10,8 @@ import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.foundation.background import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -18,7 +20,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -194,6 +195,28 @@ fun DesktopApp( } } +@Composable +private fun ScrimOverlay(visible: Boolean, onDismiss: () -> Unit) { + Column(modifier = Modifier.fillMaxSize()) { + AnimatedVisibility( + visible = visible, + enter = fadeIn(animationSpec = tween(animationDuration)), + exit = fadeOut(animationSpec = tween(animationDuration)), + ) { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = scrimAlpha)) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + onClick = onDismiss, + ) + ) + } + } +} + @Composable private fun DeviceContent( device: Device, @@ -353,16 +376,8 @@ private fun ConnectedDeviceLayout( ) } - // Scrim behind preset overlay — Column provides ColumnScope for AnimatedVisibility - Column(modifier = Modifier.fillMaxSize()) { - AnimatedVisibility( - visible = presetVisible, - enter = fadeIn(animationSpec = tween(animationDuration)), - exit = fadeOut(animationSpec = tween(animationDuration)), - ) { - Box(modifier = Modifier.fillMaxSize().background(Color.Black.copy(alpha = scrimAlpha))) - } - } + // Scrim behind preset overlay + ScrimOverlay(visible = presetVisible, onDismiss = { state = state.copy(presetOpen = false) }) // Create/Edit Preset overlay — Box provides alignment; Column provides ColumnScope Box(modifier = Modifier.fillMaxHeight().align(Alignment.CenterEnd)) { @@ -403,6 +418,9 @@ private fun ConnectedDeviceLayout( } } + // Scrim behind global controls overlay + ScrimOverlay(visible = state.globalControlsOpen, onDismiss = { state = state.copy(globalControlsOpen = false) }) + // Global Controls overlay — Box provides alignment; Column provides ColumnScope Box(modifier = Modifier.fillMaxHeight().align(Alignment.CenterEnd)) { Column(modifier = Modifier.fillMaxHeight()) { @@ -422,15 +440,8 @@ private fun ConnectedDeviceLayout( Surface( modifier = Modifier .fillMaxHeight() - .width(state.globalControlsWidthDp.dp) - .shadow(8.dp) - .border( - 1.dp, - MaterialTheme.colorScheme.outline, - RoundedCornerShape(topStart = 8.dp), - ), + .width(state.globalControlsWidthDp.dp), color = MaterialTheme.colorScheme.surface, - shape = RoundedCornerShape(topStart = 8.dp), ) { GlobalControlsWidget( device = connectedState.activeDevice.device, From 07dbc3278e4c42e8c1a46fd60494ec76ec783dd2 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 15:28:24 +0530 Subject: [PATCH 02/13] feat: fix various touch targets --- .../desktop/ui/devicetabs/DeviceTabsWidget.kt | 10 ++--- .../common/components/ForceFailureBanner.kt | 32 ++++----------- .../ui/ui/common/components/PresetCard.kt | 3 ++ .../common/components/ResponseLatencyCard.kt | 34 ++++++--------- .../common/components/buttons/BaseButton.kt | 6 +-- .../components/buttons/DensityButtons.kt | 28 +++++++++---- .../editor/FindableEditorTextField.kt | 9 ++-- .../CreateEditPresetWidget.kt | 41 ++++++------------- .../details/EndpointDetailsWidget.kt | 32 +++++---------- .../endpoints/endpoints/EndpointsWidget.kt | 37 ++++------------- .../globalcontrols/GlobalControlsWidget.kt | 3 +- .../apadmi/mockzilla/ui/utils/TouchTarget.kt | 30 ++++++++++++++ 12 files changed, 118 insertions(+), 147 deletions(-) create mode 100644 mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt index ed487c101..7016e58b9 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt @@ -66,6 +66,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.theme.LocalMonoFontFamily import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.success +import com.apadmi.mockzilla.ui.utils.iconButtonSize import kotlin.Float @@ -362,12 +363,9 @@ private fun DeviceTab( ) } - Box( - modifier = Modifier - .size(12.dp) - .clip(RoundedCornerShape(4.dp)) - .clickable(onClick = onClose), - contentAlignment = Alignment.Center, + IconButton( + onClick = onClose, + modifier = Modifier.iconButtonSize(), ) { Icon( imageVector = Icons.Filled.Close, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt index e611404dc..489809017 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp import com.apadmi.mockzilla.ui.i18n.LocalStrings import com.apadmi.mockzilla.ui.i18n.Strings +import com.apadmi.mockzilla.ui.ui.common.assets.CircleCheck import com.apadmi.mockzilla.ui.ui.common.assets.LightningBolt import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonSize @@ -144,29 +145,14 @@ internal fun ForceFailureBanner( if (state != ForceFailureBannerState.Normal) { val successColor = colorScheme.success.primary - val resumeShape = RoundedCornerShape(resumeButtonCornerRadius.dp) - Row( - modifier = Modifier - .clip(resumeShape) - .border(1.dp, successColor, resumeShape) - .clickable { onRestoreApiClicked() } - .padding(horizontal = 12.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(6.dp), - ) { - Icon( - imageVector = Icons.Default.Check, - contentDescription = null, - tint = successColor, - modifier = Modifier.size(14.dp), - ) - Text( - text = strings.widgets.globalControls.restoreButtonLabel, - style = MaterialTheme.typography.labelSmall, - color = successColor, - fontWeight = FontWeight.Medium, - ) - } + BaseButton( + label = strings.widgets.globalControls.restoreButtonLabel, + leadingIcon = Icons.CircleCheck, + contentColor = successColor, + size = ButtonSize.Sm, + variant = ButtonVariant.Outline, + onClick = onRestoreApiClicked, + ) } } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt index e2ff87297..2b3fa1bd3 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt @@ -74,6 +74,7 @@ import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.RowDensity import com.apadmi.mockzilla.ui.ui.common.widgets.monitorlogs.details.minifyJson import com.apadmi.mockzilla.ui.ui.common.widgets.monitorlogs.details.prettyPrintJson import com.apadmi.mockzilla.ui.ui.common.widgets.monitorlogs.details.typeFormat +import com.apadmi.mockzilla.ui.utils.minimumTouchTarget import io.ktor.http.HttpStatusCode @@ -230,6 +231,7 @@ internal fun PresetCard( ) { Box( modifier = Modifier + .minimumTouchTarget() .fillMaxHeight() .clip(RoundedCornerShape(6.dp)) .clickable { onEdit() } @@ -274,6 +276,7 @@ internal fun PresetCard( PresetCardVariant.Selectable -> Box( modifier = Modifier + .minimumTouchTarget() .clip(RoundedCornerShape(6.dp)) .clickable { onClicked(preset) } ) { diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt index d8a053beb..9300ab3dc 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt @@ -48,11 +48,15 @@ import androidx.compose.ui.unit.sp import com.apadmi.mockzilla.ui.engine.maxLatencySliderMs import com.apadmi.mockzilla.ui.i18n.LocalStrings import com.apadmi.mockzilla.ui.i18n.Strings +import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton +import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonSize +import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonVariant import com.apadmi.mockzilla.ui.ui.common.theme.LocalForceDarkMode import com.apadmi.mockzilla.ui.ui.common.theme.darkSurface import com.apadmi.mockzilla.ui.ui.common.theme.mockzillaMonoFontFamily import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.warning +import com.apadmi.mockzilla.ui.utils.minimumTouchTarget import kotlin.math.max import kotlin.math.min @@ -199,28 +203,13 @@ internal fun ResponseLatencyCard( ) ) - Row( - modifier = Modifier - .clip(RoundedCornerShape(4.dp)) - .clickable(onClick = onReset) - .padding(4.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp) - ) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = null, - modifier = Modifier.size(14.dp), - tint = colorScheme.onSurfaceVariant - ) - Text( - text = strings.widgets.latency.clear, - style = MaterialTheme.typography.labelMedium.copy( - color = colorScheme.onSurfaceVariant, - fontWeight = FontWeight.Medium - ) - ) - } + BaseButton( + variant = ButtonVariant.Ghost, + size = ButtonSize.Sm, + leadingIcon = Icons.Default.Close, + label = strings.widgets.latency.clear, + onClick = onReset, + ) } } @@ -398,6 +387,7 @@ internal fun ResponseLatencyCard( Box( modifier = Modifier + .minimumTouchTarget() .clip(componentShape) .border( width = 1.dp, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/BaseButton.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/BaseButton.kt index a3ffc369e..aba97e772 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/BaseButton.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/BaseButton.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -34,6 +33,7 @@ import androidx.compose.ui.unit.dp import com.apadmi.mockzilla.ui.ui.common.assets.LightningBolt import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface +import com.apadmi.mockzilla.ui.utils.minimumTouchTarget enum class ButtonVariant { Danger, Ghost, Outline, Soft, Solid @@ -81,7 +81,7 @@ fun BaseButton( val borderTarget = when (variant) { ButtonVariant.Ghost -> Color.Transparent - ButtonVariant.Outline -> if (isHovered && enabled) colorScheme.outlineVariant else colorScheme.outline + ButtonVariant.Outline -> contentColor ?: if (isHovered && enabled) colorScheme.outlineVariant else colorScheme.outline ButtonVariant.Solid -> Color.Transparent ButtonVariant.Soft -> colorScheme.outline ButtonVariant.Danger -> colorScheme.error.copy(alpha = 0.3f) @@ -97,7 +97,7 @@ fun BaseButton( val iconSize = if (size == ButtonSize.Lg) 18.dp else 14.dp Button( - modifier = modifier.defaultMinSize(minHeight = 1.dp).alpha(if (enabled) 1f else 0.5f), + modifier = modifier.minimumTouchTarget().alpha(if (enabled) 1f else 0.5f), onClick = onClick, enabled = enabled, shape = RoundedCornerShape(6.dp), diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/DensityButtons.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/DensityButtons.kt index 88f61f8a5..0c3f197da 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/DensityButtons.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/buttons/DensityButtons.kt @@ -3,16 +3,20 @@ package com.apadmi.mockzilla.ui.ui.common.components.buttons import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp + import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.RowDensity +import com.apadmi.mockzilla.ui.utils.minimumTouchTarget private const val UNSELECTED_BORDER_ALPHA = 0.2f @@ -40,14 +44,20 @@ private fun RowDensityButton( val cs = MaterialTheme.colorScheme val borderColor = if (isSelected) cs.onSurface else cs.onSurface.copy(alpha = UNSELECTED_BORDER_ALPHA) - Text( - text = label, + Box( + contentAlignment = Alignment.Center, modifier = Modifier - .border(width = 1.dp, color = borderColor, shape = RoundedCornerShape(4.dp)) - .clickable(onClick = onClick) - .padding(horizontal = 8.dp, vertical = 4.dp), - style = MaterialTheme.typography.labelSmall, - fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Normal, - color = if (isSelected) cs.onSurface else cs.onSurfaceVariant, - ) + .minimumTouchTarget() + .clickable(onClick = onClick), + ) { + Text( + text = label, + modifier = Modifier + .border(width = 1.dp, color = borderColor, shape = RoundedCornerShape(4.dp)) + .padding(horizontal = 8.dp, vertical = 4.dp), + style = MaterialTheme.typography.labelSmall, + fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Normal, + color = if (isSelected) cs.onSurface else cs.onSurfaceVariant, + ) + } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt index aa6ed0aeb..2dc9f7d9a 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt @@ -59,6 +59,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.CustomTextField import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonSize import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonVariant +import com.apadmi.mockzilla.ui.utils.iconButtonSize @Composable internal fun FindableEditorTextField( @@ -246,7 +247,7 @@ private fun FindReplaceBar( ) { IconButton( onClick = onToggleReplaceMode, - modifier = Modifier.size(24.dp), + modifier = Modifier.iconButtonSize(24.dp), ) { Icon( imageVector = Icons.Default.KeyboardArrowRight, @@ -299,7 +300,7 @@ private fun FindReplaceBar( }, ) - IconButton(onClick = onPrev, modifier = Modifier.size(28.dp)) { + IconButton(onClick = onPrev, modifier = Modifier.iconButtonSize(28.dp)) { Icon( imageVector = Icons.Default.KeyboardArrowUp, contentDescription = strings.previousMatchDescription, @@ -307,7 +308,7 @@ private fun FindReplaceBar( tint = colorScheme.onSurfaceVariant, ) } - IconButton(onClick = onNext, modifier = Modifier.size(28.dp)) { + IconButton(onClick = onNext, modifier = Modifier.iconButtonSize(28.dp)) { Icon( imageVector = Icons.Default.KeyboardArrowDown, contentDescription = strings.nextMatchDescription, @@ -321,7 +322,7 @@ private fun FindReplaceBar( .width(1.dp) .background(colorScheme.outlineVariant), ) - IconButton(onClick = onClose, modifier = Modifier.size(28.dp)) { + IconButton(onClick = onClose, modifier = Modifier.iconButtonSize(28.dp)) { Icon( imageVector = Icons.Default.Close, contentDescription = strings.closeFindBarDescription, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt index 5c92dd5e9..5dca929a6 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt @@ -90,6 +90,8 @@ import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.createeditpreset.CreateEditPresetViewModel.* import com.apadmi.mockzilla.ui.utils.blockedPointerIcon +import com.apadmi.mockzilla.ui.utils.iconButtonSize +import com.apadmi.mockzilla.ui.utils.minimumTouchTarget import io.ktor.http.HttpStatusCode import org.koin.core.parameter.parametersOf @@ -191,39 +193,21 @@ private fun ColumnScope.HeadersSection( onValueChange = { localValue = it }, ) val canAdd = localKey.isNotEmpty() && localValue.isNotEmpty() - Box( + IconButton( + onClick = { + onAddHeader(localKey, localValue) + localKey = "" + localValue = "" + }, + enabled = canAdd, modifier = Modifier - .size(28.dp) - .background(MaterialTheme.colorScheme.surfaceContainer, RoundedCornerShape(6.dp)) - .border( - width = 1.dp, - color = if (canAdd) { - MaterialTheme.colorScheme.outline - } else { - MaterialTheme.colorScheme.outline.copy(alpha = 0.8f) - }, - shape = RoundedCornerShape(6.dp), - ) - .clickable( - enabled = canAdd, - onClick = { - onAddHeader(localKey, localValue) - localKey = "" - localValue = "" - } - ) + .iconButtonSize(28.dp) .pointerHoverIcon(if (canAdd) PointerIcon.Hand else blockedPointerIcon), - contentAlignment = Alignment.Center, ) { Icon( imageVector = Icons.Default.Add, contentDescription = strings.addHeaderButton, - tint = if (canAdd) { - MaterialTheme.colorScheme.onSurfaceVariant - } else { - MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f) - }, - modifier = Modifier.size(14.dp) + modifier = Modifier.size(14.dp), ) } } @@ -536,7 +520,7 @@ private fun BodySection( IconButton( onClick = onToggleExpand, - modifier = Modifier.size(40.dp), + modifier = Modifier.iconButtonSize(40.dp), ) { Icon( imageVector = if (isExpanded) Icons.Default.FullscreenExit else Icons.Default.Fullscreen, @@ -758,6 +742,7 @@ private fun BodyTypeToggle( val isHovered by interactionSource.collectIsHoveredAsState() Box( modifier = Modifier + .minimumTouchTarget() .clip(chipShape) .background( color = when { diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt index 3322482a8..6b3ef3756 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt @@ -89,6 +89,7 @@ import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.details.EndpointDetai import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.details.components.PresetsContainer import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.EndpointProperties import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.RowDensity +import com.apadmi.mockzilla.ui.utils.iconButtonSize import org.koin.core.parameter.parametersOf @@ -231,27 +232,14 @@ private fun ColumnScope.PopulatedState( ) } Spacer(Modifier.width(8.dp)) - val customLabel = strings.endpointDetails.presets.typeDescriptions.other - Row( - modifier = Modifier - .clip(RoundedCornerShape(6.dp)) - .clickable(enabled = state.config.shouldFail != true, onClick = onCreatePreset) - .padding(horizontal = 8.dp, vertical = 2.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - Icon( - imageVector = Icons.Default.Add, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.size(12.dp), - ) - Text( - text = customLabel, - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurface, - ) - } + BaseButton( + variant = ButtonVariant.Ghost, + size = ButtonSize.Sm, + leadingIcon = Icons.Default.Add, + label = strings.endpointDetails.presets.typeDescriptions.other, + enabled = state.config.shouldFail != true, + onClick = onCreatePreset, + ) } ) { Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { @@ -498,7 +486,7 @@ private fun ActivePresetBanner( color = colorScheme.onSurfaceVariant, ) } - IconButton(onClick = onClear, modifier = Modifier.size(24.dp)) { + IconButton(onClick = onClear, modifier = Modifier.iconButtonSize(24.dp)) { Icon( imageVector = Icons.Default.Close, contentDescription = null, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt index 92f58f1b0..02a7a04ed 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt @@ -1,7 +1,6 @@ package com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.hoverable @@ -25,7 +24,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight import androidx.compose.material.icons.filled.Search @@ -43,7 +41,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color @@ -63,6 +60,8 @@ import com.apadmi.mockzilla.ui.ui.common.components.EmptyState import com.apadmi.mockzilla.ui.ui.common.components.PlatformVerticalScrollbar import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.components.StatusChip +import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton +import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonVariant import com.apadmi.mockzilla.ui.ui.common.components.buttons.RowDensityControls import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.warning @@ -173,38 +172,18 @@ private fun EndpointsList( } } -@Suppress("MAGIC_NUMBER") @Composable private fun GlobalControlsButton( isOpen: Boolean, strings: Strings = LocalStrings.current, onClick: () -> Unit ) { - val colorScheme = MaterialTheme.colorScheme - val shape = RoundedCornerShape(8.dp) - - Row( - modifier = Modifier - .clip(shape) - .background(if (isOpen) colorScheme.primary else colorScheme.surface) - .border(1.dp, if (isOpen) colorScheme.primary else colorScheme.outline, shape) - .clickable(onClick = onClick) - .padding(horizontal = 12.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - Icon( - imageVector = Icons.Filled.Tune, - contentDescription = null, - tint = if (isOpen) colorScheme.onPrimary else colorScheme.onSurfaceVariant, - modifier = Modifier.size(16.dp), - ) - Text( - text = strings.widgets.globalControls.title, - style = MaterialTheme.typography.labelMedium, - color = if (isOpen) colorScheme.onPrimary else colorScheme.onSurface, - ) - } + BaseButton( + variant = if (isOpen) ButtonVariant.Solid else ButtonVariant.Outline, + leadingIcon = Icons.Filled.Tune, + label = strings.widgets.globalControls.title, + onClick = onClick, + ) } @Composable diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt index badbc06dc..2b4cbde55 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt @@ -54,6 +54,7 @@ import com.apadmi.mockzilla.ui.ui.common.theme.warning import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.EndpointProperties import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.EndpointsViewModel import com.apadmi.mockzilla.ui.ui.common.widgets.globalcontrols.GlobalControlsViewModel.State +import com.apadmi.mockzilla.ui.utils.iconButtonSize import org.koin.core.parameter.parametersOf @@ -167,7 +168,7 @@ internal fun GlobalControlsWidgetIdleContent( ) IconButton( - modifier = Modifier.size(24.dp), + modifier = Modifier.iconButtonSize(24.dp), onClick = onClose ) { Icon( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt new file mode 100644 index 000000000..cb0da0352 --- /dev/null +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt @@ -0,0 +1,30 @@ +package com.apadmi.mockzilla.ui.utils + +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.size +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +private val touchTargetSize: Dp + get() = when (Platform.current) { + Platform.Android, Platform.Ios -> 44.dp + else -> 24.dp + } + +/** Enforces WCAG AA minimum touch target (44dp mobile, 24dp desktop). */ +fun Modifier.minimumTouchTarget(): Modifier = defaultMinSize( + minWidth = touchTargetSize, + minHeight = touchTargetSize, +) + +/** + * Sets an exact size for a compact IconButton: [desktopSize] on desktop/JS, + * 44dp on Android/iOS so the tap target meets WCAG AA. + */ +fun Modifier.iconButtonSize(desktopSize: Dp = 24.dp): Modifier = size( + when (Platform.current) { + Platform.Android, Platform.Ios -> 44.dp + else -> desktopSize + } +) From b393f671a0e180b403da4e7ec44987562cb0f809 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 17:18:04 +0530 Subject: [PATCH 03/13] feat: sort a million colours --- .../DeviceConnectionWidget.kt | 2 +- .../desktop/ui/devicetabs/DeviceTabsWidget.kt | 3 +- .../ui/ui/common/components/EmptyState.kt | 7 +++-- .../ui/ui/common/components/PresetCard.kt | 3 +- .../components/editor/EditorTextField.kt | 2 +- .../mockzilla/ui/ui/common/theme/Color.kt | 28 +++++++++---------- .../mockzilla/ui/ui/common/theme/Theme.kt | 3 +- .../formatting/BodyVisualTransformation.kt | 6 ++-- .../details/EndpointDetailsWidget.kt | 3 +- .../endpoints/endpoints/EndpointsWidget.kt | 5 ++-- .../common/widgets/metadata/MetaDataWidget.kt | 7 +++-- .../misccontrols/MiscControlsWidget.kt | 3 +- .../widgets/monitorlogs/MonitorLogsWidget.kt | 15 +++++----- .../details/MonitorLogDetailsWidget.kt | 6 ++-- .../CreateEditPresetViewModelTests.kt | 1 - 15 files changed, 52 insertions(+), 42 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt index e18fda475..444122962 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt @@ -313,7 +313,7 @@ private fun ConnectionCard( HorizontalDivider(Modifier.weight(1f), color = colorScheme.outline) Text( text = strings.widgets.deviceConnection.connectAutomatically, - color = colorScheme.onSurfaceFaint, + color = colorScheme.onSurfaceMuted, style = MaterialTheme.typography.labelMedium, ) HorizontalDivider(Modifier.weight(1f), color = colorScheme.outline) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt index 7016e58b9..c2907d4c4 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/devicetabs/DeviceTabsWidget.kt @@ -65,6 +65,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.PlatformHorizontalScrollbar import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.theme.LocalMonoFontFamily import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.success import com.apadmi.mockzilla.ui.utils.iconButtonSize @@ -238,7 +239,7 @@ fun DeviceTabsWidgetContent( text = LocalStrings.current.widgets.deviceTabs.betaBanner, modifier = Modifier.align(Alignment.CenterEnd).padding(8.dp), style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onSurfaceFaint + color = MaterialTheme.colorScheme.onSurfaceMuted ) } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt index 871732e5a..748e58f34 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt @@ -12,6 +12,9 @@ import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text + +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -39,7 +42,7 @@ fun EmptyState( text = title, style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + color = MaterialTheme.colorScheme.onSurfaceMuted ) description?.let { Spacer(modifier = Modifier.height(4.dp)) @@ -47,7 +50,7 @@ fun EmptyState( text = it, style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f) + color = MaterialTheme.colorScheme.onSurfaceFaint ) } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt index 2b3fa1bd3..2db0992e5 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt @@ -66,6 +66,7 @@ import com.apadmi.mockzilla.ui.ui.common.assets.EditUnderscore import com.apadmi.mockzilla.ui.ui.common.components.editor.EditorMode import com.apadmi.mockzilla.ui.ui.common.theme.LocalForceDarkMode import com.apadmi.mockzilla.ui.ui.common.theme.StateColors +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.success import com.apadmi.mockzilla.ui.ui.common.theme.warning @@ -169,7 +170,7 @@ internal fun PresetCard( animationSpec = tween(200), label = "chevron", ) - val chevronTint = if (hasExpandableContent) iconTint else colorScheme.onSurface.copy(alpha = 0.3f) + val chevronTint = if (hasExpandableContent) iconTint else colorScheme.onSurfaceFaint Column( Modifier.fillMaxWidth() diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/EditorTextField.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/EditorTextField.kt index 54fd8ac51..d8961b59e 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/EditorTextField.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/EditorTextField.kt @@ -329,7 +329,7 @@ private fun EditorContent( Icon( imageVector = Icons.DragCorner, contentDescription = null, - tint = colorScheme.onSurfaceVariant.copy(alpha = 0.5f), + tint = colorScheme.onSurfaceMuted, modifier = Modifier .align(Alignment.BottomEnd) .size(16.dp) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Color.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Color.kt index 9da0551dc..51972569e 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Color.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Color.kt @@ -23,13 +23,13 @@ internal val lightElevated = Color(0xFFBABFC6) // ── On-surface text ────────────────────────────────────────────────────────── internal val darkOnSurface = Color(0xFFECEFF3) internal val darkOnSurfaceVariant = Color(0xFFC0C4CB) -internal val darkOnSurfaceMuted = Color(0xFF888C94) -internal val darkOnSurfaceFaint = Color(0xFF5A5E65) +internal val darkOnSurfaceMuted = Color(0xFF91959D) +internal val darkOnSurfaceFaint = Color(0xFF747880) internal val lightOnSurface = Color(0xFF161A20) internal val lightOnSurfaceVariant = Color(0xFF2A2E34) internal val lightOnSurfaceMuted = Color(0xFF494D55) -internal val lightOnSurfaceFaint = Color(0xFF646971) +internal val lightOnSurfaceFaint = Color(0xFF565A61) // ── Outline ────────────────────────────────────────────────────────────────── internal val darkOutline = Color(0xFF2E323A) @@ -43,7 +43,7 @@ internal val darkOnPrimary = Color(0xFF07090D) internal val darkPrimaryContainer = Color(0xFF123738) internal val darkInversePrimary = Color(0xFF00858D) -internal val lightPrimary = Color(0xFF00858D) +internal val lightPrimary = Color(0xFF005F67) internal val lightOnPrimary = Color(0xFFFAFCFF) internal val lightPrimaryContainer = Color(0xFFC0E7E8) internal val lightInversePrimary = Color(0xFF68D5DA) @@ -58,13 +58,13 @@ internal val darkErrorContainer = Color(0xFF37292c) internal val darkInfo = Color(0xFF59C5F5) internal val darkInfoContainer = Color(0xFF073241) -internal val lightSuccess = Color(0xFF007C36) +internal val lightSuccess = Color(0xFF006A2D) internal val lightSuccessContainer = Color(0xFFC0F3D0) -internal val lightWarning = Color(0xFFB16600) +internal val lightWarning = Color(0xFF8A5000) internal val lightWarningContainer = Color(0xFFFFE1B6) -internal val lightError = Color(0xFFC9222B) +internal val lightError = Color(0xFFA81B23) internal val lightErrorContainer = Color(0xFFe6d7d9) -internal val lightInfo = Color(0xFF0075A9) +internal val lightInfo = Color(0xFF005F88) internal val lightInfoContainer = Color(0xFFC4ECFF) // ── HTTP methods ───────────────────────────────────────────────────────────── @@ -75,13 +75,13 @@ internal val darkMethodPatch = Color(0xFFCEA4FF) internal val darkMethodDelete = Color(0xFFFD736D) internal val darkMethodOther = Color(0xFF888C94) -internal val lightMethodGet = Color(0xFF008892) -internal val lightMethodPost = Color(0xFF007C36) -internal val lightMethodPut = Color(0xFFB76C00) -internal val lightMethodPatch = Color(0xFF794DB6) -internal val lightMethodDelete = Color(0xFFC9222B) +internal val lightMethodGet = Color(0xFF006F77) +internal val lightMethodPost = Color(0xFF006A2D) +internal val lightMethodPut = Color(0xFF8A5200) +internal val lightMethodPatch = Color(0xFF6A3EA8) +internal val lightMethodDelete = Color(0xFFA81B23) internal val lightMethodOther = Color(0xFF494D55) // ── JSON syntax ────────────────────────────────────────────────────────────── internal val darkJsonKey = Color(0xFFCEA4FF) -internal val lightJsonKey = Color(0xFF794DB6) +internal val lightJsonKey = Color(0xFF6A3EA8) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Theme.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Theme.kt index 76d2fd13b..8aafd3326 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Theme.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/theme/Theme.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density import com.apadmi.mockzilla.ui.i18n.ProvideLocalisableStrings -import com.apadmi.mockzilla.ui.ui.common.widgets.monitorlogs.details.ALPHA_MUTED import com.apadmi.mockzilla.ui.utils.Platform @Suppress("VARIABLE_NAME_INCORRECT_FORMAT") @@ -158,7 +157,7 @@ internal val ColorScheme.jsonHighlight: JsonHighlightColors stringColor = success.primary, numberColor = tertiary, boolColor = warning.primary, - nullColor = onSurface.copy(alpha = ALPHA_MUTED) + nullColor = onSurfaceMuted ) @get:Composable diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/utils/formatting/BodyVisualTransformation.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/utils/formatting/BodyVisualTransformation.kt index a21745617..e7f823a99 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/utils/formatting/BodyVisualTransformation.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/utils/formatting/BodyVisualTransformation.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.text.SpanStyle import com.apadmi.mockzilla.ui.ui.common.components.editor.EditorMode import com.apadmi.mockzilla.ui.ui.common.theme.jsonHighlight +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted internal object BodyVisualTransformation { internal fun isBodyTooLarge(body: String?) = body != null && body.length >= 25_000 @@ -15,10 +16,11 @@ internal object BodyVisualTransformation { val colorScheme = MaterialTheme.colorScheme val highlight = colorScheme.jsonHighlight + val onSurfaceMuted = colorScheme.onSurfaceMuted return remember(mode, highlight, colorScheme.onSurface, colorScheme.onSurfaceVariant) { when (mode) { EditorMode.Json -> JsonBodyVisualTransformation( - comment = SpanStyle(color = colorScheme.onSurface.copy(alpha = 0.5f)), + comment = SpanStyle(color = onSurfaceMuted), brace = SpanStyle(color = colorScheme.onSurfaceVariant), comma = SpanStyle(color = colorScheme.onSurfaceVariant), colon = SpanStyle(color = colorScheme.onSurfaceVariant), @@ -34,7 +36,7 @@ internal object BodyVisualTransformation { tagName = SpanStyle(color = highlight.keyColor), attributeName = SpanStyle(color = highlight.stringColor), attributeValue = SpanStyle(color = highlight.numberColor), - comment = SpanStyle(color = colorScheme.onSurface.copy(alpha = 0.5f)), + comment = SpanStyle(color = onSurfaceMuted), default = SpanStyle(color = colorScheme.onSurface), ) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt index 6b3ef3756..8ad719713 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt @@ -84,6 +84,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.buttons.RowDensityControls import com.apadmi.mockzilla.ui.ui.common.components.statusColors import com.apadmi.mockzilla.ui.ui.common.theme.LocalForceDarkMode import com.apadmi.mockzilla.ui.ui.common.theme.mockzillaMonoFontFamily +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.details.EndpointDetailsViewModel.* import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.details.components.PresetsContainer @@ -332,7 +333,7 @@ internal fun EndpointDetailsWidgetContent( imageVector = Icons.Default.Settings, contentDescription = null, modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + tint = MaterialTheme.colorScheme.onSurfaceFaint ) } ) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt index 02a7a04ed..834b9e7cb 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt @@ -63,6 +63,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.StatusChip import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton import com.apadmi.mockzilla.ui.ui.common.components.buttons.ButtonVariant import com.apadmi.mockzilla.ui.ui.common.components.buttons.RowDensityControls +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.warning @@ -277,7 +278,7 @@ private fun EndpointRow( Icon( imageVector = Icons.Default.ChevronRight, contentDescription = null, - tint = cs.onSurface.copy(alpha = 0.4f), + tint = cs.onSurfaceFaint, ) } HorizontalDivider(color = cs.onSurface.copy(alpha = 0.12f)) @@ -301,7 +302,7 @@ private fun EndpointRowChips( Text( text = strings.widgets.endpoints.noOverrides, style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f), + color = MaterialTheme.colorScheme.onSurfaceMuted, ) return } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt index 7a578576e..e9d9a4466 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt @@ -44,6 +44,7 @@ import com.apadmi.mockzilla.ui.i18n.Strings import com.apadmi.mockzilla.ui.ui.common.assets.MockzillaLogo import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.components.SectionHeader +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import org.jetbrains.compose.resources.decodeToImageBitmap import org.koin.core.parameter.parametersOf @@ -157,7 +158,7 @@ internal fun MetaDataRow( textAlign = TextAlign.Start, text = label, style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f) + color = MaterialTheme.colorScheme.onSurfaceMuted ) Text( modifier = Modifier.weight(1f), @@ -215,7 +216,7 @@ private fun SessionRow(label: String, value: String) = Row( text = label, style = MaterialTheme.typography.bodySmall, fontFamily = FontFamily.Monospace, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + color = MaterialTheme.colorScheme.onSurfaceMuted ) Text( text = value, @@ -269,7 +270,7 @@ private fun AppHeader( text = appPackage, style = MaterialTheme.typography.bodySmall, fontFamily = FontFamily.Monospace, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f), + color = MaterialTheme.colorScheme.onSurfaceMuted, maxLines = 2 ) } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt index 93eb8f7b3..d904f7f5a 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt @@ -53,6 +53,7 @@ import com.apadmi.mockzilla.ui.ui.common.theme.LocalSetForceDarkMode import com.apadmi.mockzilla.ui.ui.common.theme.LocalSetScaleFactor import com.apadmi.mockzilla.ui.ui.common.theme.ScaleFactor import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import org.koin.core.parameter.parametersOf @@ -275,7 +276,7 @@ private fun PresentationModeSettings( Text( text = strings.widgets.miscControls.fontScaleLabel(presentationModeScaleFactor), style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + color = MaterialTheme.colorScheme.onSurfaceMuted ) } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt index e1e65b696..c7f16cdd5 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt @@ -56,6 +56,8 @@ import com.apadmi.mockzilla.ui.ui.common.components.EmptyState import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.components.StatusChip import com.apadmi.mockzilla.ui.ui.common.theme.LocalMonoFontFamily +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.success import com.apadmi.mockzilla.ui.ui.common.theme.warning import com.apadmi.mockzilla.ui.ui.common.widgets.monitorlogs.details.formatTimestamp @@ -71,7 +73,7 @@ private fun HttpStatusCode.statusColor(isIntendedFailure: Boolean): Color { value in 200..299 -> cs.success.primary isIntendedFailure -> cs.warning.primary value >= 400 -> cs.error - else -> cs.onSurface.copy(alpha = 0.5f) + else -> cs.onSurfaceMuted } } @@ -112,7 +114,7 @@ fun LogRow( val isRealError = event.status.value >= 400 && !event.isIntendedFailure val errorColor = cs.error val errorBgColor = cs.errorContainer - val faintColor = cs.onSurface.copy(alpha = 0.3f) + val faintColor = cs.onSurfaceMuted val slowColor = cs.warning.primary Row( @@ -261,8 +263,7 @@ internal fun MonitorLogsWidgetContent( val monoFont = LocalMonoFontFamily.current val cs = MaterialTheme.colorScheme val streamingColor = cs.success.primary - val dimColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f) - val faintColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f) + val dimColor = cs.onSurfaceMuted val entryList = state.entries val titleStyle = MaterialTheme.typography.labelSmall.copy( fontFamily = monoFont, @@ -291,7 +292,7 @@ internal fun MonitorLogsWidgetContent( Icon( imageVector = Icons.Default.KeyboardArrowRight, contentDescription = null, - tint = faintColor, + tint = cs.onSurfaceFaint, modifier = Modifier.size(14.dp).rotate(chevronRotation), ) Text( @@ -308,7 +309,7 @@ internal fun MonitorLogsWidgetContent( Text( text = strings.widgets.logs.clickToInspect, style = MaterialTheme.typography.labelSmall.copy(fontFamily = monoFont), - color = faintColor, + color = cs.onSurfaceMuted, ) Spacer(modifier = Modifier.weight(1f)) Text( @@ -342,7 +343,7 @@ private fun MonitorLogsList( strings: Strings = LocalStrings.current, ) { if (entryList.isEmpty()) { - val iconTint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f) + val iconTint = MaterialTheme.colorScheme.onSurfaceFaint EmptyState( title = strings.widgets.logs.emptyTitle, description = strings.widgets.logs.emptyDescription, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt index 8b2cca280..6993f1a6b 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt @@ -218,7 +218,7 @@ internal fun MonitorLogDetailsEmptyContent( imageVector = Icons.Default.Menu, contentDescription = null, modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f) + tint = MaterialTheme.colorScheme.onSurfaceFaint ) } ) @@ -347,7 +347,7 @@ private fun LogTabBar( val selectedColor = if (isSelected) { MaterialTheme.colorScheme.primary } else { - MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f) + MaterialTheme.colorScheme.onSurfaceMuted } Column( @@ -439,7 +439,7 @@ private fun HeadersContent(headers: List>, strings: Strings Text( text = strings.widgets.logDetails.noHeaders, style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5f), + color = MaterialTheme.colorScheme.onSurfaceMuted, modifier = Modifier.padding(vertical = 4.dp), ) return diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopTest/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetViewModelTests.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopTest/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetViewModelTests.kt index 17503f951..9f3ba006f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopTest/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetViewModelTests.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopTest/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetViewModelTests.kt @@ -28,7 +28,6 @@ import kotlin.test.assertTrue import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.yield -import java.lang.Exception class CreateEditPresetViewModelTests : CoroutineTest() { private val dummyKey = EndpointConfiguration.Key("my-endpoint") From 2c85e14fad0cebf6afa3a5407cd6306da6beff20 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 17:23:31 +0530 Subject: [PATCH 04/13] fix: align button --- .../ui/ui/common/components/PresetCard.kt | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt index 2db0992e5..882f5caba 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/PresetCard.kt @@ -275,21 +275,18 @@ internal fun PresetCard( ) } - PresetCardVariant.Selectable -> Box( + PresetCardVariant.Selectable -> Tag( modifier = Modifier .minimumTouchTarget() .clip(RoundedCornerShape(6.dp)) - .clickable { onClicked(preset) } - ) { - Tag( - label = strings.applyLabel, - textColor = colorScheme.onSurface, - borderColor = colorScheme.outline, - backgroundColor = colorScheme.surfaceContainer, - shape = RoundedCornerShape(6.dp), - contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), - ) - } + .clickable { onClicked(preset) }, + label = strings.applyLabel, + textColor = colorScheme.onSurface, + borderColor = colorScheme.outline, + backgroundColor = colorScheme.surfaceContainer, + shape = RoundedCornerShape(6.dp), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), + ) } } From 0252b50a1ed6ae11dd1199bc6cd7d736f4012c63 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 17:30:44 +0530 Subject: [PATCH 05/13] fix: minor fixes --- .../kotlin/com/apadmi/mockzilla/ui/i18n/En.kt | 2 +- .../globalcontrols/GlobalControlsWidget.kt | 23 +++++++++++-------- .../mockzilla/mobile/ui/MobileAppRoot.kt | 1 + 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/i18n/En.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/i18n/En.kt index f57a2da79..8ef4b640d 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/i18n/En.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/i18n/En.kt @@ -193,7 +193,7 @@ val EnStrings = Strings( filterPlaceholderEmpty = "No matches", statusCodeFallback = "XXX", applyLabel = "Apply", - appliedLabel = "Set", + appliedLabel = "Applied", editLabel = "Edit", forceFailureBannerTitle = "Forced Failure is on.", forceFailureBannerBody = "Presets are ignored and locked", diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt index 2b4cbde55..389eb33b9 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt @@ -54,6 +54,7 @@ import com.apadmi.mockzilla.ui.ui.common.theme.warning import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.EndpointProperties import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.endpoints.EndpointsViewModel import com.apadmi.mockzilla.ui.ui.common.widgets.globalcontrols.GlobalControlsViewModel.State +import com.apadmi.mockzilla.ui.utils.Platform import com.apadmi.mockzilla.ui.utils.iconButtonSize import org.koin.core.parameter.parametersOf @@ -167,16 +168,18 @@ internal fun GlobalControlsWidgetIdleContent( onClick = onResetClicked ) - IconButton( - modifier = Modifier.iconButtonSize(24.dp), - onClick = onClose - ) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = strings.common.closeDescription, - tint = colorScheme.onSurfaceFaint, - modifier = Modifier.size(16.dp) - ) + if (Platform.current == Platform.Desktop) { + IconButton( + modifier = Modifier.iconButtonSize(24.dp), + onClick = onClose + ) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = strings.common.closeDescription, + tint = colorScheme.onSurfaceFaint, + modifier = Modifier.size(16.dp) + ) + } } } diff --git a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt index 67e766440..73d5ec556 100644 --- a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt @@ -249,6 +249,7 @@ private fun ConnectedState( ), creatingNewPreset = backStackEntry.toRoute().creatingNewPreset, onSave = navController::navigateUp, + onCancel = navController::navigateUp, ) } } From cab09369d1cd6732bfaf77d3179eab87d22de2ed Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 18:02:25 +0530 Subject: [PATCH 06/13] feat: improve headers --- .../createeditpreset/CreateEditPresetWidget.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt index 5dca929a6..7e6a9d90f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt @@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -86,6 +87,7 @@ import com.apadmi.mockzilla.ui.ui.common.components.buttons.OutlineButtonVariant import com.apadmi.mockzilla.ui.ui.common.components.editor.EditorMode import com.apadmi.mockzilla.ui.ui.common.components.editor.FindableEditorTextField import com.apadmi.mockzilla.ui.ui.common.theme.LocalMonoFontFamily +import com.apadmi.mockzilla.ui.ui.common.theme.jsonKey import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.widgets.endpoints.createeditpreset.CreateEditPresetViewModel.* @@ -116,23 +118,25 @@ private fun ColumnScope.HeadersSection( Row( modifier = Modifier .fillMaxWidth() - .height(48.dp) + .heightIn(min = 48.dp) .padding(start = 16.dp, end = 4.dp), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp) ) { Text( text = header.key, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.weight(1f), + style = MaterialTheme.typography.bodyMedium.copy(fontFamily = LocalMonoFontFamily.current), + color = MaterialTheme.colorScheme.jsonKey, + modifier = Modifier.weight(1f).padding(vertical = 4.dp), ) + Row( modifier = Modifier.weight(3f), verticalAlignment = Alignment.CenterVertically, ) { Text( - text = ": ${header.value}", - style = MaterialTheme.typography.bodyMedium, + text = header.value, + style = MaterialTheme.typography.bodyMedium.copy(fontFamily = LocalMonoFontFamily.current), color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.weight(1f), ) From 5f3310f64d595fe3d46f10d38a3047ca944636d5 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 18:15:07 +0530 Subject: [PATCH 07/13] fix: fix hardcoded heights --- .../mockzilla/ui/ui/common/components/ForceFailureBanner.kt | 6 ++---- .../ui/ui/common/components/ResponseLatencyCard.kt | 4 +--- .../ui/common/components/editor/FindableEditorTextField.kt | 5 +++-- .../common/widgets/globalcontrols/GlobalControlsWidget.kt | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt index 489809017..42321ac3a 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ForceFailureBanner.kt @@ -4,7 +4,6 @@ package com.apadmi.mockzilla.ui.ui.common.components import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -13,14 +12,13 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check import androidx.compose.material3.ColorScheme -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -90,7 +88,7 @@ internal fun ForceFailureBanner( Row( modifier = modifier .fillMaxWidth() - .height(64.dp) + .heightIn(min = 64.dp) .clip(shape) .background(color = colorScheme.background) .border( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt index 9300ab3dc..690be2398 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt @@ -337,9 +337,7 @@ internal fun ResponseLatencyCard( } Row( - modifier = Modifier - .fillMaxWidth() - .height(14.dp), + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt index 2dc9f7d9a..577fb3a26 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -357,7 +358,7 @@ private fun FindReplaceBar( leadingIcon = Icons.Default.FindReplace, variant = ButtonVariant.Soft, size = ButtonSize.Sm, - modifier = Modifier.height(30.dp), + modifier = Modifier.heightIn(min = 30.dp), onClick = onReplace, ) BaseButton( @@ -365,7 +366,7 @@ private fun FindReplaceBar( leadingIcon = Icons.Default.DoneAll, variant = ButtonVariant.Soft, size = ButtonSize.Sm, - modifier = Modifier.height(30.dp), + modifier = Modifier.heightIn(min = 30.dp), onClick = onReplaceAll, ) } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt index 389eb33b9..3351da5af 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt @@ -9,7 +9,7 @@ import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -160,7 +160,7 @@ internal fun GlobalControlsWidgetIdleContent( } BaseButton( - modifier = Modifier.height(32.dp), + modifier = Modifier.heightIn(min = 32.dp), label = strings.widgets.globalControls.resetAllLabel, variant = ButtonVariant.Ghost, size = ButtonSize.Sm, From e8098d350e77f1e7b3fdfa72a8c92175770ed5f4 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 21:47:23 +0530 Subject: [PATCH 08/13] fix: fix caching --- .../apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt | 9 +++------ .../mockzilla/ui/di/utils/KoinViewModel.android.kt | 8 +++++--- .../apadmi/mockzilla/ui/di/utils/KoinViewModel.kt | 6 ++++-- .../ui/engine/device/ActiveDeviceManager.kt | 3 +++ .../createeditpreset/CreateEditPresetWidget.kt | 6 +++--- .../endpoints/details/EndpointDetailsWidget.kt | 3 ++- .../widgets/endpoints/endpoints/EndpointsWidget.kt | 3 +-- .../widgets/globalcontrols/GlobalControlsWidget.kt | 2 +- .../ui/common/widgets/metadata/MetaDataWidget.kt | 2 +- .../widgets/misccontrols/MiscControlsWidget.kt | 2 +- .../widgets/monitorlogs/MonitorLogsWidget.kt | 2 +- .../monitorlogs/details/MonitorLogDetailsWidget.kt | 3 ++- .../mockzilla/ui/di/utils/KoinViewModel.desktop.kt | 14 ++++++++------ .../mockzilla/ui/di/utils/KoinViewModel.ios.kt | 8 +++++--- .../mockzilla/ui/di/utils/KoinViewModel.js.kt | 8 +++++--- .../apadmi/mockzilla/mobile/ui/MobileAppRoot.kt | 2 +- 16 files changed, 46 insertions(+), 35 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt index 6dea0447b..c5a035762 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt @@ -175,11 +175,8 @@ fun DesktopApp( // temporarily disconnected — the VM handles disconnection gracefully while preserving // selectedEndpoint). allDevices is a live collection, updated before the flow fires. LaunchedEffect(Unit) { - var knownKeys = activeDeviceMonitor.allDevices.map { it.device.toString() }.toSet() - activeDeviceMonitor.onDeviceConnectionStateChange.collect { - val currentKeys = activeDeviceMonitor.allDevices.map { it.device.toString() }.toSet() - (knownKeys - currentKeys).forEach { evictDesktopViewModelsForKey(it) } - knownKeys = currentKeys + activeDeviceMonitor.onDeviceRemoved.collect { + evictDesktopViewModelsForKey(it) } } @@ -223,7 +220,7 @@ private fun DeviceContent( strings: Strings ) { val viewModel = getViewModel( - key = device.toString() + device = device ) { parametersOf(device) } val state by viewModel.state.collectAsState() diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt index 82d04c133..365c41938 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt @@ -1,6 +1,7 @@ package com.apadmi.mockzilla.ui.di.utils import androidx.compose.runtime.Composable +import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.viewmodel.ViewModel as InternalViewModel @@ -21,13 +22,14 @@ actual inline fun Module.viewModel( @Composable actual inline fun getViewModel( qualifier: Qualifier?, - key: String?, + device: Device?, + keyPrefix: String?, noinline parameters: ParametersDefinition? ): T = koinViewModel( qualifier = qualifier, - key = key, + key = keyPrefix + device.toString(), parameters = parameters, scope = MockzillaUiKoinContext.koin.scopeRegistry.rootScope ) -actual fun evictDesktopViewModelsForKey(key: String) = Unit +actual fun evictDesktopViewModelsForKey(device: Device) = Unit diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt index 2edde6946..f515acab1 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt @@ -1,6 +1,7 @@ package com.apadmi.mockzilla.ui.di.utils import androidx.compose.runtime.Composable +import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.viewmodel.ViewModel import org.koin.core.definition.Definition import org.koin.core.definition.KoinDefinition @@ -16,8 +17,9 @@ expect inline fun Module.viewModel( @Composable expect inline fun getViewModel( qualifier: Qualifier? = null, - key: String? = null, + device: Device? = null, + keyPrefix: String? = null, noinline parameters: ParametersDefinition? = null ): T -expect fun evictDesktopViewModelsForKey(key: String) +expect fun evictDesktopViewModelsForKey(device: Device) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/engine/device/ActiveDeviceManager.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/engine/device/ActiveDeviceManager.kt index 8a8c2d4e9..04b0a290d 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/engine/device/ActiveDeviceManager.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/engine/device/ActiveDeviceManager.kt @@ -17,6 +17,7 @@ interface ActiveDeviceMonitor { // Fires when a device connects / disconnects val onDeviceConnectionStateChange: Flow + val onDeviceRemoved: Flow val allDevices: Collection } @@ -35,6 +36,7 @@ internal class ActiveDeviceManagerImpl( ) : ActiveDeviceMonitor, ActiveDeviceSelector { override val selectedDevice = MutableStateFlow(null) override val onDeviceConnectionStateChange = MutableSharedFlow(replay = 1) + override val onDeviceRemoved = MutableSharedFlow(replay = 0) private val allDevicesInternal = mutableMapOf() override val allDevices get() = allDevicesInternal.values @@ -106,6 +108,7 @@ internal class ActiveDeviceManagerImpl( } allDevicesInternal.remove(device) onDeviceConnectionStateChange.emit(Unit) + onDeviceRemoved.emit(device) } } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt index 7e6a9d90f..ab895ebd1 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt @@ -354,10 +354,10 @@ fun CreateEditPresetWidget( onCancel: () -> Unit = {}, onSave: () -> Unit = {}, ) { - val vmKey = "CreateEditPresetViewModel-${activeEndpoint.raw}-$device" - val cleanupVm = { evictDesktopViewModelsForKey(key = vmKey) } + val cleanupVm = { evictDesktopViewModelsForKey(device = device) } val viewModel = getViewModel( - key = vmKey + device = device, + keyPrefix = activeEndpoint.raw ) { parametersOf( activeEndpoint, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt index 8ad719713..a57a78061 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt @@ -276,7 +276,8 @@ fun EndpointDetailsWidget( ) { val uriHandler = LocalUriHandler.current val viewModel = getViewModel( - key = "${activeEndpoint?.raw}-$device" + device = device, + keyPrefix = activeEndpoint?.raw ) { parametersOf(activeEndpoint, device) } val state by viewModel.state.collectAsState() diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt index 834b9e7cb..ce27a720d 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -95,7 +94,7 @@ fun EndpointsWidget( onEndpointClicked: (Key) -> Unit, onGlobalControlsClicked: () -> Unit ) { - val viewModel = getViewModel(key = device.toString()) { + val viewModel = getViewModel(device = device) { parametersOf(device) } val state by viewModel.state.collectAsState() diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt index 3351da5af..f248be009 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt @@ -61,7 +61,7 @@ import org.koin.core.parameter.parametersOf @Composable fun GlobalControlsWidget(device: Device, onClose: () -> Unit = {}) { - val viewModel = getViewModel(key = device.toString()) { + val viewModel = getViewModel(device = device) { parametersOf(device) } val focusManager = LocalFocusManager.current diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt index e9d9a4466..a10f18382 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/metadata/MetaDataWidget.kt @@ -64,7 +64,7 @@ private fun RunTarget.label(strings: Strings) = when (this) { @Composable fun MetaDataWidget(device: Device) { val viewModel = - getViewModel(key = device.toString()) { parametersOf(device) } + getViewModel(device = device) { parametersOf(device) } val state by viewModel.state.collectAsState() MetaDataWidgetContent(state, device) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt index d904f7f5a..ad24a731b 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt @@ -77,7 +77,7 @@ private data object PresentationModeScaleFactor { fun MiscControlsWidget( device: Device? ) { - val viewModel = getViewModel(key = device?.toString()) { parametersOf(device) } + val viewModel = getViewModel(device = device) { parametersOf(device) } val state by viewModel.state.collectAsState() MiscControlsWidgetContent( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt index c7f16cdd5..af8972ad1 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/MonitorLogsWidget.kt @@ -87,7 +87,7 @@ fun MonitorLogsWidget( onExpandToggled: () -> Unit = {}, onViewDetail: (LogEvent) -> Unit, ) { - val viewModel = getViewModel(key = device.toString()) { parametersOf(device) } + val viewModel = getViewModel(device = device) { parametersOf(device) } val state by viewModel.state.collectAsState() MonitorLogsWidgetContent( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt index 6993f1a6b..5990e1748 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/monitorlogs/details/MonitorLogDetailsWidget.kt @@ -76,7 +76,8 @@ fun MonitorLogDetailsWidget( onClose: () -> Unit = {}, ) { val viewModel = getViewModel( - key = logDetail?.id ?: "empty" + device = device, + keyPrefix = logDetail?.id ) { parametersOf(device, logDetail) } val state by viewModel.state.collectAsState() diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt index a11d2dfcf..0ca0afa89 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt @@ -2,6 +2,7 @@ package com.apadmi.mockzilla.ui.di.utils import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.viewmodel.ViewModel import org.koin.core.definition.Definition import org.koin.core.module.Module @@ -23,13 +24,14 @@ actual inline fun Module.viewModel( @Composable actual inline fun getViewModel( qualifier: Qualifier?, - key: String?, + device: Device?, + keyPrefix: String?, noinline parameters: ParametersDefinition? -): T = remember(qualifier, key) { - key?.let { +): T = remember(qualifier, keyPrefix, device) { + device?.let { // Keyed VMs: check the persistent cache so the same instance is returned after the // composable re-enters composition (e.g. switching back to a device tab). - val cacheKey = "${T::class.qualifiedName}|$qualifier|$key" + val cacheKey = "${T::class.qualifiedName}|$keyPrefix|$qualifier|$device" @Suppress("UNCHECKED_CAST") desktopViewModelCache.getOrPut(cacheKey) { MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) @@ -39,9 +41,9 @@ actual inline fun getViewModel( // Called when a device is fully removed from allDevices. Cancels the coroutine scope directly // because the base ViewModel class has no clear() method. -actual fun evictDesktopViewModelsForKey(key: String) { +actual fun evictDesktopViewModelsForKey(device: Device) { desktopViewModelCache.keys - .filter { it.endsWith("|$key") } + .filter { it.endsWith("|$device") } .forEach { cacheKey -> (desktopViewModelCache.remove(cacheKey) as? ViewModel)?.viewModelScope?.cancel() } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt index 6e2fc5677..989f06ea8 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt @@ -2,6 +2,7 @@ package com.apadmi.mockzilla.ui.di.utils import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.viewmodel.ViewModel import org.koin.core.definition.Definition import org.koin.core.module.Module @@ -16,10 +17,11 @@ actual inline fun Module.viewModel( @Composable actual inline fun getViewModel( qualifier: Qualifier?, - key: String?, + device: Device?, + keyPrefix: String?, noinline parameters: ParametersDefinition? -): T = remember(qualifier, key) { +): T = remember(qualifier, device) { MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) } -actual fun evictDesktopViewModelsForKey(key: String) = Unit +actual fun evictDesktopViewModelsForKey(device: Device) = Unit diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt index 966662420..2219c7387 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt @@ -2,6 +2,7 @@ package com.apadmi.mockzilla.ui.di.utils import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.viewmodel.ViewModel import org.koin.core.definition.Definition import org.koin.core.parameter.ParametersDefinition @@ -15,10 +16,11 @@ actual inline fun org.koin.core.module.Module.viewModel( @Composable actual inline fun getViewModel( qualifier: Qualifier?, - key: String?, + device: Device?, + keyPrefix: String?, noinline parameters: ParametersDefinition? -): T = remember(qualifier, key) { +): T = remember(qualifier, device) { MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) } -actual fun evictDesktopViewModelsForKey(key: String) = Unit +actual fun evictDesktopViewModelsForKey(device: Device) = Unit diff --git a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt index 73d5ec556..12a84e90e 100644 --- a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt @@ -143,7 +143,7 @@ internal fun MobileAppRoot( @Composable private fun DeviceContent(device: Device, navController: NavHostController) { - val viewModel = getViewModel(key = device.toString()) { parametersOf(device) } + val viewModel = getViewModel(device = device) { parametersOf(device) } val state by viewModel.state.collectAsState() when (val currentState = state) { From 95e8eaecc63884a2df50f74a3fc14380ed80b56a Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 21:53:17 +0530 Subject: [PATCH 09/13] fix: improve toggle touch area --- .../ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt index ad24a731b..aa3ca7901 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt @@ -185,6 +185,11 @@ private fun DarkModeSettings( Row( modifier = Modifier.fillMaxWidth() + .toggleable( + value = LocalForceDarkMode.current, + onValueChange = { checked -> setForceDarkMode(checked) }, + role = Role.Switch, + ) .padding(horizontal = 4.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { From 853ae47dd61750a71f45d5c789c7a56270c74a27 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 21:59:53 +0530 Subject: [PATCH 10/13] feat: close widget on repeat click --- .../com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt | 2 +- .../widgets/endpoints/endpoints/EndpointsWidget.kt | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt index c5a035762..ce92fc1b1 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/DesktopAppRoot.kt @@ -302,7 +302,7 @@ private fun ConnectedDeviceLayout( device = connectedState.activeDevice.device, onEndpointClicked = { key -> viewModel.setSelectedEndpoint(key) - state = state.copy(rightPanelTab = RightPanelTab.EndpointDetails) + state = state.copy(rightPanelTab = RightPanelTab.EndpointDetails.takeUnless { key == null }) }, onGlobalControlsClicked = { state = state.copy(globalControlsOpen = true) }, ) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt index ce27a720d..84bc3e58c 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/endpoints/EndpointsWidget.kt @@ -91,7 +91,7 @@ private fun RowDensity.verticalPadding(): Dp = when (this) { @Composable fun EndpointsWidget( device: Device, - onEndpointClicked: (Key) -> Unit, + onEndpointClicked: (Key?) -> Unit, onGlobalControlsClicked: () -> Unit ) { val viewModel = getViewModel(device = device) { @@ -106,8 +106,13 @@ fun EndpointsWidget( onFilterUpdate = viewModel::onFilterChanged, onRowDensityChanged = viewModel::onRowDensityChanged, onEndpointClicked = { key -> - selectedKey = key - onEndpointClicked(key) + if (selectedKey == key) { + selectedKey = null + onEndpointClicked(null) + } else { + selectedKey = key + onEndpointClicked(key) + } }, onGlobalControlsClicked = onGlobalControlsClicked ) From 917057b36856dfcdb92ee35a3ce34c6b59a95af4 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 28 Jun 2026 22:43:05 +0530 Subject: [PATCH 11/13] fix: fix various latency issues --- .../ui/ui/common/components/CustomSlider.kt | 80 +++++-------------- .../common/components/ResponseLatencyCard.kt | 4 +- .../misccontrols/MiscControlsWidget.kt | 25 +----- 3 files changed, 23 insertions(+), 86 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt index cf9a8ef1d..56cad831b 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt @@ -15,86 +15,50 @@ import androidx.compose.material3.SliderDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint @OptIn(ExperimentalMaterial3Api::class) @Composable fun CustomSlider( value: Float, onValueChange: (Float) -> Unit, + steps: Int = 0, modifier: Modifier = Modifier, valueRange: ClosedFloatingPointRange = 0f..1f, - enabled: Boolean = true, - activeTrackColor: Color? = null, - showThumb: Boolean = true, - onValueChangeFinished: (() -> Unit)? = null, ) { val colorScheme = MaterialTheme.colorScheme - val activeColor = activeTrackColor ?: colorScheme.primary Slider( + modifier = modifier, value = value, - onValueChange = onValueChange, - modifier = modifier.height(24.dp), - enabled = enabled, + onValueChange = { onValueChange(it) }, + steps = steps, valueRange = valueRange, - onValueChangeFinished = onValueChangeFinished, - thumb = { - if (showThumb) { - Box( - modifier = Modifier - .size(22.dp) - .shadow( - elevation = 2.dp, - shape = CircleShape, - clip = false - ) - .background(Color.Transparent, CircleShape), - contentAlignment = Alignment.Center, - ) { - Box( - modifier = Modifier - .size(12.dp) - .background( - if (enabled) { - activeColor - } else { - colorScheme.onSurfaceFaint - }, - CircleShape - ) - ) - } - } + Box( + modifier = Modifier + .size(16.dp) + .clip(CircleShape) + .background(colorScheme.primary) + ) }, - - track = { sliderState -> + track = { state -> SliderDefaults.Track( - sliderState = sliderState, - modifier = Modifier.height(4.dp), + sliderState = state, + modifier = Modifier.height(2.dp), colors = SliderDefaults.colors( - activeTrackColor = activeColor, - inactiveTrackColor = colorScheme.outline.copy(alpha = 0.25f), - disabledActiveTrackColor = colorScheme.onSurfaceFaint.copy(alpha = 0.3f), - disabledInactiveTrackColor = colorScheme.outline.copy(alpha = 0.1f), - thumbColor = Color.Transparent, + activeTrackColor = colorScheme.primary, + inactiveTrackColor = colorScheme.outline, + activeTickColor = Color.Transparent, + inactiveTickColor = Color.Transparent, ), - drawStopIndicator = null, - thumbTrackGapSize = 0.dp, ) - }, - - colors = SliderDefaults.colors( - thumbColor = Color.Transparent, - activeTrackColor = activeColor, - inactiveTrackColor = colorScheme.outline.copy(alpha = 0.25f), - ), + } ) } @@ -109,11 +73,5 @@ private fun MockzillaSliderPreview() = PreviewSurface { value = 0.4f, onValueChange = {}, ) - - CustomSlider( - value = 0.7f, - onValueChange = {}, - enabled = false, - ) } } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt index 690be2398..e72ea5518 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/ResponseLatencyCard.kt @@ -147,7 +147,7 @@ internal fun ResponseLatencyCard( } } - val updateValue = remember { + val updateValue = remember(onChange) { { it: Int -> val clamped = it.clamped() value = clamped @@ -320,8 +320,6 @@ internal fun ResponseLatencyCard( modifier = Modifier .fillMaxWidth() .padding(end = if (isOverflowing) 4.dp else 0.dp), - activeTrackColor = colorScheme.primary, - showThumb = !isOverflowing, onValueChange = { updateValue(it.toInt()) }, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt index aa3ca7901..291ea37ab 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt @@ -41,6 +41,7 @@ import com.apadmi.mockzilla.ui.di.utils.getViewModel import com.apadmi.mockzilla.ui.engine.device.Device import com.apadmi.mockzilla.ui.i18n.LocalStrings import com.apadmi.mockzilla.ui.i18n.Strings +import com.apadmi.mockzilla.ui.ui.common.components.CustomSlider import com.apadmi.mockzilla.ui.ui.common.components.CustomToggle import com.apadmi.mockzilla.ui.ui.common.components.PreviewSurface import com.apadmi.mockzilla.ui.ui.common.components.SectionHeader @@ -250,32 +251,12 @@ private fun PresentationModeSettings( modifier = Modifier.fillMaxWidth().padding(end = 4.dp), verticalAlignment = Alignment.CenterVertically, ) { - Slider( + CustomSlider( modifier = Modifier.weight(1f), value = presentationModeScaleFactor, - onValueChange = { onPresentationModeScaleFactorChange(it) }, steps = 5, + onValueChange = { onPresentationModeScaleFactorChange(it) }, valueRange = PresentationModeScaleFactor.MIN..PresentationModeScaleFactor.MAX, - thumb = { - Box( - modifier = Modifier - .size(16.dp) - .clip(CircleShape) - .background(colorScheme.primary) - ) - }, - track = { state -> - SliderDefaults.Track( - sliderState = state, - modifier = Modifier.height(2.dp), - colors = SliderDefaults.colors( - activeTrackColor = colorScheme.primary, - inactiveTrackColor = colorScheme.outline, - activeTickColor = Color.Transparent, - inactiveTickColor = Color.Transparent, - ), - ) - } ) Spacer(modifier = Modifier.width(8.dp)) Text( From 053d27b56d7676d4b82a38fa7114864d08b7314e Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 29 Jun 2026 08:35:05 +0530 Subject: [PATCH 12/13] fix: actually fix caching --- .../com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt | 2 +- .../endpoints/createeditpreset/CreateEditPresetWidget.kt | 5 +++-- .../apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt index f515acab1..c38fba163 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.kt @@ -22,4 +22,4 @@ expect inline fun getViewModel( noinline parameters: ParametersDefinition? = null ): T -expect fun evictDesktopViewModelsForKey(device: Device) +expect fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String? = null) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt index ab895ebd1..b28b1b586 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt @@ -354,10 +354,11 @@ fun CreateEditPresetWidget( onCancel: () -> Unit = {}, onSave: () -> Unit = {}, ) { - val cleanupVm = { evictDesktopViewModelsForKey(device = device) } + val keyPrefix = "CreateEditPresetViewModel-${activeEndpoint.raw}" + val cleanupVm = { evictDesktopViewModelsForKey(device = device, keyPrefix = keyPrefix) } val viewModel = getViewModel( device = device, - keyPrefix = activeEndpoint.raw + keyPrefix = keyPrefix ) { parametersOf( activeEndpoint, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt index 0ca0afa89..a9fbe3791 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt @@ -31,7 +31,7 @@ actual inline fun getViewModel( device?.let { // Keyed VMs: check the persistent cache so the same instance is returned after the // composable re-enters composition (e.g. switching back to a device tab). - val cacheKey = "${T::class.qualifiedName}|$keyPrefix|$qualifier|$device" + val cacheKey = "${T::class.qualifiedName}|$qualifier|$keyPrefix|$device" @Suppress("UNCHECKED_CAST") desktopViewModelCache.getOrPut(cacheKey) { MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) @@ -41,9 +41,9 @@ actual inline fun getViewModel( // Called when a device is fully removed from allDevices. Cancels the coroutine scope directly // because the base ViewModel class has no clear() method. -actual fun evictDesktopViewModelsForKey(device: Device) { +actual fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String?) { desktopViewModelCache.keys - .filter { it.endsWith("|$device") } + .filter { it.endsWith("${"|$keyPrefix".takeIf { keyPrefix != null} ?: ""}|$device") } .forEach { cacheKey -> (desktopViewModelCache.remove(cacheKey) as? ViewModel)?.viewModelScope?.cancel() } From 84dc484084ac50e8ccae2f0439d23a921814768f Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 29 Jun 2026 18:01:02 +0530 Subject: [PATCH 13/13] chore: run spotless --- .../deviceconnection/DeviceConnectionWidget.kt | 1 - .../ui/di/utils/KoinViewModel.android.kt | 2 +- .../ui/ui/common/components/CustomSlider.kt | 3 --- .../ui/ui/common/components/EmptyState.kt | 6 +++--- .../editor/FindableEditorTextField.kt | 8 ++++---- .../createeditpreset/CreateEditPresetWidget.kt | 4 ++-- .../endpoints/details/EndpointDetailsWidget.kt | 2 +- .../globalcontrols/GlobalControlsWidget.kt | 2 +- .../widgets/misccontrols/MiscControlsWidget.kt | 7 ------- .../apadmi/mockzilla/ui/utils/TouchTarget.kt | 17 ++++++++--------- .../ui/di/utils/KoinViewModel.desktop.kt | 2 +- .../mockzilla/ui/di/utils/KoinViewModel.ios.kt | 2 +- .../mockzilla/ui/di/utils/KoinViewModel.js.kt | 2 +- .../apadmi/mockzilla/mobile/ui/MobileAppRoot.kt | 8 ++++---- .../mockzilla/mobile/ui/utils/Destination.kt | 2 +- 15 files changed, 28 insertions(+), 40 deletions(-) diff --git a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt index 444122962..7acddee98 100644 --- a/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt +++ b/mockzilla-management-ui/mockzilla-desktop/src/commonMain/kotlin/com/apadmi/mockzilla/desktop/ui/deviceconnection/DeviceConnectionWidget.kt @@ -72,7 +72,6 @@ import com.apadmi.mockzilla.ui.ui.common.components.StandardTextTooltip import com.apadmi.mockzilla.ui.ui.common.components.buttons.BaseButton import com.apadmi.mockzilla.ui.ui.common.components.buttons.SolidButton import com.apadmi.mockzilla.ui.ui.common.theme.LocalMonoFontFamily -import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import com.apadmi.mockzilla.ui.ui.common.theme.success diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt index 365c41938..e62606e74 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/androidMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.android.kt @@ -32,4 +32,4 @@ actual inline fun getViewModel( scope = MockzillaUiKoinContext.koin.scopeRegistry.rootScope ) -actual fun evictDesktopViewModelsForKey(device: Device) = Unit +actual fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String?) = Unit diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt index 56cad831b..b8845412c 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/CustomSlider.kt @@ -13,15 +13,12 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Slider import androidx.compose.material3.SliderDefaults import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp - @OptIn(ExperimentalMaterial3Api::class) @Composable fun CustomSlider( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt index 748e58f34..b5178d06f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/EmptyState.kt @@ -12,9 +12,6 @@ import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text - -import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint -import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -22,6 +19,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceFaint +import com.apadmi.mockzilla.ui.ui.common.theme.onSurfaceMuted + @Composable fun EmptyState( title: String, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt index 577fb3a26..63373ab2d 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/components/editor/FindableEditorTextField.kt @@ -248,7 +248,7 @@ private fun FindReplaceBar( ) { IconButton( onClick = onToggleReplaceMode, - modifier = Modifier.iconButtonSize(24.dp), + modifier = Modifier.iconButtonSize(), ) { Icon( imageVector = Icons.Default.KeyboardArrowRight, @@ -301,7 +301,7 @@ private fun FindReplaceBar( }, ) - IconButton(onClick = onPrev, modifier = Modifier.iconButtonSize(28.dp)) { + IconButton(onClick = onPrev, modifier = Modifier.iconButtonSize()) { Icon( imageVector = Icons.Default.KeyboardArrowUp, contentDescription = strings.previousMatchDescription, @@ -309,7 +309,7 @@ private fun FindReplaceBar( tint = colorScheme.onSurfaceVariant, ) } - IconButton(onClick = onNext, modifier = Modifier.iconButtonSize(28.dp)) { + IconButton(onClick = onNext, modifier = Modifier.iconButtonSize()) { Icon( imageVector = Icons.Default.KeyboardArrowDown, contentDescription = strings.nextMatchDescription, @@ -323,7 +323,7 @@ private fun FindReplaceBar( .width(1.dp) .background(colorScheme.outlineVariant), ) - IconButton(onClick = onClose, modifier = Modifier.iconButtonSize(28.dp)) { + IconButton(onClick = onClose, modifier = Modifier.iconButtonSize()) { Icon( imageVector = Icons.Default.Close, contentDescription = strings.closeFindBarDescription, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt index b28b1b586..7dc78fdf5 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/createeditpreset/CreateEditPresetWidget.kt @@ -205,7 +205,7 @@ private fun ColumnScope.HeadersSection( }, enabled = canAdd, modifier = Modifier - .iconButtonSize(28.dp) + .iconButtonSize() .pointerHoverIcon(if (canAdd) PointerIcon.Hand else blockedPointerIcon), ) { Icon( @@ -525,7 +525,7 @@ private fun BodySection( IconButton( onClick = onToggleExpand, - modifier = Modifier.iconButtonSize(40.dp), + modifier = Modifier.iconButtonSize(), ) { Icon( imageVector = if (isExpanded) Icons.Default.FullscreenExit else Icons.Default.Fullscreen, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt index a57a78061..ad2e1708f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/endpoints/details/EndpointDetailsWidget.kt @@ -488,7 +488,7 @@ private fun ActivePresetBanner( color = colorScheme.onSurfaceVariant, ) } - IconButton(onClick = onClear, modifier = Modifier.iconButtonSize(24.dp)) { + IconButton(onClick = onClear, modifier = Modifier.iconButtonSize()) { Icon( imageVector = Icons.Default.Close, contentDescription = null, diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt index f248be009..86c0c5c1f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/globalcontrols/GlobalControlsWidget.kt @@ -170,7 +170,7 @@ internal fun GlobalControlsWidgetIdleContent( if (Platform.current == Platform.Desktop) { IconButton( - modifier = Modifier.iconButtonSize(24.dp), + modifier = Modifier.iconButtonSize(), onClick = onClose ) { Icon( diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt index 291ea37ab..96224b78f 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/ui/common/widgets/misccontrols/MiscControlsWidget.kt @@ -1,8 +1,6 @@ package com.apadmi.mockzilla.ui.ui.common.widgets.misccontrols import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -12,14 +10,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.selection.toggleable -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Restore import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Slider -import androidx.compose.material3.SliderDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -30,8 +25,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt index cb0da0352..4b4f28bba 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/commonMain/kotlin/com/apadmi/mockzilla/ui/utils/TouchTarget.kt @@ -6,25 +6,24 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +@Suppress("MAGIC_NUMBER") private val touchTargetSize: Dp get() = when (Platform.current) { Platform.Android, Platform.Ios -> 44.dp else -> 24.dp } -/** Enforces WCAG AA minimum touch target (44dp mobile, 24dp desktop). */ +/** Enforces WCAG AA minimum touch target (44dp mobile, 24dp desktop). + * + * @return*/ fun Modifier.minimumTouchTarget(): Modifier = defaultMinSize( minWidth = touchTargetSize, minHeight = touchTargetSize, ) /** - * Sets an exact size for a compact IconButton: [desktopSize] on desktop/JS, - * 44dp on Android/iOS so the tap target meets WCAG AA. + * Sets an exact size for a compact IconButton based on the platform + * + * @return */ -fun Modifier.iconButtonSize(desktopSize: Dp = 24.dp): Modifier = size( - when (Platform.current) { - Platform.Android, Platform.Ios -> 44.dp - else -> desktopSize - } -) +fun Modifier.iconButtonSize(): Modifier = size(touchTargetSize) diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt index a9fbe3791..280c64ae5 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/desktopMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.desktop.kt @@ -43,7 +43,7 @@ actual inline fun getViewModel( // because the base ViewModel class has no clear() method. actual fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String?) { desktopViewModelCache.keys - .filter { it.endsWith("${"|$keyPrefix".takeIf { keyPrefix != null} ?: ""}|$device") } + .filter { it.endsWith("${"|$keyPrefix".takeIf { keyPrefix != null } ?: ""}|$device") } .forEach { cacheKey -> (desktopViewModelCache.remove(cacheKey) as? ViewModel)?.viewModelScope?.cancel() } diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt index 989f06ea8..9fac16db8 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/iosMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.ios.kt @@ -24,4 +24,4 @@ actual inline fun getViewModel( MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) } -actual fun evictDesktopViewModelsForKey(device: Device) = Unit +actual fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String?) = Unit diff --git a/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt b/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt index 2219c7387..44fb5dffe 100644 --- a/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt +++ b/mockzilla-management-ui/mockzilla-management-ui-common/src/jsMain/kotlin/com/apadmi/mockzilla/ui/di/utils/KoinViewModel.js.kt @@ -23,4 +23,4 @@ actual inline fun getViewModel( MockzillaUiKoinContext.koin.get(qualifier = qualifier, parameters = parameters) } -actual fun evictDesktopViewModelsForKey(device: Device) = Unit +actual fun evictDesktopViewModelsForKey(device: Device, keyPrefix: String?) = Unit diff --git a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt index 12a84e90e..63cffe4fe 100644 --- a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt +++ b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/MobileAppRoot.kt @@ -207,9 +207,9 @@ private fun ConnectedState( ) { EndpointDetailsWidget( device = currentState.activeDevice.device, - activeEndpoint = EndpointConfiguration.Key( - backStackEntry.toRoute().key, - ), + activeEndpoint = backStackEntry.toRoute().key?.let { + EndpointConfiguration.Key(it) + }, onCreatePreset = { navController.navigate(Destination.CreateEditPreset(it.raw, true)) }, @@ -225,7 +225,7 @@ private fun ConnectedState( EndpointsWidget( device = currentState.activeDevice.device, onEndpointClicked = { - navController.navigate(Destination.EndpointDetails(it.raw)) + navController.navigate(Destination.EndpointDetails(it?.raw)) }, onGlobalControlsClicked = { navController.navigate(Destination.GlobalControls) diff --git a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/utils/Destination.kt b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/utils/Destination.kt index 92f435f3c..ab465a141 100644 --- a/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/utils/Destination.kt +++ b/mockzilla-management-ui/mockzilla-mobile-ui/src/commonMain/kotlin/com/apadmi/mockzilla/mobile/ui/utils/Destination.kt @@ -27,5 +27,5 @@ internal sealed class Destination { * @property key */ @Serializable - internal data class EndpointDetails(val key: String) : Destination() + internal data class EndpointDetails(val key: String?) : Destination() }