Skip to content

Follow up analyze tab - #5750

Open
vitaliy-sova-ios wants to merge 6 commits into
masterfrom
follow_up_analyze_tab
Open

Follow up analyze tab#5750
vitaliy-sova-ios wants to merge 6 commits into
masterfrom
follow_up_analyze_tab

Conversation

@vitaliy-sova-ios

@vitaliy-sova-ios vitaliy-sova-ios commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Related issue / task

Fixes #5674

Summary

Two changes on this branch.

1. Get elevation data screen — adaptive presentation

Replaces the UISheetPresentationController medium sheet with a custom
UIPresentationController:

  • Landscape: renders as a left-side panel (393pt, full height) using the
    same geometry as the Plan Route panel — identical left/top/bottom insets,
    the same visibleMapWidth >= 252 gate, and the same "always a side panel"
    behavior on iPad / Mac Catalyst.
  • Portrait: bottom sheet sized to its content height
    (systemLayoutSizeFitting, safe-area-independent so the measurement is
    idempotent) + bottom safe area.
  • Both orientations slide in/out vertically (from the bottom).
  • Content constraints moved from raw view edges to safeAreaLayoutGuide,
    which fixes the reported bug: title / description / option rows were
    clipped under the Dynamic Island in landscape.
  • containerView.accessibilityViewIsModal = true — a custom presentation
    does not get VoiceOver modal isolation for free the way .pageSheet did.
  • Non-Pro "Use Terrain maps" now opens the Choose Plan screen directly
    (there is no navigation controller wrapper anymore); this mirrors what
    OAChoosePlanHelper does internally.

Everything lives in GetElevationDataViewController.swift (no new file, to
avoid a manual project.pbxproj edit).

2. Plan Route → Analyze tab — road-attribute section jitter (iteration 3)

Road-attribute rows (Surface / Smoothness / Steepness / Road types) now get
exact, synchronous heights from a content-keyed cache instead of
automaticDimension. Expand/collapse and the following scroll no longer
jerk contentOffset (worst when the section header is pinned at the top).
The section-header structure and its floating behavior are unchanged.

  • measuredRowHeights cache keyed by "<stat.name>|expanded|collapsed".
  • roadAttrRowHeight = chartTopInset(20) + chartHeight(54) + measured legend height; verified to match the real card constraints and
    AnalyzeCardCell (card fills the cell vertically, 16pt horizontal inset).
  • heightForRowAt / estimatedHeightForRowAt return the exact height for
    road-attribute rows, automaticDimension / a fixed estimate for the
    chart / stats / status rows.
  • toggleRoadAttribute pre-warms the new-state height, swaps the legend in
    place (keeps the bar chart), then beginUpdates()/endUpdates().
  • Cache invalidated on every reload path in applyRenderState and on a
    table-width change in viewDidLayoutSubviews.

Testing

Tested on:

  • Device: iPhone 11
  • iOS: 26.5

Scenarios

Get elevation data

  • Portrait: bottom sheet. Landscape: left panel, clear of the notch. Slides
    up from the bottom.
  • Rotate while open — nothing clipped or stuck.
  • Close with ✕ and by tapping the dimmed area.
  • "Use nearby roads" / "Use Terrain maps" (Pro) — close and run the action.
  • "Use Terrain maps" (no Pro) — Choose Plan opens, back returns here.
  • iPad — left panel in both orientations.
  • VoiceOver stays inside the screen; light / dark.

Analyze tab

  • Expand / collapse each section, including with the header pinned — no jump.
  • Scroll right after a toggle — no jitter.
  • Toggle an off-screen section, then scroll to it — correct height.
  • Track with and without elevation data.

Relevant checks

  • Portrait / Landscape tested
  • Light / Dark mode tested
  • Different profiles tested
  • Localization / RTL checked
  • VoiceOver / Accessibility checked
  • CarPlay checked
  • Android parity checked
  • Performance impact checked

AI disclaimer

Implementation:

  • Tool / Agent: Claude Code
  • Model: Claude Sonnet 5 (claude-sonnet-5)

Prompts used (summarised):

  1. Check whether that screen can open as a left-side panel like the Plan
    Route panel; first implemented by embedding it in the Plan Route panel,
    then reverted after a janky resize animation.
  2. Explore an alternative — tuning sheetPresentationController vs a custom
    UIPresentationController; implement the custom presentation controller
    (adaptive side panel / bottom sheet).
  3. In landscape, slide in from the bottom instead of from the side.
  4. Run a code review of the branch; apply the safe findings.
  5. (Earlier sessions) Iterate the Analyze-tab road-attribute jitter fix to
    iteration 3 (exact synchronous row heights + cache).

Decided by the agent, not requested explicitly:

  • Side-panel geometry constants (393pt width, insets, minimumMapWidth,
    the side-panel eligibility check) copied from
    PlanRouteScrollableViewController rather than derived or shared.
  • A 0.2 black dimming overlay with tap-to-dismiss (carried over from the
    medium sheet's behavior).
  • Corner radius kept at 20 (the old medium sheet value), not the Plan Route
    panel's 28.
  • Portrait sheet height derived from content, no scroll view.
  • Moving content constraints to safeAreaLayoutGuide (also resolves the
    original landscape report).
  • Non-Pro terrain path: replicate OAChoosePlanHelper.showImpl inline
    because the helper needs a UINavigationController that no longer exists.
  • Keep everything in one file to avoid a manual project.pbxproj change.

Final review:

  • Tool / Agent: Claude Code
  • Model: Claude Sonnet 5 (claude-sonnet-5)
  • Final diff reviewed (static review only — not built or run)

Significant findings:

  • Get elevation data: missing VoiceOver modal isolation with the custom
    presentation — fixed (accessibilityViewIsModal).

…ithout saving changes, the Save button turns dark.
Replace the medium sheet with a custom UIPresentationController:
landscape shows a 393pt left-side panel matching the plan route
layout, portrait shows a content-height bottom sheet. Both slide
in from the bottom. Content is pinned to the safe area, fixing the
title/description clipping under the Dynamic Island in landscape.
@tigrim

tigrim commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

The new exact-height cache does not account for Dynamic Type changes. roadAttrHeightKey only includes the statistic name and expanded/collapsed state, and the cache is invalidated for data reloads and table-width changes, but not when preferredContentSizeCategory changes. The expanded legend uses labels with adjustsFontForContentSizeCategory, so changing the system text size while this screen remains alive can leave the table row at its old cached height and clip or overlap the updated content. Please clear measuredRowHeights and reload the affected rows on a content-size-category change, or include the content-size category in the cache key.

@vitaliy-sova-ios

Copy link
Copy Markdown
Contributor Author
2026-09-10.13.52.26.mov

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.

Follow up Analyze tab – Plan a route

2 participants