feat(mobile): terminal mobile-fit restore, corner-inset module & home redesign - #121
Conversation
- Implement iPadOS 26 corner adaptation margin detection to dodge window controls in headers - Redesign home screen with status hero, animated transitions, and inline host removal - Extract status stats into animated strip; highlight terminals needing input
There was a problem hiding this comment.
Pull request overview
Adds mobile-companion improvements: terminal mobile-fit reflow on desktop restore, a new iPadOS 26 corner-inset native module to dodge window controls in custom headers, and a redesigned mobile home screen. Also adds repo hygiene (Gemfile for fastlane, ignoring iOS/Android build artifacts).
Changes:
- New
pty:mobileFitIPC channel +BigTerminalViewrestore logic that sizes xterm to the phone's PTY dims while held and re-fits robustly on the held→un-held transition. - New
corner-insetExpo native module (Swift) exposing iPadOS 26 corner-margin insets to JS, plus aCornerInsetkit component wired into home/host/terminal/browser/settings/notifications/troubleshoot/source-control headers. - Mobile home screen redesign (animated status hero, status strip, compact quick tiles, per-row remove action) and
.gitignore/Gemfile hygiene.
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/services/mobileServer/rpc.ts | Emits pty:mobileFit to desktops on resize/setDisplayMode/subscribe. |
| src/preload/index.ts | Exposes onMobileFit IPC bridge. |
| src/renderer/lib/ipc.ts | Renderer wrapper for onMobileFit. |
| src/renderer/components/Center/BigTerminalView.tsx | Mirrors held xterm to phone-fit dims and adds rAF+timeout restore fallback. |
| mobile-app/modules/corner-inset/ios/CornerInsetModule.swift | Native view measuring iPadOS 26 corner adaptation margin via KVO on window bounds. |
| mobile-app/modules/corner-inset/ios/CornerInset.podspec | Podspec for the native module. |
| mobile-app/modules/corner-inset/index.ts | JS wrapper around requireNativeView, guarded to iOS with try/catch. |
| mobile-app/modules/corner-inset/expo-module.config.json | Registers the Apple module. |
| mobile-app/src/ui/kit/CornerInset.tsx | Spacer component that renders the native measuring view. |
| mobile-app/src/ui/kit/index.ts | Re-exports CornerInset. |
| mobile-app/src/app/index.tsx | Home redesign: status hero, status strip, animated sections, remove action. |
| mobile-app/src/app/{host,terminal,browser,settings,notifications,troubleshoot}/... | Adds <CornerInset /> to custom headers. |
| mobile-app/src/source-control/SourceControlScreen.tsx | Adds <CornerInset /> to header. |
| mobile-app/Gemfile, Gemfile.lock | Adds fastlane via Bundler. |
| mobile-app/.gitignore | Ignores *.ipa, *.apk, *.aab. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Code Review
This pull request introduces a native Expo module CornerInset to handle iPadOS window-control margins in custom headers, redesigns the mobile app's home screen status and animations, and adds a pty:mobileFit event to synchronize terminal dimensions between mobile and desktop views for clean reflowing. Feedback highlights a critical compilation issue in the iOS native module where an availability check for a non-existent "iOS 26.0" and non-standard UIKit APIs are used.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if #available(iOS 26.0, *), let win = window { | ||
| let region = UIView.LayoutRegion.safeArea(cornerAdaptation: .horizontal) | ||
| let insets = win.directionalEdgeInsets(for: region) | ||
| leading = insets.leading | ||
| trailing = insets.trailing | ||
| top = insets.top | ||
| } |
There was a problem hiding this comment.
The availability check #available(iOS 26.0, *) targets a non-existent future iOS version (the current version is iOS 18). Furthermore, UIView.LayoutRegion and directionalEdgeInsets(for:) are not public or standard UIKit APIs in any current iOS SDK.
This will cause a critical compilation error during the iOS build process (e.g., Cannot find type 'UIView.LayoutRegion' in scope), preventing the app from being built.
Please verify if this code was placeholder or hallucinated, and implement a standard fallback or use safe area insets to handle layout margins on iPadOS.
if #available(iOS 15.0, *), let win = window {
let insets = win.safeAreaInsets
leading = insets.left
trailing = insets.right
top = insets.top
}There was a problem hiding this comment.
Thanks, but this is a false positive from an outdated knowledge cutoff. iPadOS 26 is shipping (Apple moved to year-based versioning; iOS/iPadOS 26 released Sept 2025), and these are genuine, documented APIs:
UIView.LayoutRegionis the new iPadOS 26 type for layout regions (safe area + margins).directionalEdgeInsets(for:)/edgeInsets(for:)are the documented frame-based accessors that return point values for a givenLayoutRegion;layoutGuide(for:)is the Auto Layout equivalent..horizontalcorner adaptation is Apple's recommended approach to keep header leading content clear of the new top-leading window controls.
The whole point of this module is the Corner Adaptation Margin, which is a distinct layout region from the classic safe area, so the suggested safeAreaInsets fallback would not measure the right region and would defeat the feature. The call is correctly guarded behind #available(iOS 26.0, *) and reports zeros on older OSes (0-width spacer), so nothing breaks on iOS < 26. Resolving as not applicable.
Ref: https://juniperphoton.substack.com/p/adopting-the-new-window-controls
Summary
Three related mobile-companion improvements, plus repo hygiene:
app-terminal-resize) - when a paired phone drives a shared big-terminal PTY, the desktop pane now mirrors xterm to the phone's fit dimensions while held, and reliably reflows back to full desktop width on restore.corner-insetnative module - an Expo/Swift native view that measures the iPadOS 26 "Corner Adaptation Margin" (window controls) so custom headers can offset their leading content past the traffic lights.index.tsxlanding layout and corner-inset-aware headers across screens..ipabuild artifact and added*.ipa/*.apk/*.aabtomobile-app/.gitignore.Terminal resize details
A new
pty:mobileFitIPC channel broadcasts the phone-fit dimensions a mobile device applies to the shared PTY (emitted fromrpc.tsonterminal.resize,terminal.setDisplayMode, andterminal.subscribe).BigTerminalViewconsumes it viaipc.pty.onMobileFit:requestAnimationFramefit plus a 100 ms belt-and-suspenders fallback force a re-fit if the initial fit no-ops (it can measure the container before thevisibility:hidden -> visibleflip settles). The fallback only fires for a visible, non-zero pane still parked at the phone's dims, so a desktop pane the user resized in the meantime is never clobbered.Wiring threaded through all 3 IPC layers:
rpc.ts->preload/index.ts->renderer/lib/ipc.ts.corner-inset module
modules/corner-inset/- Expo native module (CornerInsetModule.swift, podspec, config) exposing an invisible measuring view that reports{ leading, trailing, top }insets viaonInsetsChange.NativeCornerInsetViewis null and callers render nothing.requireNativeViewis wrapped in try/catch so an old dev-client without the module degrades gracefully instead of crashing at import.src/ui/kit/CornerInset.tsxwraps the native view; consumed byindex.tsx,host,terminal,browser,settings,notifications,troubleshoot, andSourceControlScreen.Test plan