Skip to content

Add selectable webcam layout presets (Picture in Picture, Vertical Stack)#241

Merged
siddharthvaddem merged 5 commits intosiddharthvaddem:mainfrom
marcusschiesser:codex/add-multiple-layout-presets-for-video
Mar 19, 2026
Merged

Add selectable webcam layout presets (Picture in Picture, Vertical Stack)#241
siddharthvaddem merged 5 commits intosiddharthvaddem:mainfrom
marcusschiesser:codex/add-multiple-layout-presets-for-video

Conversation

@marcusschiesser
Copy link
Contributor

@marcusschiesser marcusschiesser commented Mar 19, 2026

Description

  • add selectable webcam layout presets to the video editor: Picture in Picture and Vertical Stack
  • move the layout preset selector into a dedicated Layout accordion above Video Effects
  • center the combined screencast + webcam stack for Vertical Stack in both preview and export
  • improve camera permission handling in the launch/recording flow

Motivation

  • allows to do 9:16 screencasts for youtube shorts, tiktok etc.
  • easy to add more presets

Type of Change

  • New Feature
  • Bug Fix
  • Refactor / Code Cleanup
  • Documentation Update
  • Other (please specify)

Screenshots / Video

Screenshot:

Vertical-Stack layout:
image

PIP layout (existing choice):
image

New Selector:
image

Testing

  • add recording with webcam, test different layout options

Checklist

  • I have performed a self-review of my code.
  • I have added any necessary screenshots or videos.

Summary by CodeRabbit

  • New Features

    • Added webcam layout presets (picture-in-picture, vertical-stack) for flexible video composition and export.
    • Improved camera permission flow with a unified request helper.
    • Integrated app-wide notifications for clearer user messaging.
  • Tests

    • Added composite layout tests; removed legacy overlay tests.
  • Chores

    • Updated Node.js to 22.22.1 and npm to 10.9.4.

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

Updates Node/npm versions and adds a preset-driven webcam layout system with unified camera-permission handling; threads webcam layout preset through editor state, UI, playback, exporters, and rendering while replacing the old overlay module and tests.

Changes

Cohort / File(s) Summary
Version Management
\.nvmrc, package.json
Bumped Node to 22.22.1, npm to 10.9.4; added packageManager and engines entries.
Composite Layout Library & Tests
src/lib/compositeLayout.ts, src/lib/compositeLayout.test.ts
Added new composite layout module (WebcamLayoutPreset, layout computation, helpers) and comprehensive unit tests for computeCompositeLayout.
Removed Legacy Overlay
src/lib/webcamOverlay.ts, src/lib/webcamOverlay.test.ts
Deleted legacy computeWebcamOverlayLayout and its tests (superseded by composite layout).
Camera Access Helper
src/lib/requestCameraAccess.ts
New cross-platform camera permission helper returning structured CameraAccessResult.
Screen Recorder Hook
src/hooks/useScreenRecorder.ts
Replaced local preflight media probe with requestCameraAccess() and simplified setWebcamEnabled flow.
App & Launch Integrations
src/App.tsx, src/components/launch/LaunchWindow.tsx
Moved Toaster to root App; LaunchWindow triggers dev-mode camera request on mount and uses async webcam toggle handler.
Settings UI
src/components/video-editor/SettingsPanel.tsx
Added conditional "Layout" accordion for webcam layouts, Select for presets, and new props (hasWebcam, webcamLayoutPreset, onWebcamLayoutPresetChange).
Editor State & Persistence
src/components/video-editor/types.ts, src/components/video-editor/projectPersistence.ts, src/components/video-editor/projectPersistence.test.ts, src/hooks/useEditorHistory.ts
Added and normalized webcamLayoutPreset across types, project persistence, tests, and undo history (INITIAL_EDITOR_STATE).
Video Playback & Layout Utils
src/components/video-editor/VideoPlayback.tsx, src/components/video-editor/videoPlayback/layoutUtils.ts
Switched to preset-driven layout: require webcamLayoutPreset prop, remove ResizeObserver-driven stage sizing, use computeCompositeLayout results for mask and webcam rects, and apply preset box-shadow.
Video Editor Integration
src/components/video-editor/VideoEditor.tsx
Threaded webcamLayoutPreset through editor state, settings panel, playback, exporters, and removed local Toaster from editor.
Frame Rendering & Exporters
src/lib/exporter/frameRenderer.ts, src/lib/exporter/gifExporter.ts, src/lib/exporter/videoExporter.ts
Refactored renderers/exporters to accept webcamSize and webcamLayoutPreset; FrameRenderer now calls computeCompositeLayout and renders webcam only when layout present, using preset shadow rules.
Tests Updated/Added
src/components/video-editor/projectPersistence.test.ts, src/lib/compositeLayout.test.ts
Added composite layout tests and updated project persistence fixture to include webcamLayoutPreset.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as VideoEditor/UI
  participant Hook as useScreenRecorder
  participant Helper as requestCameraAccess
  participant State as EditorState
  participant Renderer as FrameRenderer
  participant Exporter as Exporter (GIF/MP4)

  User->>UI: toggle webcam
  UI->>Hook: setWebcamEnabled(true)
  Hook->>Helper: requestCameraAccess()
  Helper-->>Hook: CameraAccessResult
  Hook-->>UI: webcam enabled state update
  UI->>State: pushState(webcamLayoutPreset)
  UI->>Renderer: renderFrame(webcamFrame, webcamSize, webcamLayoutPreset)
  Renderer->>Renderer: computeCompositeLayout(canvas, screen, webcamSize, preset)
  Renderer-->>UI: computed layout (screenRect, webcamRect)
  UI->>Exporter: export(..., webcamSize, webcamLayoutPreset)
  Exporter->>Renderer: renderFrame(...) (uses composite layout)
  Exporter-->>User: exported asset
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • siddharthvaddem

