Skip to content

android keyboard bug fix#1638

Merged
ragnep merged 6 commits intomainfrom
android-keyboard-bug
Dec 10, 2025
Merged

android keyboard bug fix#1638
ragnep merged 6 commits intomainfrom
android-keyboard-bug

Conversation

@ragnep
Copy link
Copy Markdown
Contributor

@ragnep ragnep commented Dec 9, 2025

Summary by CodeRabbit

  • Refactor

    • Centralized Android keyboard handling so layout adjustments are applied consistently.
    • Removed per-component keyboard-driven container shifts; containers render with stable, predictable layout.
  • Bug Fixes

    • Prevented layout clipping/overflow when the on-screen keyboard opens on Android.
  • Tests

    • Expanded test coverage for keyboard visibility, height handling, and resulting layout behavior.

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

Signed-off-by: ragnep <ragneinfo@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 9, 2025

Walkthrough

Removed per-component Android keyboard adjustments from BrainContent and MyStreamWaveChat; centralized keyboard handling added to LayoutContext which consumes keyboard visibility/height from useAndroidKeyboard; hook simplified to Capacitor event listeners and its public types updated.

Changes

Cohort / File(s) Change Summary
Components with keyboard handling removed
components/brain/content/BrainContent.tsx, components/brain/my-stream/MyStreamWaveChat.tsx
Removed useAndroidKeyboard usage and keyboardAdjustment prop; container styles simplified to static/fallback styles without component-level Android keyboard adjustments.
Centralized keyboard handling / layout
components/brain/my-stream/layout/LayoutContext.tsx
Subscribes to Android keyboard visibility/height, passes keyboardHeight into calculateHeightStyle, adjusts waveViewStyle and capSpace based on keyboard state; calculateHeightStyle signature gains optional keyboardHeight and subtracts it from computed heights.
Hook refactor / Capacitor integration
hooks/useAndroidKeyboard.ts
Simplified hook API (removed debounce param), replaced DOM-heavy logic with Capacitor keyboardWillShow/keyboardWillHide listeners, streamlined lifecycle/cleanup, and updated exported types to use CSSProperties; getContainerStyle adjusted accordingly.
Tests updated / expanded mocks
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx, __tests__/components/waves/drop/SingleWaveDropChat.test.tsx, __tests__/hooks/useAndroidKeyboard.test.ts
Introduced configurable mocks for Capacitor and keyboard state, added tests for keyboard-visible/hidden layouts and getContainerStyle behavior, adjusted environment/setup (rAF, ResizeObserver, globalThis.innerHeight).

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Capacitor as Capacitor Keyboard
    participant Hook as useAndroidKeyboard
    participant Layout as LayoutContext
    participant Component as BrainContent / MyStreamWaveChat

    Note over Capacitor,Hook: Android keyboard events via Capacitor
    Capacitor->>Hook: keyboardWillShow(height)
    Hook->>Hook: update isAndroid, keyboardHeight
    Hook->>Layout: expose keyboard state (isVisible, keyboardHeight)
    Layout->>Layout: calculateHeightStyle(..., keyboardHeight)
    Layout->>Component: provide updated waveViewStyle / container style
    Component->>Component: render with adjusted layout

    Capacitor->>Hook: keyboardWillHide()
    Hook->>Hook: set keyboardHeight = 0, isVisible = false
    Hook->>Layout: notify keyboard state change
    Layout->>Component: recalc and render restored layout
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay extra attention to:
    • components/brain/my-stream/layout/LayoutContext.tsx: height math, dependency arrays, capSpace edge cases when keyboardVisible toggles.
    • hooks/useAndroidKeyboard.ts: listener registration/removal, CSS variable side effects, and type changes for getContainerStyle.
    • Tests: ensure mocks correctly simulate Capacitor behavior and validate no remaining callers expect removed props.

Suggested reviewers

  • simo6529
  • prxt6529

Poem

🐇
I nudged the keys and cleared the trail,
One flow now guides the windy gale,
Fewer hops and neater maps,
Waves settle in their tidy gaps,
Carrots safe — the layout hale. 🥕

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'android keyboard bug fix' directly relates to the main change: refactoring Android keyboard handling across multiple components and hooks to use Capacitor's keyboard API instead of the previous debounced detection logic.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch android-keyboard-bug

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.

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: 1

