Skip to content

feat(mobile): terminal mobile-fit restore, corner-inset module & home redesign - #121

Merged
gedeagas merged 1 commit into
mainfrom
app-terminal-resize
Jun 2, 2026
Merged

gedeagas merged 1 commit into
mainfrom
app-terminal-resize

Conversation

@gedeagas

@gedeagas gedeagas commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Three related mobile-companion improvements, plus repo hygiene:

  1. Terminal mobile-fit / clean desktop restore (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.
  2. corner-inset native 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.
  3. Mobile home screen redesign - reworked index.tsx landing layout and corner-inset-aware headers across screens.
  4. Repo hygiene - removed an accidentally committed 22 MB .ipa build artifact and added *.ipa/*.apk/*.aab to mobile-app/.gitignore.

Terminal resize details

A new pty:mobileFit IPC channel broadcasts the phone-fit dimensions a mobile device applies to the shared PTY (emitted from rpc.ts on terminal.resize, terminal.setDisplayMode, and terminal.subscribe).

BigTerminalView consumes it via ipc.pty.onMobileFit:

  • While the desktop yields to a phone, xterm is sized to the phone's PTY dims so the held scrollback buffer is laid out at the width the phone shows.
  • On the held -> un-held transition, a primary requestAnimationFrame fit plus a 100 ms belt-and-suspenders fallback force a re-fit if the initial fit no-ops (it can measure the container before the visibility:hidden -> visible flip 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 via onInsetsChange.
  • Guarded to iOS; on Android/web NativeCornerInsetView is null and callers render nothing. requireNativeView is wrapped in try/catch so an old dev-client without the module degrades gracefully instead of crashing at import.
  • src/ui/kit/CornerInset.tsx wraps the native view; consumed by index.tsx, host, terminal, browser, settings, notifications, troubleshoot, and SourceControlScreen.

Test plan

  • Pair a phone, drive a shared big terminal, switch phone<->desktop display modes; confirm desktop xterm reflows back to full width with no stranded narrow scrollback.
  • Resize the desktop pane mid-session; confirm the restore fallback does not clobber the manual size.
  • Build the iPad dev-client; confirm headers clear the window controls and that an older dev-client (no native module) still renders.

- 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
Copilot AI review requested due to automatic review settings June 2, 2026 13:32

Copilot AI 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.

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:mobileFit IPC channel + BigTerminalView restore logic that sizes xterm to the phone's PTY dims while held and re-fits robustly on the held→un-held transition.
  • New corner-inset Expo native module (Swift) exposing iPadOS 26 corner-margin insets to JS, plus a CornerInset kit 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.

@gemini-code-assist gemini-code-assist 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.

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.

Comment on lines +86 to +92
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
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

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
    }

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

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.LayoutRegion is 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 given LayoutRegion; layoutGuide(for:) is the Auto Layout equivalent.
  • .horizontal corner 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

@gedeagas
gedeagas merged commit 13c3da6 into main Jun 2, 2026
1 check passed
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