Skip to content

add collision-free StartSideRail and EndSideRail adaptive components - #652

Draft
Kimblebee wants to merge 2 commits into
kim/adaptive/capture-slotsfrom
kim/adaptive/side-rails
Draft

Kimblebee wants to merge 2 commits into
kim/adaptive/capture-slotsfrom
kim/adaptive/side-rails

Conversation

@Kimblebee

Copy link
Copy Markdown
Collaborator

Stacked PR: Based on kim/adaptive/capture-slots #651

Summary

Adds the StartSideRail and EndSideRail adaptive vertical chrome containers on top of the CaptureSlots foundation from kim/adaptive/capture-slots. Four of the five posture scaffolds in kim/adaptive/layouts (FoldableLayout, TabletPortraitLayout, TabletLandscapeLayout, and CompactShortLayout) rely on vertical start/end rails rather than horizontal top/bottom bars. Factoring these rails into their own branch isolates collision-free 3-band vertical measurement, portrait-tablet thumb-zone biasing (centerVerticalFraction), 360dp compact-height fitting, per-slot Orientation.Vertical / isCompact scoping, and LTR/RTL vertical ordering invariants into a focused, unit-tested slice.

Key Changes

  • CaptureSideRails.kt (:ui:components:capture):
    • Adds StartSideRail (START_SIDE_RAIL_TAG), stacking slots.topBar (top), slots.zoomControls (center), and slots.quickSettingsButton (bottom) inside per-control OverlapAwareCaptureSlot(orientation = Orientation.Vertical, isCompact = isCompactHeight) scopes.
    • Adds EndSideRail (END_SIDE_RAIL_TAG), hosting optional slots.elapsedTimeDisplay (top, gated by showElapsedTimeInRail), VerticalRailShutterCluster (flipCameraButton -> captureButton -> imageWell in center), and slots.captureModeToggle (bottom).
    • Adds VerticalRailLayout and VerticalRailShutterCluster custom Layout composables plus MinSideRailWidth = 72.dp and 10 LTR/RTL/posture @Preview functions.
  • TestTags.kt:
    • Adds START_SIDE_RAIL_TAG ("rail_capture_start") and END_SIDE_RAIL_TAG ("rail_capture_end").
  • CaptureSideRailsTest.kt:
    • Adds 7 Robolectric Compose UI tests covering LTR/RTL coordinate invariance, 360dp compact-height non-clipping/non-overlap, omitted-slot collapsing, 1280dp (0.70f) tablet-portrait thumb-zone clamping, and live PreviewOverlaySlotScope propagation.

Technical Notes

  • Edge-First Bounded Measurement (VerticalRailLayout): Under bounded height, measures Top first, Bottom second, and passes the remaining collision-free height (innerHeight - topReserved - bottomReserved) to Center. Empty (0px-height) slots filter to null so omitted sections reserve neither height nor minSectionGap (12.dp standard / 8.dp compact).
  • Clamped Thumb-Zone Bias (centerVerticalFraction): Places the Center band's midpoint at railHeight * centerVerticalFraction.coerceIn(0f, 1f) (0.50f default; 0.70f for 1280dp portrait tablet lower-grip reach) and clamps its top coordinate within [minCenterY, maxCenterY] so it can never collide with Top or Bottom sections.
  • Shutter Priority & Elastic Gaps (VerticalRailShutterCluster): Under bounded height, measures Capture before FlipCamera and ImageWell so the primary shutter retains height priority in micro-heights, then places active controls in strict FlipCamera -> Capture -> ImageWell order with inter-control gaps (48.dp standard / 20.dp compact) compressing proportionally (min(targetTotalGapPx, maxAllowedGapPx)) when height-constrained.
  • RTL Invariance Without Breaking Child Locale: Uses explicit placeable.place(x, y) coordinates and enum layoutIds rather than overriding LocalLayoutDirection, keeping vertical coordinates identical in LTR and RTL while child slots retain the caller's LocalLayoutDirection for localized text and icons.
  • Per-Slot Overlap & Axis Scoping: Wraps each individual slot (including each shutter-cluster item) in its own OverlapAwareCaptureSlot(orientation = Orientation.Vertical, isCompact = isCompactHeight), giving every control independent viewfinder-overlap contrast detection plus Orientation.Vertical and isCompact layout hints.

Not Included Yet

  • Comes later in this series:
    • Embedding the rails into FoldableLayout, TabletPortraitLayout, TabletLandscapeLayout, and CompactShortLayout (kim/adaptive/layouts).
    • Wiring live CaptureScaffold controls and MinSideRailWidth carousel clearance (kim/adaptive/layout-orchestrator).
    • Vertical leaf components (#649 indicator pill, #635 mode toggle, #644 zoom bar RTL polish).
    • Upright content gravity (kim/adaptive/content-gravity).
  • Open follow-ups:
    • Right-to-left behavior is not finalized: Keeping side rails on their physical sides is an interim default; ordering inside vertical components (zoom stops, status indicators) and whether the full layout should mirror remain open for follow-up polish.
  • Intentional limits:
    • Insets: Rails take explicit padding and do not read WindowInsets; system bar, hinge, and cutout handling belongs to the hosting layouts.

Testing

  • CaptureSideRailsTest (Robolectric Compose UI suite):
    • Strict top-to-bottom slot ordering, < 0.5dp LTR/RTL vertical coordinate parity, and child LocalLayoutDirection inheritance for both StartSideRail (3 slots) and EndSideRail (5 slots).
    • 360dp compact-height stress test (isCompactHeight = true, recording timer + image well active) verifying zero clipping (getBoundsInRoot == getUnclippedBoundsInRoot) and zero overlap across all 8 controls.
    • Clean space collapsing and cluster re-centering when optional slots (elapsedTimeDisplay, imageWell, topBar, quickSettingsButton) are omitted.
    • 1280dp tablet-portrait thumb-zone test (centerVerticalFraction = 0.70f, custom posture padding) verifying 896dp midpoint alignment and >= 16dp bottom-control clearance.
    • Reactive PreviewOverlaySlotScope Orientation.Vertical and isCompact propagation into slot composables.

@Kimblebee
Kimblebee changed the base branch from main to kim/adaptive/capture-slots November 13, 2026 00:46

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces adaptive side rails (StartSideRail and EndSideRail) to support landscape, foldable, and tablet capture layouts. It extends CaptureSlotScope and PreviewOverlaySlotScope to propagate container layout metadata (orientation and isCompact) directly to child controls, allowing them to adapt their dimensions and axis. Additionally, new unit tests (CaptureSideRailsTest and CaptureSlotsTest) have been added to verify layout constraints, RTL ordering, and compact sizing using Robolectric and Truth assertions. The implementation is clean, well-tested, and adheres to the repository's style guides; I have no further feedback to provide.

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.

1 participant