Caution

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

⚠️ Outside diff range comments (1)
components/brain/my-stream/layout/LayoutContext.tsx (1)

401-434: Update myVotesViewStyle to account for keyboard height on mobile.

The myVotes view contains an input field that triggers the keyboard on mobile, but myVotesViewStyle passes 0 for keyboard height to calculateHeightStyle (line 413). Unlike waveViewStyle, it doesn't account for isAndroidKeyboardVisible or keyboardHeight. Apply the same keyboard-aware adjustment pattern used in waveViewStyle to prevent the input field from being obscured when the keyboard opens.

🧹 Nitpick comments (1)
components/brain/my-stream/layout/LayoutContext.tsx (1)

65-78: Consider documenting the keyboardHeight parameter.

The new keyboardHeight parameter defaults to 0, which maintains backward compatibility. However, adding a brief JSDoc comment would clarify its purpose for future maintainers:

 // Helper function to calculate height style
+/**
+ * @param keyboardHeight - Height of the on-screen keyboard (Android only); subtracted from available height when keyboard is visible
+ */
 const calculateHeightStyle = (
   view: View,
   spaces: LayoutSpaces,
   capacitorSpace: number, // Accept specific space value
   keyboardHeight: number = 0 // Keyboard height when visible
 ): React.CSSProperties => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdcd5e7 and 16aec31.

📒 Files selected for processing (4)
  • components/brain/content/BrainContent.tsx (2 hunks)
  • components/brain/my-stream/MyStreamWaveChat.tsx (1 hunks)
  • components/brain/my-stream/layout/LayoutContext.tsx (4 hunks)
  • hooks/useAndroidKeyboard.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/brain/content/BrainContent.tsx
  • hooks/useAndroidKeyboard.ts
  • components/brain/my-stream/layout/LayoutContext.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always add readonly before props in React components

Files:

  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/brain/content/BrainContent.tsx
  • components/brain/my-stream/layout/LayoutContext.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/brain/content/BrainContent.tsx
  • hooks/useAndroidKeyboard.ts
  • components/brain/my-stream/layout/LayoutContext.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/brain/content/BrainContent.tsx
  • hooks/useAndroidKeyboard.ts
  • components/brain/my-stream/layout/LayoutContext.tsx
🧠 Learnings (4)
📚 Learning: 2025-12-03T14:52:34.255Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.255Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.255Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.255Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-05T10:55:30.859Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.859Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.255Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.255Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)

Applied to files:

  • hooks/useAndroidKeyboard.ts
🧬 Code graph analysis (1)
components/brain/my-stream/layout/LayoutContext.tsx (1)
hooks/useAndroidKeyboard.ts (1)
  • useAndroidKeyboard (14-84)
⏰ 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 (4)
components/brain/my-stream/MyStreamWaveChat.tsx (1)

70-70: LGTM!

The simplification to use waveViewStyle directly from LayoutContext is clean. The fallback to an empty object is appropriate for cases where the context hasn't completed measurements yet.

components/brain/content/BrainContent.tsx (1)

28-29: LGTM!

The removal of keyboard-specific handling from this component aligns with the centralization of Android keyboard logic into LayoutContext. The component now focuses on its primary layout responsibilities without keyboard concerns.

Also applies to: 62-62

hooks/useAndroidKeyboard.ts (1)

71-78: LGTM on transform composition logic.

The approach to preserve existing baseStyle.transform while appending the keyboard offset translation is correct. The trim and conditional undefined fallback handle edge cases well.

components/brain/my-stream/layout/LayoutContext.tsx (1)

381-399: LGTM on centralized keyboard handling.

The keyboard-aware layout logic is well-implemented:

  • capSpace correctly toggles between 0 (keyboard open) and 128 (keyboard closed) for Android
  • kbHeight properly subtracts the keyboard height from the visible area
  • Dependencies are complete and accurate

Comment thread hooks/useAndroidKeyboard.ts
Signed-off-by: ragnep <ragneinfo@gmail.com>
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

🧹 Nitpick comments (1)
hooks/useAndroidKeyboard.ts (1)

21-67: Well-implemented listener lifecycle with mounted flag pattern.

The mounted flag correctly addresses the potential cleanup race condition identified in previous reviews. The async setup properly handles the case where unmount occurs during addListener awaits by immediately removing the listeners.

One minor note: line 33 uses info.keyboardHeight || 300, which treats 0 as falsy. While unlikely in a keyboardWillShow event, if the API ever returns 0, it would default to 300px. Consider using nullish coalescing (??) if you want to only fall back when the value is null/undefined:

-          const height = info.keyboardHeight || 300;
+          const height = info.keyboardHeight ?? 300;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16aec31 and 3b0688d.

📒 Files selected for processing (1)
  • hooks/useAndroidKeyboard.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • hooks/useAndroidKeyboard.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • hooks/useAndroidKeyboard.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • hooks/useAndroidKeyboard.ts
🧠 Learnings (4)
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)

Applied to files:

  • hooks/useAndroidKeyboard.ts
⏰ 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 (5)
hooks/useAndroidKeyboard.ts (5)

1-12: LGTM!

Clean imports using direct named imports from React (including type-only import for CSSProperties) and well-defined interface. Follows the coding guidelines.


14-19: LGTM!

The simplified hook signature (removing the debounce parameter) aligns with the leaner Capacitor-driven approach. The platform detection values are stable after hydration.


69-90: LGTM!

The getContainerStyle callback properly composes transforms while preserving existing baseStyle values. The use of nullish coalescing (??) for the transition default correctly respects explicit empty strings in baseStyle.transition. Dependencies in useCallback are complete.


92-93: LGTM!

Return object matches the AndroidKeyboardHookReturn interface correctly.


4-5: The imports are compatible with @capacitor/keyboard v2.0.3. The keyboardWillShow and keyboardWillHide event listeners and the addListener async API are fully supported. No changes needed.

Signed-off-by: ragnep <ragneinfo@gmail.com>
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

♻️ Duplicate comments (1)
hooks/useAndroidKeyboard.ts (1)

32-43: Listener callbacks still lack mounted guards.

The mounted flag pattern was added for the async setup completion check (lines 46-50), but the listener callbacks themselves don't check mounted before calling setState. If the keyboard events fire after unmount but before cleanup executes, state updates will still be attempted.

The previous review suggested adding guards inside the callbacks:

 const showListener = await Keyboard.addListener('keyboardWillShow', (info) => {
+  if (!mounted) return;
   const height = info.keyboardHeight ?? 300;
   setKeyboardHeight(height);
   setIsVisible(true);
   document.documentElement.style.setProperty('--android-keyboard-height', `${height}px`);
 });

 const hideListener = await Keyboard.addListener('keyboardWillHide', () => {
+  if (!mounted) return;
   setKeyboardHeight(0);
   setIsVisible(false);
   document.documentElement.style.setProperty('--android-keyboard-height', '0px');
 });
🧹 Nitpick comments (1)
hooks/useAndroidKeyboard.ts (1)

45-45: Remove explanatory comment per coding guidelines.

Code should be self-explanatory without comments. The if (!mounted) pattern is clear enough.

-        // If unmounted during async setup, remove listeners immediately
         if (!mounted) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b0688d and 80e5940.

📒 Files selected for processing (1)
  • hooks/useAndroidKeyboard.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • hooks/useAndroidKeyboard.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • hooks/useAndroidKeyboard.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • hooks/useAndroidKeyboard.ts
🧠 Learnings (4)
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks

Applied to files:

  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)

Applied to files:

  • hooks/useAndroidKeyboard.ts
⏰ 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 (3)
hooks/useAndroidKeyboard.ts (3)

3-12: LGTM!

Clean type-only import for CSSProperties and well-defined interface matching the simplified API.


69-90: LGTM!

Clean implementation with proper transform composition and correct nullish coalescing for preserving existing transitions. Dependencies are correctly specified.


92-93: LGTM!

Return value correctly matches the AndroidKeyboardHookReturn interface with the simplified API.

