Skip to content

feat(adaptive-window): add salt-adaptive-window module - #59

Draft
Moriafly wants to merge 1 commit into
mainfrom
feat/salt-adaptive-window
Draft

Moriafly wants to merge 1 commit into
mainfrom
feat/salt-adaptive-window

Conversation

@Moriafly

Copy link
Copy Markdown
Owner

Introduce a new KMP module salt-adaptive-window under package com.moriafly.salt.adaptive.window that lets code determine the device screen form factor and the available window size class at runtime.

Public API:

  • DeviceFormFactor (Phone, Tablet, Foldable, Desktop, Car, Unknown)
  • WindowSizeClass (Compact, Medium, Expanded) at the Material 3 breakpoints <600dp / 600-840dp / >=840dp
  • SaltAdaptiveWindow(formFactor, sizeClass)
  • LocalSaltAdaptiveWindow for ambient access from deeply nested code
  • currentSaltAdaptiveWindow() as the platform expect/actual source

Why a separate module rather than reusing material3-adaptive: Google's androidx.compose.material3.adaptive is Android-only and deliberately has no device-type concept, but this library also targets desktop JVM and iOS, where "desktop" is a real distinct form factor. DeviceFormFactor is therefore documented as an interaction signal only (touch vs pointer), and layout breakpoints must be driven by sizeClass, because a tablet in split-screen can still have a Compact window.

LocalSaltAdaptiveWindow defaults to error(...) instead of a silent fallback, matching LocalSaltWindowInfo in ui2: reading it without a provider is a wiring mistake and should fail loudly rather than report a wrong form factor. The provider wiring is intentionally not part of this change.

Naming follows the current Google convention of a current prefix for a @composable that recomputes on every recomposition rather than caching, so no remember is claimed that does not happen.

Platform detection:

  • Android: PackageManager.FEATURE_AUTOMOTIVE for car and FEATURE_SENSOR_HINGE_ANGLE for foldable, both behind SDK_INT guards (minSdk 23), plus the platform's own sw600dp tablet qualifier. The foldable check is documented as a heuristic, since without a Jetpack WindowManager dependency the hinge angle sensor is the only signal the platform exposes.
  • Desktop: constant Desktop form factor, size class from LocalWindowInfo so it tracks window resizes.
  • iOS: UIDevice.userInterfaceIdiom mapped to Phone/Tablet/Car, size class read from the window rather than the screen so it stays correct under iPad Split View and Stage Manager.

Validation: compileAndroidMain, compileKotlinDesktop, compileKotlinIosArm64 and compileKotlinIosSimulatorArm64 all pass.

Introduce a new KMP module `salt-adaptive-window` under package
`com.moriafly.salt.adaptive.window` that lets code determine the device
screen form factor and the available window size class at runtime.

Public API:
- `DeviceFormFactor` (Phone, Tablet, Foldable, Desktop, Car, Unknown)
- `WindowSizeClass` (Compact, Medium, Expanded) at the Material 3
  breakpoints <600dp / 600-840dp / >=840dp
- `SaltAdaptiveWindow(formFactor, sizeClass)`
- `LocalSaltAdaptiveWindow` for ambient access from deeply nested code
- `currentSaltAdaptiveWindow()` as the platform `expect`/`actual` source

Why a separate module rather than reusing material3-adaptive: Google's
`androidx.compose.material3.adaptive` is Android-only and deliberately has
no device-type concept, but this library also targets desktop JVM and iOS,
where "desktop" is a real distinct form factor. `DeviceFormFactor` is
therefore documented as an interaction signal only (touch vs pointer), and
layout breakpoints must be driven by `sizeClass`, because a tablet in
split-screen can still have a Compact window.

`LocalSaltAdaptiveWindow` defaults to `error(...)` instead of a silent
fallback, matching `LocalSaltWindowInfo` in ui2: reading it without a
provider is a wiring mistake and should fail loudly rather than report a
wrong form factor. The provider wiring is intentionally not part of this
change.

Naming follows the current Google convention of a `current` prefix for a
@composable that recomputes on every recomposition rather than caching, so
no `remember` is claimed that does not happen.

Platform detection:
- Android: `PackageManager.FEATURE_AUTOMOTIVE` for car and
  `FEATURE_SENSOR_HINGE_ANGLE` for foldable, both behind SDK_INT guards
  (minSdk 23), plus the platform's own sw600dp tablet qualifier. The
  foldable check is documented as a heuristic, since without a Jetpack
  WindowManager dependency the hinge angle sensor is the only signal the
  platform exposes.
- Desktop: constant `Desktop` form factor, size class from
  `LocalWindowInfo` so it tracks window resizes.
- iOS: `UIDevice.userInterfaceIdiom` mapped to Phone/Tablet/Car, size
  class read from the window rather than the screen so it stays correct
  under iPad Split View and Stage Manager.

Validation: `compileAndroidMain`, `compileKotlinDesktop`,
`compileKotlinIosArm64` and `compileKotlinIosSimulatorArm64` all pass.
@Moriafly
Moriafly requested a review from GaodaGG September 23, 2026 13:16
@Moriafly
Moriafly marked this pull request as draft September 23, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants