feat(extensions): add click-ripple cursor-effect example#412
feat(extensions): add click-ripple cursor-effect example#412willytop8 wants to merge 1 commit intowebadderallorg:mainfrom
Conversation
Adds a packaged example extension demonstrating registerCursorEffect() with three switchable styles (ripple, pulse, burst) and a settings panel nested under the Cursor section. Also adds a one-line entry to the Examples section of EXTENSIONS.md.
📝 WalkthroughWalkthroughThis PR adds a complete "Click Ripple" extension example to the ChangesClick Ripple Extension Example
Sequence DiagramsequenceDiagram
participant Recordly as Recordly Engine
participant Ext as Extension (activate)
participant API as Recordly Extension API
participant Settings as Settings Panel
participant Canvas as Canvas/Drawing
Recordly->>Ext: Load Extension
Ext->>API: registerSettingsPanel("Click Effects")
API->>Settings: Register fields (style, color, size, duration, etc.)
Ext->>API: registerCursorEffect(callback)
API->>Canvas: Store effect callback
Note over Recordly: User clicks in preview
Recordly->>Canvas: Draw frame at timeMs
Canvas->>API: Get cursor state & settings
API->>Settings: Fetch current style, color, size, duration
Canvas->>Canvas: Call cursor effect callback(ctx)
Canvas->>Canvas: Compute progress & right-click state
Canvas->>Canvas: Transform coordinates via sceneTransform
Canvas->>Canvas: Select style (ripple/pulse/burst)
Canvas->>Canvas: Draw effect with fade based on progress
Canvas->>Recordly: Return to frame rendering
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Review rate limit: 8/10 reviews remaining, refill in 8 minutes and 48 seconds. Comment |
|
|
1 similar comment
|
|
There was a problem hiding this comment.
🧹 Nitpick comments (2)
extension-examples/willytop8.click-ripple/src/index.ts (1)
36-41: ⚡ Quick winNormalize/clamp setting values before using them in render math.
getSetting()returnsunknown; direct casts here can propagate invalid values (e.g., string/NaN/out-of-range) intoprogress, radii, and alpha computations. Add typed parsing with bounds to keep rendering deterministic.Proposed patch
+ const readNumber = (key: string, fallback: number, min: number, max: number) => { + const raw = api.getSetting(key); + const n = typeof raw === "number" ? raw : Number(raw); + if (!Number.isFinite(n)) return fallback; + return Math.min(max, Math.max(min, n)); + }; + + const readBool = (key: string, fallback: boolean) => { + const raw = api.getSetting(key); + return typeof raw === "boolean" ? raw : fallback; + }; + - const size = (api.getSetting("size") as number) ?? 1.0; - const durationMs = (api.getSetting("durationMs") as number) ?? 600; - const thickness = (api.getSetting("thickness") as number) ?? 2; - const differentiateRC = (api.getSetting("differentiateRightClick") as boolean) ?? true; + const size = readNumber("size", 1.0, 0.5, 2.5); + const durationMs = readNumber("durationMs", 600, 200, 1500); + const thickness = readNumber("thickness", 2, 1, 8); + const differentiateRC = readBool("differentiateRightClick", true);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@extension-examples/willytop8.click-ripple/src/index.ts` around lines 36 - 41, The settings are cast directly from unknown and can be invalid; validate and normalize each setting before use: read raw values from api.getSetting for style, color, size, durationMs, thickness, and differentiateRightClick, then coerce/parse them (e.g., parseFloat for numbers, normalize hex/color strings for color, ensure style is one of allowed enums) and clamp numeric values to safe ranges (e.g., size > 0 and within a sensible min/max, durationMs positive, thickness non-negative) and guard against NaN by falling back to the current defaults; update the variables style, color, size, durationMs, thickness, and differentiateRC in index.ts with these validated values so downstream math (progress, radii, alpha) always gets deterministic, typed inputs.extension-examples/willytop8.click-ripple/build.mjs (1)
6-9: ⚡ Quick winMake the deploy destination configurable instead of macOS-only.
This hardcoded path only matches one local setup and can diverge from Recordly’s actual install location (
electron/extensions/extensionLoader.ts:29-33resolves viaapp.getPath("userData")/extensions). Prefer an env-overridable base path so contributors on other platforms can use the script reliably.Proposed patch
-const INSTALLED = join( - homedir(), - "Library/Application Support/Recordly/extensions/recordly-click-ripple/dist/index.js", -); +const EXTENSIONS_DIR = + process.env.RECORDLY_EXTENSIONS_DIR ?? + join(homedir(), "Library", "Application Support", "Recordly", "extensions"); + +const INSTALLED = join( + EXTENSIONS_DIR, + "recordly-click-ripple", + "dist", + "index.js", +);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@extension-examples/willytop8.click-ripple/build.mjs` around lines 6 - 9, The INSTALLED constant is hardcoded to a macOS-only path; make the deploy destination configurable by reading an environment variable (e.g., RECORDLY_EXTENSIONS_DIR or RECORDLY_USER_DATA) and falling back to a sensible cross-platform default based on os.platform() instead of homedir() alone. Update the code that builds INSTALLED (the join(...) expression that currently uses homedir()) to: 1) require('os')/require('path'), 2) compute a baseDir = process.env.RECORDLY_EXTENSIONS_DIR || platform-specific default (use process.env.APPDATA on win32, process.env.XDG_DATA_HOME or path.join(os.homedir(), '.config') on linux, and the existing Library/Application Support/... on darwin), and 3) set INSTALLED = join(baseDir, 'extensions', 'recordly-click-ripple', 'dist', 'index.js') so contributors on other platforms can override with an env var.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@extension-examples/willytop8.click-ripple/build.mjs`:
- Around line 6-9: The INSTALLED constant is hardcoded to a macOS-only path;
make the deploy destination configurable by reading an environment variable
(e.g., RECORDLY_EXTENSIONS_DIR or RECORDLY_USER_DATA) and falling back to a
sensible cross-platform default based on os.platform() instead of homedir()
alone. Update the code that builds INSTALLED (the join(...) expression that
currently uses homedir()) to: 1) require('os')/require('path'), 2) compute a
baseDir = process.env.RECORDLY_EXTENSIONS_DIR || platform-specific default (use
process.env.APPDATA on win32, process.env.XDG_DATA_HOME or
path.join(os.homedir(), '.config') on linux, and the existing
Library/Application Support/... on darwin), and 3) set INSTALLED = join(baseDir,
'extensions', 'recordly-click-ripple', 'dist', 'index.js') so contributors on
other platforms can override with an env var.
In `@extension-examples/willytop8.click-ripple/src/index.ts`:
- Around line 36-41: The settings are cast directly from unknown and can be
invalid; validate and normalize each setting before use: read raw values from
api.getSetting for style, color, size, durationMs, thickness, and
differentiateRightClick, then coerce/parse them (e.g., parseFloat for numbers,
normalize hex/color strings for color, ensure style is one of allowed enums) and
clamp numeric values to safe ranges (e.g., size > 0 and within a sensible
min/max, durationMs positive, thickness non-negative) and guard against NaN by
falling back to the current defaults; update the variables style, color, size,
durationMs, thickness, and differentiateRC in index.ts with these validated
values so downstream math (progress, radii, alpha) always gets deterministic,
typed inputs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 43cc96ad-9ee5-422b-b68a-bd47f878fa1b
⛔ Files ignored due to path filters (6)
extension-examples/willytop8.click-ripple/dist/index.jsis excluded by!**/dist/**extension-examples/willytop8.click-ripple/package-lock.jsonis excluded by!**/package-lock.jsonextension-examples/willytop8.click-ripple/screenshots/burst-style.pngis excluded by!**/*.pngextension-examples/willytop8.click-ripple/screenshots/pulse-style.pngis excluded by!**/*.pngextension-examples/willytop8.click-ripple/screenshots/ripple-style.pngis excluded by!**/*.pngextension-examples/willytop8.click-ripple/screenshots/settings-panel.pngis excluded by!**/*.png
📒 Files selected for processing (10)
EXTENSIONS.mdextension-examples/willytop8.click-ripple/.gitignoreextension-examples/willytop8.click-ripple/LICENSEextension-examples/willytop8.click-ripple/README.mdextension-examples/willytop8.click-ripple/build.mjsextension-examples/willytop8.click-ripple/package.jsonextension-examples/willytop8.click-ripple/recordly-extension.jsonextension-examples/willytop8.click-ripple/src/index.tsextension-examples/willytop8.click-ripple/src/recordly-types.d.tsextension-examples/willytop8.click-ripple/tsconfig.json
What this adds
A new example extension under
extension-examples/willytop8.click-ripple/that renders animated effects at every cursor click — ripple, pulse, or burst — usingregisterCursorEffect(). Settings panel is nested under the existing Cursor section viaparentSection: "cursor".One-line entry added to the
## Examplessection ofEXTENSIONS.md.Why
The existing example (
webadderall.more-wallpapers) only covers asset registration. There's nothing showing how to use the cursor APIs. This fills that gap —registerCursorEffect,CursorEffectContext, coordinate handling withsceneTransform, and settings panel nesting are all demonstrated in a single readable file.The extension is also published standalone at https://github.com/willytop8/recordly-click-ripple so it can be installed and tested independently.
Changes
extension-examples/willytop8.click-ripple/— full extension (manifest, TypeScript source, compiled bundle, screenshots, README, MIT license)EXTENSIONS.md— one-line addition under## ExamplesScreenshots
Settings panel nested under Cursor:
Ripple:
Pulse:
Burst:
Testing
extension-examples/willytop8.click-ripple/into your Recordly extensions directory (Extensions → Open Directory).Notes
cursoranduionly — no core APIs touched.videoLayout.maskRect.width, not canvas width, so it's resolution-independent.sceneTransformdivision is guarded against zero/non-finite scale.Summary by CodeRabbit
Release Notes
New Features
Documentation