Poem

🐰 I nudged the presets into their place,
Picture-in-picture or a vertical space.
Permissions asked, layouts drawn right,
From editor state to export flight—
A little hop for smoother video grace. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding selectable webcam layout presets (Picture in Picture and Vertical Stack).
Description check ✅ Passed The PR description covers all major required sections: clear description of changes, motivation for the feature, type of change marked, screenshots/video provided, testing instructions, and checklist items completed.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

return (
<TooltipProvider>
{content}
<Toaster theme="dark" className="pointer-events-auto" />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

bug fix: toaster wasn't working in the control panel - now it is working

@@ -0,0 +1 @@
22.22.1
Copy link
Contributor Author

Choose a reason for hiding this comment

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

now you can use the right node version with nvm use

Comment on lines +6 to +10
"packageManager": "npm@10.9.4",
"engines": {
"node": "22.22.1",
"npm": "10.9.4"
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this prevents generating a new lock file when someone is using npm 11

return "unknown";
}

export async function requestCameraAccess(): Promise<CameraAccessResult> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

centralizes camera access request (electron or navigator)

const MIN_SIZE = 96;
const MAX_BORDER_RADIUS = 24;
const WEBCAM_LAYOUT_PRESET_MAP: Record<WebcamLayoutPreset, WebcamLayoutPresetDefinition> = {
"picture-in-picture": {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

here we can add more presets

@marcusschiesser
Copy link
Contributor Author

@siddharthvaddem good idea with making the webcam layout editable - this PR is starting with some presets - would be great if you can merge it

Copy link

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
src/hooks/useScreenRecorder.ts (1)

161-174: ⚠️ Potential issue | 🟠 Major

Handle requestCameraAccess() exceptions in setWebcamEnabled.
At Line 161, a rejected permission call currently escapes this function, which can skip user-facing error handling and cause unhandled promise rejection behavior in the toggle flow.

💡 Suggested fix
 const setWebcamEnabled = useCallback(async (enabled: boolean) => {
 	if (!enabled) {
 		setWebcamEnabledState(false);
 		return true;
 	}
-
-	const accessResult = await requestCameraAccess();
+	let accessResult;
+	try {
+		accessResult = await requestCameraAccess();
+	} catch (error) {
+		console.error("Failed to request camera access:", error);
+		toast.error("Failed to request camera access.");
+		return false;
+	}
 	if (!accessResult.success) {
 		toast.error("Failed to request camera access.");
 		return false;
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useScreenRecorder.ts` around lines 161 - 174, The setWebcamEnabled
function calls requestCameraAccess without catching rejections, so wrap the
requestCameraAccess call in a try/catch inside setWebcamEnabled; on catch call
toast.error with a user-facing message (and optionally include error.message),
ensure you return false on error, and only call setWebcamEnabledState(true) when
accessResult.success and accessResult.granted are true.
🧹 Nitpick comments (2)
src/components/video-editor/projectPersistence.ts (1)

347-351: Avoid hard-coding the valid preset list here.

This works for the two current presets, but it duplicates the source of truth. When the next preset is added, saved projects will silently normalize back to the default unless this branch is updated too, which undercuts the “easy to add more presets” goal.

♻️ Suggested cleanup
+import { WEBCAM_LAYOUT_PRESETS } from "@/lib/compositeLayout";
+
+const VALID_WEBCAM_LAYOUT_PRESETS = new Set<WebcamLayoutPreset>(
+	WEBCAM_LAYOUT_PRESETS.map(({ value }) => value),
+);
+
+function isWebcamLayoutPreset(value: unknown): value is WebcamLayoutPreset {
+	return (
+		typeof value === "string" &&
+		VALID_WEBCAM_LAYOUT_PRESETS.has(value as WebcamLayoutPreset)
+	);
+}
+
 	return {
 		...
-		webcamLayoutPreset:
-			editor.webcamLayoutPreset === "vertical-stack" ||
-			editor.webcamLayoutPreset === "picture-in-picture"
-				? editor.webcamLayoutPreset
-				: DEFAULT_WEBCAM_LAYOUT_PRESET,
+		webcamLayoutPreset: isWebcamLayoutPreset(editor.webcamLayoutPreset)
+			? editor.webcamLayoutPreset
+			: DEFAULT_WEBCAM_LAYOUT_PRESET,
 		...
 	};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/video-editor/projectPersistence.ts` around lines 347 - 351,
The current normalization for webcamLayoutPreset duplicates the valid-preset
list and will regress when new presets are added; replace the inline boolean
check with a membership test against the single source-of-truth (e.g., an
existing enum/constant like WebcamLayoutPreset or VALID_WEBCAM_LAYOUT_PRESETS)
by importing/using that symbol and testing if editor.webcamLayoutPreset is
included in it, otherwise fall back to DEFAULT_WEBCAM_LAYOUT_PRESET; update the
expression that sets webcamLayoutPreset to use that membership check
(referencing webcamLayoutPreset, editor.webcamLayoutPreset,
DEFAULT_WEBCAM_LAYOUT_PRESET and the central
WebcamLayoutPreset/VALID_WEBCAM_LAYOUT_PRESETS symbol).
src/lib/compositeLayout.test.ts (1)

36-59: Add a 9:16 / mismatched-aspect-ratio stack case.

This test still uses a 16:9 screen and a 16:9 webcam, so it doesn't exercise the normalization path behind the Shorts/TikTok scenario. A portrait screen plus a differently shaped webcam feed would give this change much better regression coverage.

🧪 Example coverage addition
+	it("centers a portrait stack with a non-matching webcam aspect ratio", () => {
+		const layout = computeCompositeLayout({
+			canvasSize: { width: 1080, height: 1920 },
+			maxContentSize: { width: 864, height: 1536 },
+			screenSize: { width: 1080, height: 1920 },
+			webcamSize: { width: 1920, height: 1080 },
+			layoutPreset: "vertical-stack",
+		});
+
+		expect(layout).not.toBeNull();
+		expect(layout?.webcamRect).not.toBeNull();
+		expect(layout?.screenRect.x).toBe(layout?.webcamRect?.x);
+		expect(layout?.screenRect.width).toBe(layout?.webcamRect?.width);
+		const stackTop = layout!.screenRect.y;
+		const stackBottom = layout!.webcamRect!.y + layout!.webcamRect!.height;
+		expect(stackTop).toBe(Math.floor((1920 - (stackBottom - stackTop)) / 2));
+	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/compositeLayout.test.ts` around lines 36 - 59, Add a new unit test
that calls computeCompositeLayout with a portrait (9:16) screenSize and a
mismatched-aspect webcamSize (e.g., screenSize: {width:1080, height:1920},
webcamSize: {width:1280, height:720}), keep layoutPreset: "vertical-stack" and
an appropriate canvasSize/maxContentSize to mimic Shorts/TikTok; assert the
result is not null and that screenRect and webcamRect are positioned stacked
(webcam below screen) and that sizes are normalized to fit maxContentSize (use
the same style of expect checks as the existing "centers the combined screen and
webcam stack in vertical stack mode" test so it exercises the normalization code
path in computeCompositeLayout).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/compositeLayout.ts`:
- Around line 105-108: getWebcamLayoutPresetDefinition currently returns
WEBCAM_LAYOUT_PRESET_MAP[preset] which can be undefined for stale/malformed
persisted presets and later causes computeCompositeLayout to crash on
preset.transform; update getWebcamLayoutPresetDefinition to detect a missing
lookup and return a safe default (use the "picture-in-picture" definition from
WEBCAM_LAYOUT_PRESET_MAP) instead of undefined so callers always receive a valid
WebcamLayoutPresetDefinition.

In `@src/lib/exporter/frameRenderer.ts`:
- Around line 425-430: The composite layout is being computed with a reserved
webcam size even when renderFrame may receive webcamFrame === null, causing
empty webcam slots; update the computeCompositeLayout call in renderFrame to
pass webcamSize as null when webcamFrame is null (e.g., replace the constant
this.config.webcamSize argument with webcamFrame ? this.config.webcamSize :
null) so computeCompositeLayout and downstream compositeWithShadows receive no
webcam space for frames lacking webcam content.

In `@src/lib/requestCameraAccess.ts`:
- Around line 17-22: The IPC call to window.electronAPI.requestCameraAccess can
reject and must be normalized to a CameraAccessResult; wrap the call in a
try/catch inside requestCameraAccess, call await
window.electronAPI.requestCameraAccess() in the try, and on any thrown error
return a CameraAccessResult like { success: false, granted: false, error:
<string or error object> } (preserve existing electronResult fields when
present). Apply the same try/catch normalization pattern to the similar IPC call
in the later block (lines 33-46) so all electron API failures return a
CameraAccessResult rather than throwing.

---

Outside diff comments:
In `@src/hooks/useScreenRecorder.ts`:
- Around line 161-174: The setWebcamEnabled function calls requestCameraAccess
without catching rejections, so wrap the requestCameraAccess call in a try/catch
inside setWebcamEnabled; on catch call toast.error with a user-facing message
(and optionally include error.message), ensure you return false on error, and
only call setWebcamEnabledState(true) when accessResult.success and
accessResult.granted are true.

---

Nitpick comments:
In `@src/components/video-editor/projectPersistence.ts`:
- Around line 347-351: The current normalization for webcamLayoutPreset
duplicates the valid-preset list and will regress when new presets are added;
replace the inline boolean check with a membership test against the single
source-of-truth (e.g., an existing enum/constant like WebcamLayoutPreset or
VALID_WEBCAM_LAYOUT_PRESETS) by importing/using that symbol and testing if
editor.webcamLayoutPreset is included in it, otherwise fall back to
DEFAULT_WEBCAM_LAYOUT_PRESET; update the expression that sets webcamLayoutPreset
to use that membership check (referencing webcamLayoutPreset,
editor.webcamLayoutPreset, DEFAULT_WEBCAM_LAYOUT_PRESET and the central
WebcamLayoutPreset/VALID_WEBCAM_LAYOUT_PRESETS symbol).

In `@src/lib/compositeLayout.test.ts`:
- Around line 36-59: Add a new unit test that calls computeCompositeLayout with
a portrait (9:16) screenSize and a mismatched-aspect webcamSize (e.g.,
screenSize: {width:1080, height:1920}, webcamSize: {width:1280, height:720}),
keep layoutPreset: "vertical-stack" and an appropriate canvasSize/maxContentSize
to mimic Shorts/TikTok; assert the result is not null and that screenRect and
webcamRect are positioned stacked (webcam below screen) and that sizes are
normalized to fit maxContentSize (use the same style of expect checks as the
existing "centers the combined screen and webcam stack in vertical stack mode"
test so it exercises the normalization code path in computeCompositeLayout).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4e14f041-9b29-4a4d-9cb9-b2fa0d5676ec

📥 Commits

Reviewing files that changed from the base of the PR and between 4563641 and c84c244.

📒 Files selected for processing (21)
  • .nvmrc
  • package.json
  • src/App.tsx
  • src/components/launch/LaunchWindow.tsx
  • src/components/video-editor/SettingsPanel.tsx
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/VideoPlayback.tsx
  • src/components/video-editor/projectPersistence.test.ts
  • src/components/video-editor/projectPersistence.ts
  • src/components/video-editor/types.ts
  • src/components/video-editor/videoPlayback/layoutUtils.ts
  • src/hooks/useEditorHistory.ts
  • src/hooks/useScreenRecorder.ts
  • src/lib/compositeLayout.test.ts
  • src/lib/compositeLayout.ts
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/gifExporter.ts
  • src/lib/exporter/videoExporter.ts
  • src/lib/requestCameraAccess.ts
  • src/lib/webcamOverlay.test.ts
  • src/lib/webcamOverlay.ts
💤 Files with no reviewable changes (2)
  • src/lib/webcamOverlay.test.ts
  • src/lib/webcamOverlay.ts

Copy link

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/exporter/frameRenderer.ts`:
- Around line 648-664: The preset shadow is being applied unconditionally;
update the block around
getWebcamLayoutPresetDefinition(this.config.webcamLayoutPreset) so that you only
set ctx.shadowColor/blur/offsetX/offsetY when the export shadow controls allow
it — e.g., check this.config.showShadow is true and this.config.shadowIntensity
> 0 before applying preset.shadow, and scale preset.shadow.blur/intensity by
this.config.shadowIntensity when setting ctx.shadowBlur (and adjust color alpha
if needed) so shadows respect the global export controls; keep the existing
roundRect/clip logic but guard and modify preset.shadow usage accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e239b469-c530-4024-b266-891ebe729e80

📥 Commits

Reviewing files that changed from the base of the PR and between c84c244 and 6236d2a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • src/lib/exporter/frameRenderer.ts
  • src/lib/requestCameraAccess.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/requestCameraAccess.ts

Comment on lines +648 to 664
const preset = getWebcamLayoutPresetDefinition(this.config.webcamLayoutPreset);
ctx.save();
ctx.beginPath();
ctx.roundRect(
webcamRect.x,
webcamRect.y,
webcamRect.width,
webcamRect.height,
webcamRect.borderRadius,
);
ctx.closePath();
if (preset.shadow) {
ctx.shadowColor = preset.shadow.color;
ctx.shadowBlur = preset.shadow.blur;
ctx.shadowOffsetX = preset.shadow.offsetX;
ctx.shadowOffsetY = preset.shadow.offsetY;
}
Copy link

@coderabbitai coderabbitai bot Mar 19, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Webcam preset shadows ignore the export shadow controls.

This branch applies preset.shadow even when showShadow is false or shadowIntensity is 0, so exports can still show a webcam shadow after shadows are disabled in Video Effects.

💡 Suggested fix
-			if (preset.shadow) {
+			if (this.config.showShadow && this.config.shadowIntensity > 0 && preset.shadow) {
 				ctx.shadowColor = preset.shadow.color;
 				ctx.shadowBlur = preset.shadow.blur;
 				ctx.shadowOffsetX = preset.shadow.offsetX;
 				ctx.shadowOffsetY = preset.shadow.offsetY;
 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const preset = getWebcamLayoutPresetDefinition(this.config.webcamLayoutPreset);
ctx.save();
ctx.beginPath();
ctx.roundRect(
webcamRect.x,
webcamRect.y,
webcamRect.width,
webcamRect.height,
webcamRect.borderRadius,
);
ctx.closePath();
if (preset.shadow) {
ctx.shadowColor = preset.shadow.color;
ctx.shadowBlur = preset.shadow.blur;
ctx.shadowOffsetX = preset.shadow.offsetX;
ctx.shadowOffsetY = preset.shadow.offsetY;
}
const preset = getWebcamLayoutPresetDefinition(this.config.webcamLayoutPreset);
ctx.save();
ctx.beginPath();
ctx.roundRect(
webcamRect.x,
webcamRect.y,
webcamRect.width,
webcamRect.height,
webcamRect.borderRadius,
);
ctx.closePath();
if (this.config.showShadow && this.config.shadowIntensity > 0 && preset.shadow) {
ctx.shadowColor = preset.shadow.color;
ctx.shadowBlur = preset.shadow.blur;
ctx.shadowOffsetX = preset.shadow.offsetX;
ctx.shadowOffsetY = preset.shadow.offsetY;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/exporter/frameRenderer.ts` around lines 648 - 664, The preset shadow
is being applied unconditionally; update the block around
getWebcamLayoutPresetDefinition(this.config.webcamLayoutPreset) so that you only
set ctx.shadowColor/blur/offsetX/offsetY when the export shadow controls allow
it — e.g., check this.config.showShadow is true and this.config.shadowIntensity
> 0 before applying preset.shadow, and scale preset.shadow.blur/intensity by
this.config.shadowIntensity when setting ctx.shadowBlur (and adjust color alpha
if needed) so shadows respect the global export controls; keep the existing
roundRect/clip logic but guard and modify preset.shadow usage accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@siddharthvaddem i think we should keep shadows (and the other video effects) separate for the webcam, so i think it's still ok to keep it as is for now. later we could have "Video Effects" becoming "Screen Effects" and a dedicated "Webcam Effects"

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@siddharthvaddem siddharthvaddem merged commit 3eeecc4 into siddharthvaddem:main Mar 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants