Skip to content

Zoom fix#1749

Merged
simo6529 merged 2 commits intomainfrom
zoom-fix
Jan 16, 2026
Merged

Zoom fix#1749
simo6529 merged 2 commits intomainfrom
zoom-fix

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Jan 16, 2026

Summary by CodeRabbit

  • New Features

    • Implemented platform-specific optimizations for iOS and Android devices with enhanced animation performance on Android.
  • Bug Fixes

    • Improved mobile viewport handling for better compatibility across devices and screen sizes.
    • Enhanced touch interactions and input responsiveness on mobile platforms.
    • Fixed cursor behavior and input focus management on mobile devices.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

The changes implement platform-specific optimizations and viewport management for mobile applications. Key updates include iOS detection in the mobile wrapper dialog, viewport meta tag preservation and management via Capacitor setup, CSS refinements for mobile dialogs with GPU-accelerated transforms, and improved input handling in the Lexical editor with better null-safety checks.

Changes

Cohort / File(s) Summary
Mobile Platform & Viewport Management
components/mobile-wrapper-dialog/MobileWrapperDialog.tsx, components/providers/CapacitorSetup.tsx
Added iOS detection via useCapacitor() for platform-specific logic. Updated viewport height calculations to use min(100vh, 100svh) instead of hardcoded 100dvh. Introduced conditional GPU transform classes for non-iOS platforms. Added touchAction: "manipulation" styling. CapacitorSetup now manages viewport meta tags with preservation of original values and Capacitor-specific configurations including viewport-fit=cover.
Editor Input Refinements
components/waves/CreateDropInput.tsx
Reorganized Lexical component imports for clarity. Adjusted placeholder logic to use strict null check (type === null). Added touchAction: "manipulation" to ContentEditable. Refined click handling and cursor placement with optional chaining (selection?.rangeCount). Streamlined conditional className logic while maintaining functional equivalence.
Mobile Dialog Styling
styles/globals.scss
Introduced .mobile-wrapper-dialog style scope applying font-size: 16px and touch-action: manipulation to input/textarea/select elements. Minor formatting adjustments to scroll-shadow gradients.

Sequence Diagrams

sequenceDiagram
    participant App as App Initialization
    participant Setup as CapacitorSetup
    participant Meta as Viewport Meta Tag
    participant DOM as DOM/Rendering

    App->>Setup: Component mounts (isCapacitor flag)
    Setup->>Meta: Query or create viewport meta tag
    Setup->>Meta: Store original viewport content
    alt isCapacitor is true
        Setup->>Meta: Set fixed viewport (no-zoom, viewport-fit=cover)
    else isCapacitor is false
        Setup->>Meta: Restore original viewport content
    end
    Meta->>DOM: Viewport configuration applied
    Setup->>DOM: Apply capacitor-native class to body
    DOM->>DOM: Render with platform-specific layout
    Note over Setup: Cleanup restores original viewport on unmount
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Reactions dialog #1718: Updates to MobileWrapperDialog component (classNames, viewport height logic, iOS detection) directly affect mobile dialog rendering used by reactions and other mobile-specific features.

Suggested reviewers

  • ragnep

Poem

🐰 Hoppy hops through viewports wide,
iOS and Android side by side,
Touch actions smooth, transforms GPU-bound,
Mobile dialogs dance without a sound!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive The title 'Zoom fix' is vague and generic, using non-descriptive terminology that doesn't convey meaningful information about the specific changes made in the changeset. Replace with a more specific title that describes the primary change, such as 'Fix zoom behavior and viewport handling on mobile platforms' or 'Prevent iOS auto-zoom and optimize mobile animations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/waves/CreateDropInput.tsx (1)

184-192: Guard against null before calling focus().
The current cast can throw if the contenteditable element is missing (e.g., before mount or after unmount).

🐛 Proposed fix
       focus: () => {
-        (
-          editorRef.current?.querySelector(
-            '[contenteditable="true"]'
-          ) as HTMLElement
-        ).focus();
+        const editable = editorRef.current?.querySelector(
+          '[contenteditable="true"]'
+        ) as HTMLElement | null;
+        editable?.focus();
       },
🧹 Nitpick comments (2)
components/mobile-wrapper-dialog/MobileWrapperDialog.tsx (2)

93-94: Minor redundancy: touchAction is also set via CSS.

The touch-action: manipulation is already applied to .mobile-wrapper-dialog elements in globals.scss (lines 206-213). The inline style here is redundant but ensures the style is applied regardless of CSS load order.

Consider removing the inline style if you're confident the CSS is always loaded:

♻️ Optional: Remove redundant inline style
 <DialogPanel
   className={panelClassNames}
-  style={{ touchAction: "manipulation" }}
   onClick={(e) => e.stopPropagation()}
 >

38-38: Consider adding a fallback for in-app and older embedded browsers.

The svh unit has ~94% support in modern browsers (Chrome 108+, Firefox 101+, Safari 15.4+), but is not consistently supported in in-app browsers (Messenger, older Android webviews). For these environments, the browser won't recognize the svh value. Use a progressive enhancement pattern with @supports to safely fall back to 100vh for browsers that don't support the newer viewport units, ensuring consistent behavior across all target platforms.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afc5934 and bdacc37.

📒 Files selected for processing (4)
  • components/mobile-wrapper-dialog/MobileWrapperDialog.tsx
  • components/providers/CapacitorSetup.tsx
  • components/waves/CreateDropInput.tsx
  • styles/globals.scss
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (10)
components/waves/CreateDropInput.tsx (3)

3-4: No review comment.

Also applies to: 12-13, 38-43


157-169: Placeholder logic looks good.


232-253: ContentEditable interaction tweaks look solid.

components/providers/CapacitorSetup.tsx (3)

18-46: Cleanup function may cause unintended viewport restoration.

The cleanup function restores the original viewport on every effect cleanup (including when isCapacitor changes). Since the effect body at lines 37-38 already handles restoration when isCapacitor becomes false, the cleanup will immediately run again and restore the same value - this is benign but redundant.

However, there's a subtle issue: if the component unmounts while isCapacitor is false (and originalViewport was never set because isCapacitor started false), the cleanup does nothing (which is correct). But if the component mounts with isCapacitor=true, sets the viewport, then unmounts, the cleanup correctly restores. This logic appears sound.

One edge case: if isCapacitor toggles rapidly, the nullish coalescing on line 30 ensures originalViewport.current captures only the first observed value, which is the intended behavior.


19-19: SSR guard is appropriate.

The typeof document === "undefined" check correctly prevents DOM manipulation during server-side rendering.


21-28: Meta tag creation logic is sound.

The nullish coalescing with createElement and the name attribute check ensure the element is only appended when newly created. Good defensive approach.

styles/globals.scss (2)

206-213: Good iOS zoom prevention pattern.

Setting font-size: 16px on form inputs prevents iOS Safari's auto-zoom behavior (triggered for inputs < 16px). Combined with touch-action: manipulation to disable double-tap zoom, this effectively addresses common mobile zoom issues.


581-584: Formatting-only change.

The transition property was reformatted to multi-line for readability. No functional change.

components/mobile-wrapper-dialog/MobileWrapperDialog.tsx (2)

46-48: iOS GPU transform exclusion is a known workaround.

Disabling transform-gpu and will-change-transform on iOS avoids known rendering issues (flickering, z-index problems) with these properties on Safari. This is a reasonable trade-off for stability.


39-44: Height calculation change from dvh to min(vh, svh).

This change affects dialog sizing behavior. Using min(100vh, 100svh) will consistently use the smaller viewport height (accounting for browser chrome), whereas dvh dynamically adjusts. This prevents layout shifts when mobile browser UI appears/disappears, which aligns with the zoom fix objective.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@simo6529 simo6529 merged commit e16930a into main Jan 16, 2026
7 checks passed
@simo6529 simo6529 deleted the zoom-fix branch January 16, 2026 08:33
@coderabbitai coderabbitai Bot mentioned this pull request Mar 30, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Apr 9, 2026
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