Skip to content

iOS: show the full alt-screen notice on compact phones - #7727

Merged
azooz2003-bit merged 10 commits into
mainfrom
feat-ios-alt-screen-notice-layout
Jul 10, 2026
Merged

azooz2003-bit merged 10 commits into
mainfrom
feat-ios-alt-screen-notice-layout

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • adapt the alt-screen explanation to a sheet on compact iPhone layouts
  • use a scrollable fallback when height or Dynamic Type cannot fit the full content

Testing

  • ./scripts/reload.sh --tag altfit
  • ./ios/scripts/reload.sh --tag altfit --simulator cmux-altfit-primary-20260709-1125
  • isolated simulator UI verification in progress

Issues

  • Reported directly with an iPhone screenshot; no GitHub issue.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Low Risk
SwiftUI presentation and copy changes for an informational notice only; no auth, networking, or terminal protocol impact.

Overview
Fixes clipped alt-screen explanation popovers on compact iPhones and large Dynamic Type by sizing the presentation to content at 340pt width and falling back to a vertical ScrollView when height is tight.

The popover uses a new AltScreenNoticePresentationSizing helper plus ViewThatFits / scrollBounceBehavior(.basedOnSize) instead of a fixed 320pt content frame. Copy now includes concrete exit steps (Claude Code /tui default, Codex codex --no-alt-screen), with matching en/ja strings in Localizable.xcstrings. The permanent-dismiss control gets an accessibility identifier for UI tests.

DEBUG TerminalLayoutPreviewView can mount the notice in a NavigationStack toolbar when CMUX_UITEST_ALT_SCREEN_NOTICE_PREVIEW=1, wired to MobileDisplaySettings.showAltScreenNotice.

Reviewed by Cursor Bugbot for commit 13f89d9. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Shows the full alt-screen notice on compact iPhones and with large Dynamic Type by fitting the native popover to measured content at 340pt, with a vertical scroll fallback and size-based bounce to avoid clipping.

Extracts sizing into AltScreenNoticePresentationSizing, adds a DEBUG preview behind CMUX_UITEST_ALT_SCREEN_NOTICE_PREVIEW=1 that mounts the notice button in a NavigationStack toolbar and dismisses via MobileDisplaySettings, adds an accessibility ID on the permanent-dismiss button, and updates the copy with clear exit steps: Claude Code /tui default; Codex codex --no-alt-screen.

Written for commit 13f89d9. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • UI Improvements

    • Refined the Alt Screen notice popover for compact devices by improving layout sizing and adding a scrollable fallback.
    • Updated the dismiss button styling and added a consistent accessibility identifier.
  • Preview/Test Behavior

    • Enhanced the Terminal Layout preview to optionally show a top-bar Alt Screen notice button in a dedicated preview/test mode, with support for dismissing it.

@vercel

vercel Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jul 10, 2026 7:45am
cmux-staging Building Building Preview, Comment Jul 10, 2026 7:45am

@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The alt-screen notice popover now uses fitted sizing with a scrollable fallback, updated dismiss-button styling, and explicit sizing behavior. The terminal layout preview conditionally adds a toolbar notice button driven by display settings when the preview flag is enabled.

Changes

Alt-screen notice UI and preview wiring

Layer / File(s) Summary
Popover presentation and sizing
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AltScreenNoticeButton.swift
Fits popover content vertically, falls back to scrolling, applies fixed-width presentation sizing, and updates dismiss-button styling, accessibility, and container width.
Conditional preview toolbar wiring
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/TerminalLayoutPreviewView.swift
Reads MobileDisplaySettings, conditionally wraps the preview in a NavigationStack, adds an AltScreenNoticeButton toolbar item, and clears showAltScreenNotice from the button action.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TerminalLayoutPreviewView
  participant MobileDisplaySettings
  participant AltScreenNoticeButton
  participant Popover
  TerminalLayoutPreviewView->>MobileDisplaySettings: read showAltScreenNotice
  TerminalLayoutPreviewView->>AltScreenNoticeButton: add toolbar button when preview flag is enabled
  AltScreenNoticeButton->>Popover: present fitted notice content
  AltScreenNoticeButton->>MobileDisplaySettings: clear showAltScreenNotice on dismiss
Loading

Possibly related PRs

  • manaflow-ai/cmux#7669: Introduces the alt-screen warning button and related popover behavior that this PR further adjusts.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed The changes are UI-only SwiftUI code; the new PresentationSizing helper is private inside a view, and MobileDisplaySettings stays MainActor-bound with main-thread view actions.