analyticsflowee
analyticsflowee previously approved these changes Dec 9, 2025
Signed-off-by: ragnep <ragneinfo@gmail.com>
Signed-off-by: ragnep <ragneinfo@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Dec 9, 2025

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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80e5940 and 52141e6.

📒 Files selected for processing (4)
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (3 hunks)
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx (3 hunks)
  • __tests__/hooks/useAndroidKeyboard.test.ts (1 hunks)
  • hooks/useAndroidKeyboard.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always add readonly before props in React components

Files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧠 Learnings (11)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/hooks/useAndroidKeyboard.test.ts
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
  • hooks/useAndroidKeyboard.ts
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/__tests__/**/*.{ts,tsx} : Place tests in `__tests__/` directory or as `ComponentName.test.tsx` alongside components

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧬 Code graph analysis (1)
__tests__/hooks/useAndroidKeyboard.test.ts (1)
hooks/useAndroidKeyboard.ts (1)
  • useAndroidKeyboard (14-95)
🪛 GitHub Check: SonarCloud Code Analysis
__tests__/hooks/useAndroidKeyboard.test.ts

[warning] 177-177: Remove this useless assignment to variable "result".

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIXPaenwMPeGB3X&open=AZsCwxIXPaenwMPeGB3X&pullRequest=1638


[warning] 197-197: Remove this useless assignment to variable "initialState".

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIXPaenwMPeGB3Y&open=AZsCwxIXPaenwMPeGB3Y&pullRequest=1638

__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx

[warning] 2-2: Remove this unused import of 'act'.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIKPaenwMPeGB3S&open=AZsCwxIKPaenwMPeGB3S&pullRequest=1638


[warning] 89-89: Prefer globalThis over window.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIKPaenwMPeGB3U&open=AZsCwxIKPaenwMPeGB3U&pullRequest=1638


[warning] 74-74: Prefer globalThis over window.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIKPaenwMPeGB3T&open=AZsCwxIKPaenwMPeGB3T&pullRequest=1638


[warning] 105-105: Prefer globalThis over window.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIKPaenwMPeGB3V&open=AZsCwxIKPaenwMPeGB3V&pullRequest=1638


[warning] 120-120: Prefer globalThis over window.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxIKPaenwMPeGB3W&open=AZsCwxIKPaenwMPeGB3W&pullRequest=1638

__tests__/components/waves/drop/SingleWaveDropChat.test.tsx

[warning] 27-27: Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxEcPaenwMPeGB3Q&open=AZsCwxEcPaenwMPeGB3Q&pullRequest=1638


[warning] 1-1: Remove this unused import of 'screen'.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxEcPaenwMPeGB3P&open=AZsCwxEcPaenwMPeGB3P&pullRequest=1638


[warning] 27-27: Visible, non-interactive elements with click handlers must have at least one keyboard listener.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZsCwxEcPaenwMPeGB3R&open=AZsCwxEcPaenwMPeGB3R&pullRequest=1638

🔇 Additional comments (6)
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (2)

5-16: Keyboard/layout mocks and platform‑specific tests look solid.

Configurable useCapacitor / useAndroidKeyboard mocks plus the new Android/iOS/desktop scenarios give good coverage of the layout behavior without leaking implementation details. The beforeEach reset pattern is sound, and the assertions on content.style.height match the intended capSpace/keyboardHeight semantics.

Also applies to: 33-37, 70-130


2-2: Remove incorrect review comment—act is not imported.

The file already shows import { render, screen } from '@testing-library/react' on line 2 without act. No changes needed.

Likely an incorrect or invalid review comment.

__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (2)

8-20: Keyboard visibility/padding tests are well‑structured.

The configurable useAndroidKeyboard mock plus mockKeyboardVisible/mockGetContainerStyle let you assert the exact style payload and adjustment argued into getContainerStyle. The two new tests correctly distinguish between keyboard‑visible (paddingBottom: '0px') and keyboard‑hidden (calc(env(safe-area-inset-bottom))) cases.

Also applies to: 45-96


1-1: The review comment does not require changes—the file already implements the suggested improvements. The screen import is not present (the current imports are correctly: render, fireEvent, act), and the PrivilegedDropCreator mock already includes accessibility attributes (role="button", tabIndex={0}, and onKeyDown handler for keyboard support), satisfying a11y requirements without conversion to a native <button> element.

__tests__/hooks/useAndroidKeyboard.test.ts (1)

1-166: Comprehensive hook coverage and style assertions look good.

The rest of the suite—platform/plugin gating, show/hide events (including null/undefined heights), CSS variable updates, getContainerStyle transform/transition behavior, and listener/variable cleanup—matches the implementation in hooks/useAndroidKeyboard.ts and provides strong regression coverage for Android keyboard behavior.

Also applies to: 217-348

hooks/useAndroidKeyboard.ts (1)

3-95: Hook refactor and listener lifecycle look correct and test‑aligned.

The refactored useAndroidKeyboard:

  • Correctly gates on isSSR/isAndroid, and checks Capacitor.isPluginAvailable('Keyboard').
  • Uses mounted plus showCleanup/hideCleanup to handle async Keyboard.addListener and ensure listeners are removed both on normal unmount and when setup completes after unmount.
  • Updates --android-keyboard-height consistently on show/hide and cleanup.
  • Provides getContainerStyle that respects existing transform/transition and only applies a translateY when the keyboard is visible with positive effective height.

This matches the behavior asserted in __tests__/hooks/useAndroidKeyboard.test.ts and the layout/component tests that depend on keyboardHeight and getContainerStyle.

Comment thread __tests__/hooks/useAndroidKeyboard.test.ts
Comment thread __tests__/hooks/useAndroidKeyboard.test.ts
Signed-off-by: ragnep <ragneinfo@gmail.com>
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: 1

🧹 Nitpick comments (6)
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (4)

5-16: Well-structured mocks for platform and keyboard testing.

The configurable mock pattern using let bindings is correct and allows per-test state configuration. The mock functions properly reference these variables via closure.

Optional: Remove explanatory comments.

The comments on lines 5 and 12 describe what the code already shows. Per coding guidelines, comments should be omitted in favor of self-explanatory code.

Apply this diff to remove the comments:

-// Mock useCapacitor hook with configurable values
 let mockCapacitorValues = { isCapacitor: false, isAndroid: false, isIos: false };
 jest.mock('@/hooks/useCapacitor', () => ({
   __esModule: true,
   default: () => mockCapacitorValues
 }));

-// Mock useAndroidKeyboard hook with configurable values
 let mockKeyboardValues = { isVisible: false, keyboardHeight: 0, isAndroid: false, getContainerStyle: jest.fn() };
 jest.mock('@/hooks/useAndroidKeyboard', () => ({
   useAndroidKeyboard: () => mockKeyboardValues
 }));

33-37: Good test isolation with beforeEach.

Resetting mock values before each test ensures proper isolation between test cases.

Optional: Remove explanatory comment.

Per coding guidelines, the comment on line 34 can be removed as beforeEach semantics are self-evident.

Apply this diff:

 beforeEach(() => {
-  // Reset mocks before each test
   mockCapacitorValues = { isCapacitor: false, isAndroid: false, isIos: false };
   mockKeyboardValues = { isVisible: false, keyboardHeight: 0, isAndroid: false, getContainerStyle: jest.fn() };
 });

70-99: Excellent coverage of Android keyboard behavior.

Both test cases correctly simulate Android platform states and verify that:

  • 128px capSpace is applied when keyboard is closed
  • Keyboard height is subtracted and capSpace is removed when keyboard is open

The assertions properly match the LayoutContext logic described in the relevant snippets.

Optional: Remove assertion comments.

Lines 81 and 96 contain comments that restate what the assertions already express clearly.

Apply this diff:

     const content = screen.getByTestId('content');
-    // Should include 128px capSpace
     expect(content.style.height).toContain('- 128px');
   });

   it('removes capSpace and subtracts keyboard height on Android when keyboard is open', () => {
     mockCapacitorValues = { isCapacitor: true, isAndroid: true, isIos: false };
     mockKeyboardValues = { isVisible: true, keyboardHeight: 350, isAndroid: true, getContainerStyle: jest.fn() };

     Object.defineProperty(globalThis, 'innerHeight', { value: 1000, configurable: true });
     render(
       <LayoutProvider>
         <TestComponent />
       </LayoutProvider>
     );
     const content = screen.getByTestId('content');
-    // Should subtract keyboard height (350px) but not capSpace
     expect(content.style.height).toContain('- 350px');
     expect(content.style.height).not.toContain('- 128px');

101-130: Comprehensive platform coverage with iOS and desktop tests.

The tests correctly verify that:

  • iOS applies 20px capSpace
  • Desktop applies no capSpace

This completes comprehensive platform coverage alongside the Android tests.

Optional: Remove assertion comments.

Lines 112 and 127 contain comments that duplicate what the assertions clearly express.

Apply this diff:

     const content = screen.getByTestId('content');
-    // Should include 20px capSpace for iOS
     expect(content.style.height).toContain('- 20px');
   });

   it('does not apply capSpace on desktop', () => {
     mockCapacitorValues = { isCapacitor: false, isAndroid: false, isIos: false };
     mockKeyboardValues = { isVisible: false, keyboardHeight: 0, isAndroid: false, getContainerStyle: jest.fn() };

     Object.defineProperty(globalThis, 'innerHeight', { value: 1000, configurable: true });
     render(
       <LayoutProvider>
         <TestComponent />
       </LayoutProvider>
     );
     const content = screen.getByTestId('content');
-    // Should not include any capSpace
     expect(content.style.height).not.toContain('- 128px');
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (2)

8-19: Remove comment; consider stronger typing.

Line 8 violates the guideline that code should be self-explanatory without comments. The mock variable names and setup are clear enough without the comment.

Additionally, baseStyle: any on line 10 could use a more specific type like React.CSSProperties or an interface matching the expected style object.

Apply this diff:

-// Mock useAndroidKeyboard with configurable values
 let mockKeyboardVisible = false;
-let mockGetContainerStyle = jest.fn((baseStyle: any) => baseStyle);
+let mockGetContainerStyle = jest.fn((baseStyle: React.CSSProperties) => baseStyle);

As per coding guidelines, "Do not include any comments in the code; it should be self-explanatory" applies to all TypeScript files.


82-96: Remove comment; consider behavior-focused testing.

The test logic appears consistent (second argument is 0 when keyboard is hidden), but the comment on line 89 should be removed per the coding guideline.

Consider refactoring both keyboard tests to verify the actual rendered styles or DOM attributes instead of asserting on mock function calls. Testing implementation details (how getContainerStyle is called) is more brittle than testing user-visible behavior (what padding is actually applied to the DOM).

Apply this diff to remove the comment:

-    // getContainerStyle should have been called with paddingBottom: safe-area-inset-bottom
     expect(mockGetContainerStyle).toHaveBeenCalledWith(

As per coding guidelines, code should be self-explanatory without comments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52141e6 and 7e81994.

📒 Files selected for processing (3)
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (4 hunks)
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx (3 hunks)
  • __tests__/hooks/useAndroidKeyboard.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/hooks/useAndroidKeyboard.test.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version

**/*.{ts,tsx,js,jsx}: Replace <img> elements with <Image /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always add readonly before props in React components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use <Link>, images should use next/image, and adopt Next's ESLint rules (Core Web Vitals)

**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage (React.useMemo, React.useRef, etc.)
If the react-hooks/exhaustive-deps lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in useEffectEvent

**/*.{ts,tsx}: Must pass tsc --noEmit for TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for images, adopt Next's ESLint rules
Use 'use cache' directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace <img> elements with <Image /> from next/image
Use <Link href="/path"> for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with 'use server' directive

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
🧠 Learnings (7)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Applied to files:

  • __tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
⏰ 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 (2)
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (1)

59-59: Correct use of globalThis in test environment.

Using globalThis.innerHeight instead of window.innerHeight is appropriate for Node.js/Jest environments.

__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (1)

45-49: LGTM!

The beforeEach hook properly resets mock state to prevent test pollution. This ensures each test starts with a clean, predictable state.

Comment thread __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
@ragnep ragnep merged commit 4146890 into main Dec 10, 2025
9 checks passed
@ragnep ragnep deleted the android-keyboard-bug branch December 10, 2025 07:29
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.

3 participants