Skip to content

fix(react-dogfood): correct closed captions capability checks - #2365

Merged
oliverlaz merged 1 commit into
mainfrom
fix/dogfood-closed-captions-capabilities
Aug 12, 2026
Merged

fix(react-dogfood): correct closed captions capability checks#2365
oliverlaz merged 1 commit into
mainfrom
fix/dogfood-closed-captions-capabilities

Conversation

@oliverlaz

@oliverlaz oliverlaz commented Aug 12, 2026

Copy link
Copy Markdown
Member

💡 Overview

The closed captions button in the react-dogfood call controls was gated on both START_CLOSED_CAPTIONS_CALL and STOP_CLOSED_CAPTIONS_CALL at once. useHasPermissions uses .every(), so a user holding only one of the two grants saw a permanently disabled button. The call's transcription.closed_caption_mode was never consulted either, so the button looked actionable even when captions are disabled for the call type — clicking it just failed server-side.

📝 Implementation notes

  • canStart / canStop are now checked separately; canToggle picks the one matching the current captioning state.
  • Added the closed_caption_mode !== 'disabled' gate, matching the settings-plus-capability pattern in NoiseCancellationProvider.
  • The button is hidden when captions are disabled for the call or the user holds neither grant, and stays rendered-but-disabled in the asymmetric case (captions running, user may start but not stop) so it doesn't vanish mid-call.

Verified with tsc --noEmit and eslint. Not exercised in a browser: the interesting branches need a call type with closed_caption_mode: disabled and a role missing one of the two grants, which the default dogfood login doesn't reproduce.

🎫 Ticket: https://linear.app/stream/issue/REACT-1077

Summary by CodeRabbit

  • Bug Fixes
    • Improved closed-caption controls to reflect the action currently available.
    • Disabled the control when the required permission is unavailable.
    • Hid the control when closed captions are disabled or inaccessible.

The closed captions toggle checked START_CLOSED_CAPTIONS_CALL and
STOP_CLOSED_CAPTIONS_CALL together. useHasPermissions requires all
listed capabilities, so a user holding only one of the two grants got a
permanently disabled button and could never start captions.

Check the two grants independently and pick the one matching the current
captioning state. Also gate on transcription.closed_caption_mode, and
hide the button entirely when captions are disabled for the call or the
user holds neither grant.
@oliverlaz
oliverlaz requested a review from jdimovska August 12, 2026 12:24
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The closed captions button now checks whether captions are enabled, evaluates start and stop permissions separately, and sets its disabled state based on the required action.

Changes

Closed captions controls

Layer / File(s) Summary
Permission-aware captions button
sample-apps/react/react-dogfood/components/ClosedCaptions.tsx
The component uses the closed-caption mode enum. It hides the button when captions are disabled or no relevant permission exists. It selects start or stop permission based on the current captioning state.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: santhoshvai

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the correction to closed captions capability checks.
Description check ✅ Passed The description includes the overview, implementation notes, ticket, validation results, and testing limitation; only the optional Docs link is missing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dogfood-closed-captions-capabilities

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.

@github-actions

Copy link
Copy Markdown

Bundle size

Built package output. Sizes in KB; delta vs main@e52384b.

No significant package size increase vs main.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sample-apps/react/react-dogfood/components/ClosedCaptions.tsx`:
- Around line 24-28: Update the isClosedCaptionsEnabled/render guard in
ClosedCaptions so closed captions remain hidden while settings is null or
undefined, requiring loaded settings before evaluating closed_caption_mode;
preserve the existing disabled-mode and canStart/canStop checks, and add a
regression test covering the initial unloaded settings state.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 961ec12c-3d04-4dba-aa26-217a7c55d66d

📥 Commits

Reviewing files that changed from the base of the PR and between e52384b and 3aca673.

📒 Files selected for processing (1)
  • sample-apps/react/react-dogfood/components/ClosedCaptions.tsx

Comment on lines +24 to +28
const isClosedCaptionsEnabled =
settings?.transcription.closed_caption_mode !==
TranscriptionSettingsResponseClosedCaptionModeEnum.DISABLED;

if (!isClosedCaptionsEnabled || (!canStart && !canStop)) return null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 12 \
  '\b(useCallSettings|closed_caption_mode|ToggleClosedCaptionsButton)\b' \
  packages/react-sdk packages/client sample-apps/react/react-dogfood \
  --glob '*.{ts,tsx}'

Repository: GetStream/stream-video-js

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- ClosedCaptions component ---'
sed -n '1,130p' sample-apps/react/react-dogfood/components/ClosedCaptions.tsx

printf '%s\n' '--- useCallSettings definitions and state selectors ---'
rg -n -C 8 \
  'useCallSettings|callSettings|settings\??:' \
  packages/react-sdk/src \
  --glob '*.{ts,tsx}' \
  | head -n 500

printf '%s\n' '--- Call context mounting and call lifecycle around ActiveCall ---'
rg -n -C 8 \
  'ActiveCall|StreamCall|StreamVideo|call\.join|callingState|CallState' \
  sample-apps/react/react-dogfood \
  --glob '*.{ts,tsx}' \
  | head -n 500

Repository: GetStream/stream-video-js

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Exact useCallSettings implementation ---'
rg -l 'useCallSettings' packages/react-sdk/src --glob '*.{ts,tsx}' |
  while IFS= read -r file; do
    if rg -q 'useCallSettings' "$file"; then
      printf '\n### %s\n' "$file"
      rg -n -C 15 'useCallSettings' "$file"
    fi
  done

printf '%s\n' '--- ActiveCall render conditions ---'
rg -n -C 15 \
  'export const ActiveCall|<ActiveCall|ToggleClosedCaptionsButton|CallingState|call\.get|getOrCreate' \
  sample-apps/react/react-dogfood/components/ActiveCall.tsx \
  sample-apps/react/react-dogfood/pages \
  --glob '*.{ts,tsx}' \
  | head -n 700

printf '%s\n' '--- Tests for call settings and closed captions ---'
rg -n -C 10 \
  'useCallSettings|ClosedCaptions|closed_caption_mode|START_CLOSED_CAPTIONS_CALL|STOP_CLOSED_CAPTIONS_CALL' \
  packages/react-sdk sample-apps/react/react-dogfood \
  --glob '*.{test,spec}.{ts,tsx}' \
  --glob '*__tests__*'

Repository: GetStream/stream-video-js

Length of output: 43728


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Call-state hook factory and selector source ---'
rg -n -C 12 \
  'useCallStateHooks|CallStateHooks|useCallSettings|callSettings' \
  packages \
  --glob '*.{ts,tsx}' \
  --glob '!**/gen/**' \
  --glob '!**/__tests__/data.ts' \
  | grep -E '(^[^-].*|useCallStateHooks|CallStateHooks|useCallSettings|callSettings)' \
  | head -n 800

printf '%s\n' '--- All files that define or export call-state hooks ---'
rg -l \
  'useCallStateHooks|useCallSettings' \
  packages \
  --glob '*.{ts,tsx}' \
  --glob '!**/gen/**' \
  | sort

printf '%s\n' '--- Call state initialization and settings loading ---'
rg -n -C 12 \
  'settings:|callSettings|call\.get\(|call\.getOrCreate\(|getOrCreate\(' \
  packages/client/src \
  --glob '*.{ts,tsx}' \
  | head -n 800

Repository: GetStream/stream-video-js

Length of output: 50383


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Candidate binding and call-state files ---'
git ls-files | rg \
  '(^|/)(react-bindings|.*CallState.*|.*call.*state.*|.*hooks.*)\.(ts|tsx)$' \
  | head -n 300

printf '%s\n' '--- Hook factory declarations and exports ---'
rg -n \
  'export .*useCallStateHooks|function useCallStateHooks|const useCallStateHooks|create.*Call.*State|CallState.*Hooks' \
  . \
  --glob '*.{ts,tsx}' \
  --glob '!**/gen/**' \
  --glob '!**/node_modules/**' \
  --glob '!**/dist/**' \
  --glob '!**/build/**' \
  | head -n 300

printf '%s\n' '--- Call settings state assignments ---'
rg -n -C 8 \
  'callState\.settings|state\.settings|settings\s*=' \
  packages/client/src \
  --glob '*.{ts,tsx}' \
  | head -n 400

Repository: GetStream/stream-video-js

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- useCallSettings selector ---'
rg -n -C 12 \
  'useCallSettings|settings\$|settings' \
  packages/react-bindings/src/hooks/callStateHooks.ts

printf '%s\n' '--- CallState settings declaration and updates ---'
rg -n -C 15 \
  'settings|callSettings|call\.settings' \
  packages/client/src/store/CallState.ts

printf '%s\n' '--- Call get/getOrCreate state hydration ---'
rg -n -C 15 \
  'getOrCreate|get\(|settings' \
  packages/client/src/Call.ts \
  packages/client/src \
  --glob '*Call*.ts' \
  | head -n 600

Repository: GetStream/stream-video-js

Length of output: 50381


Require loaded call settings before rendering closed captions.

settings$ starts as undefined and receives data only after get() or getOrCreate() updates call state. The current comparison enables the control during this interval. Require settings != null before evaluating closed_caption_mode, and add a regression test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sample-apps/react/react-dogfood/components/ClosedCaptions.tsx` around lines
24 - 28, Update the isClosedCaptionsEnabled/render guard in ClosedCaptions so
closed captions remain hidden while settings is null or undefined, requiring
loaded settings before evaluating closed_caption_mode; preserve the existing
disabled-mode and canStart/canStop checks, and add a regression test covering
the initial unloaded settings state.

Source: MCP tools

@oliverlaz
oliverlaz merged commit 425b5c7 into main Aug 12, 2026
13 of 17 checks passed
@oliverlaz
oliverlaz deleted the fix/dogfood-closed-captions-capabilities branch August 12, 2026 12:41
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.

1 participant