Context: This document exists because a long debugging session on safe-area, canvas sizing, and rotation in the iOS WKWebView shell did not converge on a verified fix. A lot of time was lost iterating on layout, CSS env() variables, and instrumentation. Treat everything below as working hypotheses and file pointers, not as solved facts.
- Multiple overlapping concerns were tackled at once: CSS safe-area insets, JavaScript layout mode (
desktop/mobile-portrait/mobile-landscape), canvas zoom (updateMobileCanvasSize),visualViewportvswindow.innerWidth/Height, and iOS app orientation policy. - Runtime evidence was sparse or inconclusive relative to the complexity (rotation transitions, WebKit quirks, transient geometry). The session ended with debug tooling removed at the author’s request—not with a proven fix.
- Do not assume the last structural change (orientation lock, variable renames, etc.) fully addresses notch alignment, input mapping, or zoom stability until someone measures again on device/simulator.
- Layout mode is derived in JS (
updateLayoutMode):desktopvsmobile-portraitvsmobile-landscape, driven by touch + viewport size threshold and aspect/orientation heuristics (visualViewportpreferred;screen.orientation/window.orientation/matchMediaas fallbacks). data-layouton<body>reflectslayoutModeand is used for CSS branching.- Mobile canvas scaling goes through
updateMobileCanvasSize, which reads themobile-canvas-containerbounding rect, compares tovisualViewportdimensions, applies a “oversized” guard (schedules a settle pass viarequestAnimationFramewhen geometry looks transient/wrong), and setszoomFactorfrom container vs logical canvas size.resetViewTransform,applyEditorDimensions,setVisualsfollow when zoom changes. - Resize /
orientationchangelisteners callupdateLayoutMode, then either desktop scale orupdateMobileCanvasSize(sometimes double-requestAnimationFrameafter orientation change to catch settled layout).
FlickWebView.swiftloads bundledwww/index.html(synced from root via the Xcode build phase /make sync-ios). It injectswindow.FLICKGAME_HOST = 'ios-app'andwindow.FLICKGAME_IOS_APP = trueat document start.- Supported orientations were restricted to reduce the “four orientations / notch jumps around” problem:
Info.plist:UISupportedInterfaceOrientationslistsUIInterfaceOrientationPortraitandUIInterfaceOrientationLandscapeLeftonly.project.pbxprojalso setsINFOPLIST_KEY_UISupportedInterfaceOrientations_*— keep plist and build settings aligned if you change this (GENERATE_INFOPLIST_FILEmakes both relevant).
- If the physical notch ends up on the “wrong” side in landscape for a given device expectation, the fix may be as small as swapping
LandscapeLeft↔LandscapeRightin both places—verify on hardware, don’t guess.
- Heavy debug instrumentation (NDJSON ingest, optional native log bridge,
captureSafeAreaSnapshot-style payloads) was added to correlate viewport rects, zoom, and layout mode. It was removed when debugging stopped; do not expect those hooks in the tree now. ios/README.mdwas shortened: it no longer documents a?debugSafeArea=1workflow (that path may not exist anymore).
These are candidates, not confirmed root causes:
- Rotation / layout settling:
innerWidth/innerHeightandvisualViewportcan disagree during iOS rotation; code already tries rAF chaining—timing may still be wrong for some paths. - Zoom vs CSS safe-area:
zoomFactorand pixel mapping for drawing/input must stay consistent with actual displayed canvas size; any mismatch looks like “wrong stroke position” or “canvas in wrong place.” WKWebView+ safe-area: env(safe-area-inset-*) behavior in embedded WebKit can differ from Mobile Safari; padding on the wrong element duplicates or fights JS assumptions.- Policy vs UX: Locking to two orientations trades flexibility for predictability; it does not automatically fix geometry bugs.
- Reproduce on iOS (simulator + real device): portrait ↔ single allowed landscape, note notch side, toolbar overlap, canvas alignment, draw accuracy.
- Trace one code path end-to-end:
orientationchange/resize→updateLayoutMode→onLayoutModeChange→updateMobileCanvasSize→applyEditorDimensions/getCoordsfor input. - Add minimal, targeted logging (or Web Inspector breakpoints) only after forming hypotheses—avoid another multi-hour unfocused pass.
- If changing orientations again, edit both
Info.plistandproject.pbxprojkeys so they stay consistent.
| Area | Path |
|---|---|
| Editor logic, layout mode, mobile zoom | index.html (large; search layoutMode, updateMobileCanvasSize, updateLayoutMode) |
| Bundled copy for Xcode | ios/FlickgameShell/FlickgameShell/www/index.html (generated; sync from root) |
| WebView host flags | ios/FlickgameShell/FlickgameShell/FlickWebView.swift |
| iOS orientation plist | ios/FlickgameShell/FlickgameShell.xcodeproj/Info.plist |
| Build settings / generated plist keys | ios/FlickgameShell/FlickgameShell.xcodeproj/project.pbxproj |
| Sync script | ios/scripts/sync-web-assets.sh, Makefile (sync-ios) |
Today’s session was costly and did not deliver a validated, minimal fix for the underlying canvas/safe-area/orientation behavior. The app may still exhibit issues on rotation or notched devices. The next person should treat this as a fresh debugging task with clear reproduction steps and measured evidence, not as “almost done.”