From f050eedca9b9b94133290288cad9577c7a416b26 Mon Sep 17 00:00:00 2001 From: Maxime MICHEL Date: Wed, 22 Jul 2026 17:57:52 +0200 Subject: [PATCH 1/3] :memo: Fix v0.1.4 KDoc and docs for Section.NETWORK, color properties, NetworkMockResourceLoader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Section.kt: add NETWORK to all KDoc bulleted lists (Section Organization, Default Icons, Icon Mapping); add KDoc to containerColor and contentColor extension properties which had none - Module.kt: add Section.NETWORK to the Available Sections KDoc list - theming.md: fix containerColour/contentColour typos → containerColor/contentColor; fix invalid MaterialTheme usage in non-composable context (use Color literals); add section-derived defaults table (v0.1.4+); replace Dokka placeholder link - custom-modules.md: add containerColor/contentColor to Module interface listing; replace Dokka placeholder link - networkmock.md: replace Dokka placeholder link; remove redundant trailing line - networkmock-core.md: add NetworkMockResourceLoader section (added in v0.1.3) with signature, basic usage, DI example, and rationale Co-Authored-By: Claude Opus 4.6 (1M context) --- .../com/worldline/devview/core/Module.kt | 1 + .../com/worldline/devview/core/Section.kt | 23 +++++++++++ docs/guides/theming.md | 25 ++++++++--- docs/modules/custom-modules.md | 4 +- docs/modules/networkmock-core.md | 41 +++++++++++++++++++ docs/modules/networkmock.md | 6 +-- 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/devview/src/commonMain/kotlin/com/worldline/devview/core/Module.kt b/devview/src/commonMain/kotlin/com/worldline/devview/core/Module.kt index 72acb48..5a4e471 100644 --- a/devview/src/commonMain/kotlin/com/worldline/devview/core/Module.kt +++ b/devview/src/commonMain/kotlin/com/worldline/devview/core/Module.kt @@ -149,6 +149,7 @@ public interface Module { * ## Available Sections * - [Section.SETTINGS]: Configuration and app information * - [Section.FEATURES]: Feature flags and development tools + * - [Section.NETWORK]: Network monitoring and mocking * - [Section.LOGGING]: Debugging, analytics, and logging * - [Section.CUSTOM]: Application-specific modules * diff --git a/devview/src/commonMain/kotlin/com/worldline/devview/core/Section.kt b/devview/src/commonMain/kotlin/com/worldline/devview/core/Section.kt index dd8e91d..26ecaae 100644 --- a/devview/src/commonMain/kotlin/com/worldline/devview/core/Section.kt +++ b/devview/src/commonMain/kotlin/com/worldline/devview/core/Section.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.vector.ImageVector * ## Section Organization * - [SETTINGS]: Configuration and app information modules * - [FEATURES]: Feature flag and development tools + * - [NETWORK]: Network monitoring, logging, and mocking tools * - [LOGGING]: Debugging, analytics, and logging tools * - [CUSTOM]: Application-specific custom modules * @@ -35,6 +36,7 @@ import androidx.compose.ui.graphics.vector.ImageVector * Each section has a default icon accessible via the [icon] extension property: * - SETTINGS → Settings icon (gear) * - FEATURES → DeveloperMode icon + * - NETWORK → NetworkCheck icon * - LOGGING → FormatListNumbered icon (list) * - CUSTOM → Extension icon (puzzle piece) * @@ -102,6 +104,7 @@ public enum class Section { * ## Icon Mapping * - [Section.SETTINGS] → Settings (gear icon) * - [Section.FEATURES] → DeveloperMode icon + * - [Section.NETWORK] → NetworkCheck icon * - [Section.LOGGING] → FormatListNumbered (list icon) * - [Section.CUSTOM] → Extension (puzzle piece icon) * @@ -129,6 +132,16 @@ public val Section.icon: ImageVector Section.CUSTOM -> Icons.Rounded.Extension } +/** + * Extension property providing the default container (background) color for each section. + * + * Returns a brand-palette color used as the background of module icon containers + * on the DevView home screen. Modules inherit this via [Module.containerColor] + * by default but can override it. + * + * @see Section + * @see Module.containerColor + */ public val Section.containerColor: Color get() = when (this) { Section.SETTINGS -> Color(color = 0xFF545AAE) @@ -138,5 +151,15 @@ public val Section.containerColor: Color Section.CUSTOM -> Color(color = 0xFFA03CBC) } +/** + * Extension property providing the default content (foreground) color for each section. + * + * Returns a light tint used for the icon drawn inside the section's container. + * Modules inherit this via [Module.contentColor] by default but can override it. + * All sections currently share the same content color (`0xFFE8E9F7`). + * + * @see Section + * @see Module.contentColor + */ public val Section.contentColor: Color get() = Color(color = 0xFFE8E9F7) diff --git a/docs/guides/theming.md b/docs/guides/theming.md index 372cc83..ce0a1ba 100644 --- a/docs/guides/theming.md +++ b/docs/guides/theming.md @@ -12,16 +12,31 @@ MaterialTheme.colorScheme.primary MaterialTheme.typography.bodyLarge ``` -## Customising Colours -Override colours for modules or components as needed: +## Customizing Colors +Override colors for modules or components as needed: ```kotlin object MyModule : Module { - override val containerColour = MaterialTheme.colorScheme.secondary - override val contentColour = MaterialTheme.colorScheme.onSecondary + override val containerColor: Color = Color(0xFFFF5722) // Deep Orange + override val contentColor: Color = Color.White // ...other properties... } ``` +### Section-Derived Defaults (v0.1.4+) + +Since v0.1.4, `containerColor` and `contentColor` on `Module` default to the +module's `Section` palette colors. Each section has its own brand-palette tint: + +| Section | Container Color | Content Color | +|---------|----------------|---------------| +| `SETTINGS` | `#545AAE` | `#E8E9F7` | +| `FEATURES` | `#764DD0` | `#E8E9F7` | +| `NETWORK` | `#5571B2` | `#E8E9F7` | +| `LOGGING` | `#6970CA` | `#E8E9F7` | +| `CUSTOM` | `#A03CBC` | `#E8E9F7` | + +You only need to override `containerColor`/`contentColor` if your module requires a color outside its section's default. + ## Customising Typography Use your app's typography settings in custom modules: ```kotlin @@ -50,4 +65,4 @@ override val icon = Icons.Default.Build - Explore [Examples](../examples/index.md) for themed module samples. ## API Reference -> _[API reference available via Dokka. Add direct link here when available.]_ +> _[Dokka API Reference](../api/index.html)_ diff --git a/docs/modules/custom-modules.md b/docs/modules/custom-modules.md index 9d485ec..45ccd73 100644 --- a/docs/modules/custom-modules.md +++ b/docs/modules/custom-modules.md @@ -15,6 +15,8 @@ interface Module { val moduleName: String // defaults to class simple name val section: Section val icon: ImageVector // defaults to section icon + val containerColor: Color // defaults to section container color + val contentColor: Color // defaults to section content color val subtitle: String? // optional description text, defaults to null val destinations: PersistentMap, DestinationMetadata> val entryDestination: NavKey @@ -148,4 +150,4 @@ See [Examples section](../examples/index.md) for complete custom module examples - Verify your colour and icon definitions are valid and supported by Compose. ## API Reference -> _[API reference available via Dokka. Add direct link here when available.]_ +> _[Dokka API Reference](../api/devview/com.worldline.devview.core/-module/index.html)_ diff --git a/docs/modules/networkmock-core.md b/docs/modules/networkmock-core.md index 25b7cf2..136cf4c 100644 --- a/docs/modules/networkmock-core.md +++ b/docs/modules/networkmock-core.md @@ -88,6 +88,47 @@ State is persisted via `MockStateRepository`: `EndpointMockState` is serialized as `{"type":"network"}` (pass-through) or `{"type":"mock","responseFile":"getUser-200.json"}`. +## NetworkMockResourceLoader + +_Added in v0.1.3._ + +`NetworkMockResourceLoader` is a `fun interface` that abstracts how mock resource bytes are loaded from a path. It exists to support DI-friendly architectures where the mock JSON files live in a different Gradle module than the one constructing `NetworkMock`. + +```kotlin +public fun interface NetworkMockResourceLoader { + public suspend fun load(path: String): ByteArray +} +``` + +### Basic Usage + +```kotlin +NetworkMock( + resourceLoader = NetworkMockResourceLoader { path -> Res.readBytes(path) } +) +``` + +### DI Usage (Koin example) + +In the module that owns the mock resource files: +```kotlin +single { + NetworkMockResourceLoader { Res.readBytes(it) } +} +``` + +In the presentation module where `NetworkMock` is constructed: +```kotlin +val loader = koinInject() +val modules = rememberModules { + module(NetworkMock(resourceLoader = loader)) +} +``` + +### Why This Exists + +Before v0.1.3, `NetworkMock` accepted a raw `suspend (String) -> ByteArray` lambda. This worked but was impossible to register as a typed binding in DI frameworks (Koin, Hilt) across Gradle module boundaries. The named `NetworkMockResourceLoader` type solves this. + ## Related Modules - [NetworkMock](networkmock.md): UI layer and module entry point. diff --git a/docs/modules/networkmock.md b/docs/modules/networkmock.md index d4c0a2f..ad17d0c 100644 --- a/docs/modules/networkmock.md +++ b/docs/modules/networkmock.md @@ -84,8 +84,4 @@ val client = HttpClient(OkHttp) { - [Creating Custom Modules](custom-modules.md) ## API Reference -> _[API reference available via Dokka. Add direct link here when available.]_ - ---- - -*API reference is available via Dokka or in your IDE.* +> _[Dokka API Reference](../api/devview-networkmock/index.html)_ From 184a0bc967561a03c9dd3cff83860eb1a3fda1d7 Mon Sep 17 00:00:00 2001 From: Maxime MICHEL Date: Wed, 22 Jul 2026 17:58:13 +0200 Subject: [PATCH 2/3] :memo: Add documentation hygiene rules to CLAUDE.md and update-docs skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md: new Documentation Hygiene section — any metalava api.txt change must be accompanied by KDoc and doc site updates; checklist covers source KDoc, module pages, theming guide, custom-modules guide, and code samples - update-docs skill: renamed to "4 coordinated changes", added step 4 for verifying KDoc is in sync (enum entries, extension properties, bulleted lists); added table row for changed enum entries/extension properties Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/update-docs.md | 14 +++++++++++++- CLAUDE.md | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.claude/skills/update-docs.md b/.claude/skills/update-docs.md index f5339d1..fc164c1 100644 --- a/.claude/skills/update-docs.md +++ b/.claude/skills/update-docs.md @@ -5,7 +5,7 @@ description: Update Zensical and Dokka documentation when adding or changing a D You are updating the DevView documentation. The docs site is built with Zensical (an MkDocs fork) and API docs are generated with Dokka. Three files must stay synchronized — missing any one means the new module silently doesn't appear in the published site. -## The 3 coordinated changes +## The 4 coordinated changes ### 1. Create or update `docs/modules/.md` @@ -98,6 +98,17 @@ The project accessor name follows Gradle's camelCase convention from the module' - `devview-myfeature` → `projects.devviewMyfeature` - `devview-myfeature-core` → `projects.devviewMyfeatureCore` +### 4. Verify KDoc is in sync with the actual API + +After making doc site changes, also verify that **source-level KDoc** matches the current API: + +- Every public enum entry has its own KDoc block. +- Extension properties on public types have KDoc (not just the type itself). +- Bulleted lists in KDoc that enumerate enum entries, sections, or property names are complete — no missing items. +- Code examples in KDoc use correct property names and types. + +Run `git diff /api/api.txt` to see what changed in the metalava surface, then verify each changed symbol has up-to-date KDoc. + ## Doc build pipeline The full pipeline (from `scripts/build_docs.sh`): @@ -127,3 +138,4 @@ The output is in `site/`. If you don't have Python/Zensical, at minimum verify: | New Ktor plugin variant | New `docs/modules/-ktor.md` + zensical.toml + dokka | | Renamed or removed public API | Update docs + check for stale examples | | New release | `CHANGELOG.md` auto-copies via build script | +| Changed enum entries or extension properties | Update KDoc lists that enumerate them (e.g. Section, Module) | diff --git a/CLAUDE.md b/CLAUDE.md index 14282b5..57b10f9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -132,3 +132,15 @@ Library group: `com.worldline.devview`. Version and Sonatype config are in `grad ## Changelog `CHANGELOG.md` at the repo root is the single source of truth. `docs/changelog.md` is built from it automatically — only edit the root file. + +## Documentation Hygiene + +Any change to the public API surface (anything tracked by metalava in `/api/api.txt`) **must** be accompanied by documentation updates in the same PR. Before merging, check: + +- **KDoc in source**: Every public class, property, function, and enum entry must have KDoc. Bulleted lists that enumerate enum entries or properties (e.g. `## Available Sections`, `## Icon Mapping`) must be kept complete. +- **`docs/modules/.md`**: Update if the module's public API changed. +- **`docs/guides/theming.md`**: Update if colors, icons, or visual appearance APIs changed. +- **`docs/modules/custom-modules.md`** and **`docs/guides/module-development.md`**: Update if the `Module` interface or `Section` enum changed. +- **Code samples in docs**: Verify property names, types, and constructor signatures in Markdown code blocks match the actual API — no stale examples. + +When the metalava `api.txt` diff in a PR is non-empty, the PR must include corresponding doc page updates (or explicitly note why none are needed). From 7b3f51b91afa699223ed6557d244f7e1b3ee1c67 Mon Sep 17 00:00:00 2001 From: Maxime MICHEL Date: Wed, 22 Jul 2026 18:04:08 +0200 Subject: [PATCH 3/3] :wrench: Fail pre-commit if detekt auto-corrects; apply pending corrections detekt runs with autoCorrect=true, so the pre-commit hook was silently rewriting files and leaving the corrections as unstaged diffs. Added `git diff --exit-code` after detektFull so the hook fails when auto- corrections occur, forcing them to be reviewed and re-staged before the commit lands. Also commits the ktlint formatting fixes that detekt had already applied to the UI refresh files (import ordering, indentation, trailing commas). Co-Authored-By: Claude Opus 4.6 (1M context) --- .pre-commit-config.yaml | 2 +- .../analytics/components/AnalyticsLogItem.kt | 100 +++++++------- .../devview/featureflip/FeatureFlipScreen.kt | 2 +- .../featureflip/components/FeatureItem.kt | 3 +- .../networkmock/NetworkMockEndpointScreen.kt | 6 +- .../devview/networkmock/NetworkMockScreen.kt | 2 +- .../networkmock/components/EndpointCard.kt | 3 +- .../components/EndpointHeaderCard.kt | 3 +- .../kotlin/com/worldline/devview/DevView.kt | 3 +- .../com/worldline/devview/HomeScreen.kt | 129 +++++++++--------- .../worldline/devview/sample/DevViewApp.kt | 2 +- 11 files changed, 128 insertions(+), 127 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5622fa2..bd54dca 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: hooks: - id: detekt name: Detekt - entry: bash ./gradlew detektFull -Pandroidx.baselineprofile.skipgeneration + entry: bash -c './gradlew detektFull -Pandroidx.baselineprofile.skipgeneration && git diff --exit-code' language: system pass_filenames: false verbose: true diff --git a/devview-analytics/src/commonMain/kotlin/com/worldline/devview/analytics/components/AnalyticsLogItem.kt b/devview-analytics/src/commonMain/kotlin/com/worldline/devview/analytics/components/AnalyticsLogItem.kt index e4a06b8..5f41f21 100644 --- a/devview-analytics/src/commonMain/kotlin/com/worldline/devview/analytics/components/AnalyticsLogItem.kt +++ b/devview-analytics/src/commonMain/kotlin/com/worldline/devview/analytics/components/AnalyticsLogItem.kt @@ -65,61 +65,61 @@ internal fun AnalyticsLogItem(analyticsLog: AnalyticsLog, modifier: Modifier = M .fillMaxHeight() .background(color = categoryColor) ) - Row( - modifier = Modifier - .weight(weight = 1f) - .padding(start = 13.dp, end = 16.dp), - horizontalArrangement = Arrangement.spacedBy(space = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier.weight(weight = 1f), - verticalArrangement = Arrangement.spacedBy(space = 2.dp) + Row( + modifier = Modifier + .weight(weight = 1f) + .padding(start = 13.dp, end = 16.dp), + horizontalArrangement = Arrangement.spacedBy(space = 16.dp), + verticalAlignment = Alignment.CenterVertically ) { - Text( - modifier = Modifier.testTag(tag = "analytics_log_tag_${analyticsLog.tag}"), - text = analyticsLog.tag, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.titleMedium.copy( - fontWeight = FontWeight.Bold + Column( + modifier = Modifier.weight(weight = 1f), + verticalArrangement = Arrangement.spacedBy(space = 2.dp) + ) { + Text( + modifier = Modifier.testTag(tag = "analytics_log_tag_${analyticsLog.tag}"), + text = analyticsLog.tag, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Bold + ) ) - ) - Text( - modifier = Modifier.testTag( - tag = "analytics_log_screen_class_${analyticsLog.screenClass}" - ), - text = analyticsLog.screenClass, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } + Text( + modifier = Modifier.testTag( + tag = "analytics_log_screen_class_${analyticsLog.screenClass}" + ), + text = analyticsLog.screenClass, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } - Column( - horizontalAlignment = Alignment.End, - verticalArrangement = Arrangement.spacedBy(space = 4.dp) - ) { - Text( - modifier = Modifier.testTag( - tag = "analytics_log_timestamp_${analyticsLog.formattedTimestamp}" - ), - text = analyticsLog.formattedTimestamp, - style = MaterialTheme.typography.bodyMedium.copy( - fontWeight = FontWeight.Medium - ), - color = MaterialTheme.colorScheme.onSurface - ) - CategoryChip( - modifier = Modifier.testTag( - tag = "analytics_log_category_chip_${analyticsLog.type.category}" - ), - category = analyticsLog.type.category - ) + Column( + horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy(space = 4.dp) + ) { + Text( + modifier = Modifier.testTag( + tag = "analytics_log_timestamp_${analyticsLog.formattedTimestamp}" + ), + text = analyticsLog.formattedTimestamp, + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Medium + ), + color = MaterialTheme.colorScheme.onSurface + ) + CategoryChip( + modifier = Modifier.testTag( + tag = "analytics_log_category_chip_${analyticsLog.type.category}" + ), + category = analyticsLog.type.category + ) + } } } - } } @Preview(locale = "en") diff --git a/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/FeatureFlipScreen.kt b/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/FeatureFlipScreen.kt index e4f8566..e60321a 100644 --- a/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/FeatureFlipScreen.kt +++ b/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/FeatureFlipScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done import androidx.compose.material.icons.rounded.Lightbulb import androidx.compose.material.icons.rounded.Search -import androidx.compose.ui.text.style.TextAlign import androidx.compose.material3.FilterChip import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -43,6 +42,7 @@ import androidx.compose.runtime.toMutableStateMap import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp diff --git a/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/components/FeatureItem.kt b/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/components/FeatureItem.kt index d1b4079..0dd329d 100644 --- a/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/components/FeatureItem.kt +++ b/devview-featureflip/src/commonMain/kotlin/com/worldline/devview/featureflip/components/FeatureItem.kt @@ -102,8 +102,7 @@ internal fun FeatureItem( .background( color = MaterialTheme.colorScheme.surfaceContainerHigh, shape = MaterialTheme.shapes.extraSmall - ) - .padding(horizontal = 6.dp, vertical = 2.dp) + ).padding(horizontal = 6.dp, vertical = 2.dp) ) { Text( modifier = Modifier.testTag(tag = "feature_type_${feature.name}"), diff --git a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockEndpointScreen.kt b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockEndpointScreen.kt index b5ca1f4..a2b77c3 100644 --- a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockEndpointScreen.kt +++ b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockEndpointScreen.kt @@ -10,19 +10,18 @@ import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row 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.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowUpward import androidx.compose.material.icons.rounded.TouchApp -import androidx.compose.ui.Alignment import androidx.compose.material3.CardDefaults import androidx.compose.material3.ElevatedCard import androidx.compose.material3.FabPosition @@ -38,6 +37,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter diff --git a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockScreen.kt b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockScreen.kt index 3111905..84ce96f 100644 --- a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockScreen.kt +++ b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/NetworkMockScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.material3.Tab import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember @@ -31,6 +30,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.worldline.devview.networkmock.components.EmptyState import com.worldline.devview.networkmock.components.EndpointCard import com.worldline.devview.networkmock.components.ErrorState diff --git a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointCard.kt b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointCard.kt index 529220f..71a9032 100644 --- a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointCard.kt +++ b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointCard.kt @@ -77,8 +77,7 @@ internal fun EndpointCard( .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(size = 4.dp) - ) - .padding(horizontal = 6.dp, vertical = 2.dp) + ).padding(horizontal = 6.dp, vertical = 2.dp) ) { Text( modifier = Modifier.testTag( diff --git a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointHeaderCard.kt b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointHeaderCard.kt index 6d3a3f5..eda0053 100644 --- a/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointHeaderCard.kt +++ b/devview-networkmock/src/commonMain/kotlin/com/worldline/devview/networkmock/components/EndpointHeaderCard.kt @@ -55,8 +55,7 @@ internal fun EndpointHeaderCard(endpoint: EndpointUiModel, modifier: Modifier = .background( color = MaterialTheme.colorScheme.primaryContainer, shape = RoundedCornerShape(size = 4.dp) - ) - .padding(horizontal = 6.dp, vertical = 2.dp) + ).padding(horizontal = 6.dp, vertical = 2.dp) ) { Text( text = endpoint.descriptor.config.method, diff --git a/devview/src/commonMain/kotlin/com/worldline/devview/DevView.kt b/devview/src/commonMain/kotlin/com/worldline/devview/DevView.kt index fb446ab..25c5fe3 100644 --- a/devview/src/commonMain/kotlin/com/worldline/devview/DevView.kt +++ b/devview/src/commonMain/kotlin/com/worldline/devview/DevView.kt @@ -14,7 +14,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar -import androidx.compose.ui.text.font.FontWeight import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect @@ -27,8 +26,8 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.text.font.FontWeight import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.rememberNavBackStack diff --git a/devview/src/commonMain/kotlin/com/worldline/devview/HomeScreen.kt b/devview/src/commonMain/kotlin/com/worldline/devview/HomeScreen.kt index 9cae7bc..b11b39a 100644 --- a/devview/src/commonMain/kotlin/com/worldline/devview/HomeScreen.kt +++ b/devview/src/commonMain/kotlin/com/worldline/devview/HomeScreen.kt @@ -12,16 +12,14 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.layout.ContentScale -import org.jetbrains.compose.resources.painterResource import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview @@ -33,6 +31,7 @@ import com.worldline.devview.internal.HasTitle import com.worldline.devview.internal.components.ModuleItem import com.worldline.devview.internal.components.ModulePosition import kotlinx.serialization.Serializable +import org.jetbrains.compose.resources.painterResource /** * Internal composable that displays the DevView home screen with all modules. @@ -97,7 +96,13 @@ internal fun HomeScreen( } } - val watermarkAlpha = if (MaterialTheme.colorScheme.background.luminance() < 0.5f) 0.38f else 0.07f + val watermarkAlpha = if (MaterialTheme.colorScheme.background.luminance() < + 0.5f + ) { + 0.38f + } else { + 0.07f + } Scaffold( modifier = modifier @@ -109,73 +114,73 @@ internal fun HomeScreen( modifier = Modifier .fillMaxSize() .alpha(alpha = watermarkAlpha), - contentScale = ContentScale.Fit, + contentScale = ContentScale.Fit ) - LazyColumn( - modifier = Modifier - .fillMaxSize() - ) { - item { - Spacer( - modifier = Modifier.height( - height = paddingValues.calculateTopPadding() - ) - ) - } - - mappedModules.entries.forEachIndexed { - mappedModulesIndex, - (section, modulesPerSection) - -> - stickyHeader( - key = section - ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(start = 16.dp + 16.dp) - .padding(vertical = 8.dp) - .testTag(tag = "section_header_${section.name}"), - text = section.name.replace(oldChar = '_', newChar = ' '), - style = MaterialTheme.typography.bodySmallEmphasized.copy( - color = MaterialTheme.colorScheme.primary, - fontWeight = FontWeight.Medium + LazyColumn( + modifier = Modifier + .fillMaxSize() + ) { + item { + Spacer( + modifier = Modifier.height( + height = paddingValues.calculateTopPadding() ) ) } - itemsIndexed( - items = modulesPerSection, - key = { _, module -> module.moduleName }, - contentType = { _, _ -> "Module" } - ) { index, module -> - ModuleItem( - module = module, - position = when { - modulesPerSection.size == 1 -> ModulePosition.SINGLE - index == 0 -> ModulePosition.FIRST - index == modulesPerSection.lastIndex -> ModulePosition.LAST - else -> ModulePosition.MIDDLE - }, - openModule = openModule - ) - } - if (mappedModulesIndex != mappedModules.values.toList().lastIndex) { - item { - Spacer( - modifier = Modifier.height(height = 16.dp) + + mappedModules.entries.forEachIndexed { + mappedModulesIndex, + (section, modulesPerSection) + -> + stickyHeader( + key = section + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp + 16.dp) + .padding(vertical = 8.dp) + .testTag(tag = "section_header_${section.name}"), + text = section.name.replace(oldChar = '_', newChar = ' '), + style = MaterialTheme.typography.bodySmallEmphasized.copy( + color = MaterialTheme.colorScheme.primary, + fontWeight = FontWeight.Medium + ) + ) + } + itemsIndexed( + items = modulesPerSection, + key = { _, module -> module.moduleName }, + contentType = { _, _ -> "Module" } + ) { index, module -> + ModuleItem( + module = module, + position = when { + modulesPerSection.size == 1 -> ModulePosition.SINGLE + index == 0 -> ModulePosition.FIRST + index == modulesPerSection.lastIndex -> ModulePosition.LAST + else -> ModulePosition.MIDDLE + }, + openModule = openModule ) } + if (mappedModulesIndex != mappedModules.values.toList().lastIndex) { + item { + Spacer( + modifier = Modifier.height(height = 16.dp) + ) + } + } } - } - item { - Spacer( - modifier = Modifier.height( - height = paddingValues.calculateBottomPadding() + item { + Spacer( + modifier = Modifier.height( + height = paddingValues.calculateBottomPadding() + ) ) - ) + } } } - } } } diff --git a/sample/shared/src/commonMain/kotlin/com/worldline/devview/sample/DevViewApp.kt b/sample/shared/src/commonMain/kotlin/com/worldline/devview/sample/DevViewApp.kt index 6aed59b..b12f565 100644 --- a/sample/shared/src/commonMain/kotlin/com/worldline/devview/sample/DevViewApp.kt +++ b/sample/shared/src/commonMain/kotlin/com/worldline/devview/sample/DevViewApp.kt @@ -4,13 +4,13 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme -import androidx.compose.ui.graphics.Color import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Color import com.worldline.devview.DevView import com.worldline.devview.analytics.Analytics import com.worldline.devview.analytics.AnalyticsLogger