Cmux Swift Blocking Runtime ✅ Passed Touched Swift files add only SwiftUI layout/preview changes; no semaphores, sleeps, sync waits, asyncAfter, timers, or manual locks appear in the diff.
Cmux Browser Automation Off-Main ✅ Passed Only AltScreenNoticeButton.swift changed; no browser.* socket-routing or main-actor automation code was touched.
Cmux Expensive Synchronous Load ✅ Passed The touched SwiftUI views only adjust popover layout and DEBUG preview wiring; no agent-history loads, JSON parsing, or directory scans were added on a main/interactive path.
Cmux Cache Substitution Correctness ✅ Passed PASS: The diff only refactors SwiftUI popover layout and DEBUG preview wiring; it doesn’t swap any authoritative read for cached data in a persistence/history/snapshot path.
Cmux No Hacky Sleeps ✅ Passed The patch only changes a SwiftUI file; no TypeScript/JavaScript/shell/build/runtime scripts were modified, so the no-hacky-sleeps rule is not applicable.
Cmux Algorithmic Complexity ✅ Passed The diff only adds fixed-size SwiftUI popover layout work; no scalable collection scans, batch rescans, or hot-path sorting/filtering appear.
Cmux Swift Concurrency ✅ Passed Changed files are SwiftUI layout/preview code only; no new DispatchQueue, Combine, completion-handler, or fire-and-forget Task patterns were introduced.
Cmux Swift @Concurrent ✅ Passed Changed Swift files are synchronous SwiftUI/layout code only; no async helpers or @concurrent annotations were introduced.
Cmux Swift File And Package Boundaries ✅ Passed Touched Swift files are small (110 and 94 lines) UI/debug glue inside CmuxMobileShellUI, with no mixed persistence/network/protocol responsibilities or boundary spillover.
Cmux Swiftpm Lockfiles ✅ Passed Diff only changes two Swift source files; no Package.swift, Package.resolved, .gitignore, or Xcode package-reference files were touched.
Cmux Swift Logging ✅ Passed No added logging APIs or ad hoc stdout/file diagnostics appear in the Swift diff; the change is layout-only.
Cmux User-Facing Error Privacy ✅ Passed Only generic alt-screen copy is user-visible; no vendor/internal names, env vars, raw errors, or payload dumps appear in production UI.
Cmux Full Internationalization ✅ Passed AltScreenNoticeButton only changes layout; user-facing strings use L10n.string/String(localized:) and the alt-screen keys already have en/ja catalog entries in HEAD and parent.
Cmux Swiftui State Layout ✅ Passed No new ObservableObject/@published state, no GeometryReader layout measurement, no lazy-row store refs, and no render-time state writes in the touched SwiftUI views.
Cmux Architecture Rethink ✅ Passed No architectural smell introduced: the new path is DEBUG/test-only, MobileDisplaySettings remains the single owner of showAltScreenNotice, and no timing/observer/lock patterns were added.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: the diff only refactors a popover and a DEBUG preview view; it adds no NSWindow/NSPanel/WindowGroup, no cmux.* identifier, and no close-shortcut routing changes.
Cmux Source Artifacts ✅ Passed Both changed paths are Swift source files under Sources; no artifact, cache, temp, or generated-output paths appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The only touched production file, AltScreenNoticeButton.swift, adds popover/layout code only; no #if DEBUG, test hook, or debug-named seam was introduced.
Cmux No Ambient Global State ✅ Passed PASS: The patch adds only private helper structs and instance methods inside existing views; no new file-scope funcs, mutable globals, or singletons were introduced.
Title check ✅ Passed The title accurately summarizes the main UI change: showing the full alt-screen notice on compact iPhones.
Description check ✅ Passed It includes Summary, Testing, and an Issues note, so the core template is covered, but it omits the demo video, review trigger, and checklist sections.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-ios-alt-screen-notice-layout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes clipped alt-screen notice popovers on compact iPhones and large Dynamic Type by wrapping the popover content in ViewThatFits with a ScrollView fallback, and sizing the popover to its measured content via a new AltScreenNoticePresentationSizing protocol conformance at a 340pt max width.

  • AltScreenNoticeButton: popover now uses ViewThatFits(in: .vertical) so that on compact-height devices the ScrollView variant is selected; PresentationSizing proposes the measured content height instead of a fixed size; explanation copy updated in en/ja to include exit commands (/tui default, codex --no-alt-screen), and accessibility identifier added to the dismiss button.
  • AltScreenNoticePresentationSizing: new PresentationSizing struct that calls root.sizeThatFits at 340pt width to derive the proposed height, letting the system clamp on small screens while ViewThatFits falls through to the scroll path.
  • TerminalLayoutPreviewView: adds CMUX_UITEST_ALT_SCREEN_NOTICE_PREVIEW=1 env-var path (inside the existing #if canImport(UIKit) && DEBUG guard) to mount the notice button in a NavigationStack toolbar for simulator UI verification, consistent with existing CMUX_UITEST_* patterns in the same file.

Confidence Score: 5/5

Safe to merge — localized UI and popover presentation only, with no auth, networking, or terminal protocol changes.

All changes are scoped to the alt-screen notice popover: layout sizing, scroll fallback, copy update, and a debug simulator harness inside an existing DEBUG-only file. The package deployment target is iOS 18, which matches the PresentationSizing API requirement. Both supported locales (en, ja) are updated consistently. No state management regressions, no actor isolation issues, and no blocking synchronization introduced.

No files require special attention.

Important Files Changed

Filename Overview
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AltScreenNoticeButton.swift Wraps popover content in ViewThatFits with a ScrollView fallback, applies AltScreenNoticePresentationSizing for content-fitted presentation, adds accessibility identifier to dismiss button, and updates explanation copy with exit commands.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AltScreenNoticePresentationSizing.swift New PresentationSizing implementation that measures content at 340pt width and proposes that exact size, letting the system clamp on compact screens while ViewThatFits selects the scroll fallback.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/TerminalLayoutPreviewView.swift Adds CMUX_UITEST_ALT_SCREEN_NOTICE_PREVIEW env-var gate (within the existing #if canImport(UIKit) && DEBUG guard) to mount the alt-screen notice in a NavigationStack toolbar, consistent with pre-existing CMUX_UITEST_* patterns in the same file.
ios/cmux/Resources/Localizable.xcstrings Updates mobile.altScreenNotice.explanation in both en and ja locales to include exit commands (Claude Code /tui default; Codex --no-alt-screen); all catalog-supported locales are covered.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User as User (compact iPhone)
    participant Button as AltScreenNoticeButton
    participant Popover as Popover(.popover)
    participant VTF as ViewThatFits(in: .vertical)
    participant Sizing as AltScreenNoticePresentationSizing
    participant Content as popoverContent
    participant Scroll as ScrollView fallback

    User->>Button: tap exclamation triangle
    Button->>Popover: "isPresented = true"
    Popover->>Sizing: proposedSize(for: root)
    Sizing->>Content: sizeThatFits(width: 340, height: nil)
    Content-->>Sizing: measured height
    Sizing-->>Popover: ProposedViewSize(340, measured height)
    Popover->>VTF: layout with system-clamped height
    alt content fits vertical space
        VTF->>Content: render popoverContent directly
    else height too small (large Dynamic Type / compact screen)
        VTF->>Scroll: "render ScrollView { popoverContent }"
    end
    User->>Content: tap Don't Show Again
    Content->>Button: dismissFromPopover()
    Button->>Button: "dismissNotice() + isPresentingExplanation = false"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User as User (compact iPhone)
    participant Button as AltScreenNoticeButton
    participant Popover as Popover(.popover)
    participant VTF as ViewThatFits(in: .vertical)
    participant Sizing as AltScreenNoticePresentationSizing
    participant Content as popoverContent
    participant Scroll as ScrollView fallback

    User->>Button: tap exclamation triangle
    Button->>Popover: "isPresented = true"
    Popover->>Sizing: proposedSize(for: root)
    Sizing->>Content: sizeThatFits(width: 340, height: nil)
    Content-->>Sizing: measured height
    Sizing-->>Popover: ProposedViewSize(340, measured height)
    Popover->>VTF: layout with system-clamped height
    alt content fits vertical space
        VTF->>Content: render popoverContent directly
    else height too small (large Dynamic Type / compact screen)
        VTF->>Scroll: "render ScrollView { popoverContent }"
    end
    User->>Content: tap Don't Show Again
    Content->>Button: dismissFromPopover()
    Button->>Button: "dismissNotice() + isPresentingExplanation = false"
Loading

Reviews (9): Last reviewed commit: "Separate alt-screen presentation sizing" | Re-trigger Greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c52323e. Configure here.

@azooz2003-bit
azooz2003-bit merged commit 663d6fe into main Jul 10, 2026
40 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-ios-alt-screen-notice-layout branch July 10, 2026 14:38

This branch was successfully deployed

1 active deployment
Preview – cmux — 13f89d9c Deployed Jul 10, 2026 by vercel[bot]
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